mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-10 01:33:53 +00:00
Added url::Get interface
This commit is contained in:
parent
2b7a968468
commit
da26b517a3
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@ tags
|
|||||||
example/server
|
example/server
|
||||||
example/client
|
example/client
|
||||||
example/hello
|
example/hello
|
||||||
|
example/simplecli
|
||||||
example/simplesvr
|
example/simplesvr
|
||||||
example/benchmark
|
example/benchmark
|
||||||
example/redirect
|
example/redirect
|
||||||
|
@ -5,7 +5,7 @@ OPENSSL_DIR = /usr/local/opt/openssl
|
|||||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
||||||
|
|
||||||
all: server client hello simplesvr upload redirect sse benchmark
|
all: server client hello simplecli simplesvr upload redirect sse benchmark
|
||||||
|
|
||||||
server : server.cc ../httplib.h Makefile
|
server : server.cc ../httplib.h Makefile
|
||||||
$(CXX) -o server $(CXXFLAGS) server.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
$(CXX) -o server $(CXXFLAGS) server.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||||
@ -16,6 +16,9 @@ client : client.cc ../httplib.h Makefile
|
|||||||
hello : hello.cc ../httplib.h Makefile
|
hello : hello.cc ../httplib.h Makefile
|
||||||
$(CXX) -o hello $(CXXFLAGS) hello.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
$(CXX) -o hello $(CXXFLAGS) hello.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||||
|
|
||||||
|
simplecli : simplecli.cc ../httplib.h Makefile
|
||||||
|
$(CXX) -o simplecli $(CXXFLAGS) simplecli.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||||
|
|
||||||
simplesvr : simplesvr.cc ../httplib.h Makefile
|
simplesvr : simplesvr.cc ../httplib.h Makefile
|
||||||
$(CXX) -o simplesvr $(CXXFLAGS) simplesvr.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
$(CXX) -o simplesvr $(CXXFLAGS) simplesvr.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||||
|
|
||||||
@ -36,4 +39,4 @@ pem:
|
|||||||
openssl req -new -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem
|
openssl req -new -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm server client hello simplesvr upload redirect sse benchmark *.pem
|
rm server client hello simplecli simplesvr upload redirect sse benchmark *.pem
|
||||||
|
@ -15,5 +15,5 @@ int main(void) {
|
|||||||
res.set_content("Hello World!", "text/plain");
|
res.set_content("Hello World!", "text/plain");
|
||||||
});
|
});
|
||||||
|
|
||||||
svr.listen("localhost", 1234);
|
svr.listen("localhost", 8080);
|
||||||
}
|
}
|
||||||
|
33
example/simplecli.cc
Normal file
33
example/simplecli.cc
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// simplecli.cc
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 Yuji Hirose. All rights reserved.
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <httplib.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define CA_CERT_FILE "./ca-bundle.crt"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
httplib::url::Options options;
|
||||||
|
options.ca_cert_file_path = CA_CERT_FILE;
|
||||||
|
// options.server_certificate_verification = true;
|
||||||
|
|
||||||
|
auto res = httplib::url::Get("https://localhost:8080/hi", options);
|
||||||
|
#else
|
||||||
|
auto res = httplib::url::Get("http://localhost:8080/hi");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
cout << res->status << endl;
|
||||||
|
cout << res->get_header_value("Content-Type") << endl;
|
||||||
|
cout << res->body << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
61
httplib.h
61
httplib.h
@ -3885,10 +3885,10 @@ inline bool Client::redirect(const Request &req, Response &res) {
|
|||||||
if (location.empty()) { return false; }
|
if (location.empty()) { return false; }
|
||||||
|
|
||||||
const static std::regex re(
|
const static std::regex re(
|
||||||
R"(^(?:(https?):)?(?://([^/?#]*)(?:(:\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)");
|
R"(^(?:(https?):)?(?://([^:/?#]*)(?::(\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)");
|
||||||
|
|
||||||
std::smatch m;
|
std::smatch m;
|
||||||
if (!regex_match(location, m, re)) { return false; }
|
if (!std::regex_match(location, m, re)) { return false; }
|
||||||
|
|
||||||
auto scheme = is_ssl() ? "https" : "http";
|
auto scheme = is_ssl() ? "https" : "http";
|
||||||
|
|
||||||
@ -4967,6 +4967,63 @@ inline bool SSLClient::check_host_name(const char *pattern,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace url {
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
// TODO: support more options...
|
||||||
|
bool follow_location = false;
|
||||||
|
std::string client_cert_path;
|
||||||
|
std::string client_key_path;
|
||||||
|
|
||||||
|
std::string ca_cert_file_path;
|
||||||
|
std::string ca_cert_dir_path;
|
||||||
|
bool server_certificate_verification = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::shared_ptr<Response> Get(const char *url, Options &options) {
|
||||||
|
const static std::regex re(
|
||||||
|
R"(^(https?)://([^:/?#]+)(?::(\d+))?([^?#]*(?:\?[^#]*)?)(?:#.*)?)");
|
||||||
|
|
||||||
|
std::cmatch m;
|
||||||
|
if (!std::regex_match(url, m, re)) { return nullptr; }
|
||||||
|
|
||||||
|
auto next_scheme = m[1].str();
|
||||||
|
auto next_host = m[2].str();
|
||||||
|
auto port_str = m[3].str();
|
||||||
|
auto next_path = m[4].str();
|
||||||
|
|
||||||
|
auto next_port = !port_str.empty() ? std::stoi(port_str)
|
||||||
|
: (next_scheme == "https" ? 443 : 80);
|
||||||
|
|
||||||
|
if (next_path.empty()) { next_path = "/"; }
|
||||||
|
|
||||||
|
if (next_scheme == "https") {
|
||||||
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
SSLClient cli(next_host.c_str(), next_port, options.client_cert_path,
|
||||||
|
options.client_key_path);
|
||||||
|
cli.set_follow_location(options.follow_location);
|
||||||
|
cli.set_ca_cert_path(options.ca_cert_file_path.c_str(), options.ca_cert_dir_path.c_str());
|
||||||
|
cli.enable_server_certificate_verification(
|
||||||
|
options.server_certificate_verification);
|
||||||
|
return cli.Get(next_path.c_str());
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
Client cli(next_host.c_str(), next_port, options.client_cert_path,
|
||||||
|
options.client_key_path);
|
||||||
|
cli.set_follow_location(options.follow_location);
|
||||||
|
return cli.Get(next_path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<Response> Get(const char *url) {
|
||||||
|
Options options;
|
||||||
|
return Get(url, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace url
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
} // namespace httplib
|
} // namespace httplib
|
||||||
|
55
test/test.cc
55
test/test.cc
@ -654,7 +654,7 @@ TEST(YahooRedirectTestWithURL, Redirect) {
|
|||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(301, res->status);
|
EXPECT_EQ(301, res->status);
|
||||||
|
|
||||||
httplib::url::options options;
|
httplib::url::Options options;
|
||||||
options.follow_location = true;
|
options.follow_location = true;
|
||||||
|
|
||||||
res = httplib::url::Get("http://yahoo.com", options);
|
res = httplib::url::Get("http://yahoo.com", options);
|
||||||
@ -669,6 +669,59 @@ TEST(HttpsToHttpRedirectTest, Redirect) {
|
|||||||
cli.Get("/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
|
cli.Get("/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(HttpsToHttpRedirectTestWithURL, Redirect) {
|
||||||
|
httplib::url::Options options;
|
||||||
|
options.follow_location = true;
|
||||||
|
|
||||||
|
auto res = httplib::url::Get(
|
||||||
|
"https://httpbin.org/"
|
||||||
|
"redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
|
||||||
|
ASSERT_TRUE(res != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RedirectToDifferentPort, Redirect) {
|
||||||
|
Server svr8080;
|
||||||
|
Server svr8081;
|
||||||
|
|
||||||
|
svr8080.Get("/1", [&](const Request & /*req*/, Response &res) {
|
||||||
|
res.set_redirect("http://localhost:8081/2");
|
||||||
|
});
|
||||||
|
|
||||||
|
svr8081.Get("/2", [&](const Request & /*req*/, Response &res) {
|
||||||
|
res.set_content("Hello World!", "text/plain");
|
||||||
|
});
|
||||||
|
|
||||||
|
auto thread8080 = std::thread([&]() {
|
||||||
|
svr8080.listen("localhost", 8080);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto thread8081 = std::thread([&]() {
|
||||||
|
svr8081.listen("localhost", 8081);
|
||||||
|
});
|
||||||
|
|
||||||
|
while (!svr8080.is_running() || !svr8081.is_running()) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give GET time to get a few messages.
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
|
||||||
|
Client cli("localhost", 8080);
|
||||||
|
cli.set_follow_location(true);
|
||||||
|
|
||||||
|
auto res = cli.Get("/1");
|
||||||
|
ASSERT_TRUE(res != nullptr);
|
||||||
|
EXPECT_EQ(200, res->status);
|
||||||
|
EXPECT_EQ(res->body, "Hello World!");
|
||||||
|
|
||||||
|
svr8080.stop();
|
||||||
|
svr8081.stop();
|
||||||
|
thread8080.join();
|
||||||
|
thread8081.join();
|
||||||
|
ASSERT_FALSE(svr8080.is_running());
|
||||||
|
ASSERT_FALSE(svr8081.is_running());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(Server, BindAndListenSeparately) {
|
TEST(Server, BindAndListenSeparately) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user