Skip to content

Commit

Permalink
fix reverse proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos committed Apr 7, 2024
1 parent 0d65efe commit 9a8941d
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 23 deletions.
2 changes: 2 additions & 0 deletions include/cinatra/coro_http_request.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ class coro_http_request {

const auto &get_queries() const { return parser_.queries(); }

std::string_view full_url() { return parser_.full_url(); }

void set_body(std::string &body) {
body_ = body;
auto type = get_content_type();
Expand Down
23 changes: 16 additions & 7 deletions include/cinatra/coro_http_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,16 +196,14 @@ class coro_http_server {
coro_io::channel<coro_http_client>::create(hosts, {.lba = type},
weights));
auto handler =
[this, channel, type, url_path](
[this, channel, type](
coro_http_request &req,
coro_http_response &response) -> async_simple::coro::Lazy<void> {
co_await channel->send_request(
[this, &req, &response](
coro_http_client &client,
std::string_view host) -> async_simple::coro::Lazy<void> {
uri_t uri;
uri.parse_from(host.data());
co_await reply(client, uri.get_path(), req, response);
co_await reply(client, host, req, response);
});
};

Expand Down Expand Up @@ -769,17 +767,28 @@ class coro_http_server {
}

async_simple::coro::Lazy<void> reply(coro_http_client &client,
std::string url_path,
std::string_view host,
coro_http_request &req,
coro_http_response &response) {
uri_t uri;
std::string proxy_host;

if (host.find("//") == std::string_view::npos) {
proxy_host.append("http://").append(host);
uri.parse_from(proxy_host.data());
}
else {
uri.parse_from(host.data());
}
std::unordered_map<std::string, std::string> req_headers;
for (auto &[k, v] : req_headers) {
for (auto &[k, v] : req.get_headers()) {
req_headers.emplace(k, v);
}
req_headers["Host"] = uri.host;

auto ctx = req_context<std::string_view>{.content = req.get_body()};
auto result = co_await client.async_request(
std::move(url_path), method_type(req.get_method()), std::move(ctx),
req.full_url(), method_type(req.get_method()), std::move(ctx),
std::move(req_headers));

for (auto &[k, v] : result.resp_headers) {
Expand Down
4 changes: 4 additions & 0 deletions include/cinatra/http_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class http_parser {
}
}

full_url_ = url_;
if (has_query) {
size_t pos = url_.find('?');
parse_query(url_.substr(pos + 1, url_len - pos - 1));
Expand All @@ -125,6 +126,8 @@ class http_parser {

const auto &queries() const { return queries_; }

std::string_view full_url() { return full_url_; }

std::string_view get_query_value(std::string_view key) {
if (auto it = queries_.find(key); it != queries_.end()) {
return it->second;
Expand Down Expand Up @@ -270,6 +273,7 @@ class http_parser {
std::array<http_header, CINATRA_MAX_HTTP_HEADER_FIELD_SIZE> headers_;
std::string_view method_;
std::string_view url_;
std::string_view full_url_;
std::unordered_map<std::string_view, std::string_view> queries_;
};
} // namespace cinatra
32 changes: 16 additions & 16 deletions tests/test_coro_http_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1532,21 +1532,21 @@ TEST_CASE("test reverse proxy") {

coro_http_server proxy_wrr(2, 8090);
proxy_wrr.set_http_proxy_handler<GET, POST>(
"/wrr", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"},
"/", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"},
coro_io::load_blance_algorithm::WRR, {10, 5, 5}, log_t{}, check_t{});

coro_http_server proxy_rr(2, 8091);
proxy_rr.set_http_proxy_handler<GET, POST>(
"/rr", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"},
"/", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"},
coro_io::load_blance_algorithm::RR, {}, log_t{});

coro_http_server proxy_random(2, 8092);
proxy_random.set_http_proxy_handler<GET, POST>(
"/random", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"});
"/", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"});

coro_http_server proxy_all(2, 8093);
proxy_all.set_http_proxy_handler(
"/all", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"});
"/", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"});

proxy_wrr.async_start();
proxy_rr.async_start();
Expand All @@ -1556,37 +1556,37 @@ TEST_CASE("test reverse proxy") {
std::this_thread::sleep_for(200ms);

coro_http_client client_rr;
resp_data resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
resp_data resp_rr = client_rr.get("http://127.0.0.1:8091/");
CHECK(resp_rr.resp_body == "web1");
resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
resp_rr = client_rr.get("http://127.0.0.1:8091/");
CHECK(resp_rr.resp_body == "web2");
resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
resp_rr = client_rr.get("http://127.0.0.1:8091/");
CHECK(resp_rr.resp_body == "web3");
resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
resp_rr = client_rr.get("http://127.0.0.1:8091/");
CHECK(resp_rr.resp_body == "web1");
resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
resp_rr = client_rr.get("http://127.0.0.1:8091/");
CHECK(resp_rr.resp_body == "web2");
resp_rr = client_rr.post("http://127.0.0.1:8091/rr", "test content",
resp_rr = client_rr.post("http://127.0.0.1:8091/", "test content",
req_content_type::text);
CHECK(resp_rr.resp_body == "web3");

coro_http_client client_wrr;
resp_data resp = client_wrr.get("http://127.0.0.1:8090/wrr");
resp_data resp = client_wrr.get("http://127.0.0.1:8090/");
CHECK(resp.resp_body == "web1");
resp = client_wrr.get("http://127.0.0.1:8090/wrr");
resp = client_wrr.get("http://127.0.0.1:8090/");
CHECK(resp.resp_body == "web1");
resp = client_wrr.get("http://127.0.0.1:8090/wrr");
resp = client_wrr.get("http://127.0.0.1:8090/");
CHECK(resp.resp_body == "web2");
resp = client_wrr.get("http://127.0.0.1:8090/wrr");
resp = client_wrr.get("http://127.0.0.1:8090/");
CHECK(resp.resp_body == "web3");

coro_http_client client_random;
resp_data resp_random = client_random.get("http://127.0.0.1:8092/random");
resp_data resp_random = client_random.get("http://127.0.0.1:8092/");
std::cout << resp_random.resp_body << "\n";
CHECK(!resp_random.resp_body.empty());

coro_http_client client_all;
resp_random = client_all.post("http://127.0.0.1:8093/all", "test content",
resp_random = client_all.post("http://127.0.0.1:8093/", "test content",
req_content_type::text);
std::cout << resp_random.resp_body << "\n";
CHECK(!resp_random.resp_body.empty());
Expand Down

0 comments on commit 9a8941d

Please sign in to comment.