Skip to content

Commit 51494a2

Browse files
authored
fix server (#545)
1 parent 2ced3a1 commit 51494a2

File tree

5 files changed

+73
-52
lines changed

5 files changed

+73
-52
lines changed

include/cinatra/coro_http_request.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ class coro_http_request {
127127

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

130+
std::string_view full_url() { return parser_.full_url(); }
131+
130132
void set_body(std::string &body) {
131133
body_ = body;
132134
auto type = get_content_type();

include/cinatra/coro_http_server.hpp

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,20 @@ class coro_http_server {
6969
#endif
7070

7171
// only call once, not thread safe.
72-
std::errc sync_start() noexcept {
72+
std::error_code sync_start() noexcept {
7373
auto ret = async_start();
7474
ret.wait();
7575
return ret.value();
7676
}
7777

7878
// only call once, not thread safe.
79-
async_simple::Future<std::errc> async_start() {
79+
async_simple::Future<std::error_code> async_start() {
8080
errc_ = listen();
8181

82-
async_simple::Promise<std::errc> promise;
82+
async_simple::Promise<std::error_code> promise;
8383
auto future = promise.getFuture();
8484

85-
if (errc_ == std::errc{}) {
85+
if (!errc_) {
8686
if (out_ctx_ == nullptr) {
8787
thd_ = std::thread([this] {
8888
pool_->run();
@@ -91,7 +91,7 @@ class coro_http_server {
9191

9292
accept().start([p = std::move(promise), this](auto &&res) mutable {
9393
if (res.hasError()) {
94-
errc_ = std::errc::io_error;
94+
errc_ = std::make_error_code(std::errc::io_error);
9595
p.setValue(errc_);
9696
}
9797
else {
@@ -196,16 +196,14 @@ class coro_http_server {
196196
coro_io::channel<coro_http_client>::create(hosts, {.lba = type},
197197
weights));
198198
auto handler =
199-
[this, channel, type, url_path](
199+
[this, channel, type](
200200
coro_http_request &req,
201201
coro_http_response &response) -> async_simple::coro::Lazy<void> {
202202
co_await channel->send_request(
203203
[this, &req, &response](
204204
coro_http_client &client,
205205
std::string_view host) -> async_simple::coro::Lazy<void> {
206-
uri_t uri;
207-
uri.parse_from(host.data());
208-
co_await reply(client, uri.get_path(), req, response);
206+
co_await reply(client, host, req, response);
209207
});
210208
};
211209

@@ -503,10 +501,10 @@ class coro_http_server {
503501
}
504502

505503
std::string_view address() { return address_; }
506-
std::errc get_errc() { return errc_; }
504+
std::error_code get_errc() { return errc_; }
507505

508506
private:
509-
std::errc listen() {
507+
std::error_code listen() {
510508
CINATRA_LOG_INFO << "begin to listen";
511509
using asio::ip::tcp;
512510
asio::error_code ec;
@@ -519,25 +517,29 @@ class coro_http_server {
519517
if (ec || it == it_end) {
520518
CINATRA_LOG_ERROR << "bad address: " << address_
521519
<< " error: " << ec.message();
522-
return std::errc::bad_address;
520+
if (ec) {
521+
return ec;
522+
}
523+
return std::make_error_code(std::errc::address_not_available);
523524
}
524525

525526
auto endpoint = it->endpoint();
526527
acceptor_.open(endpoint.protocol(), ec);
527528
if (ec) {
528529
CINATRA_LOG_ERROR << "acceptor open failed"
529530
<< " error: " << ec.message();
530-
return std::errc::io_error;
531+
return ec;
531532
}
532533
#ifdef __GNUC__
533534
acceptor_.set_option(tcp::acceptor::reuse_address(true), ec);
534535
#endif
535536
acceptor_.bind(endpoint, ec);
536537
if (ec) {
537538
CINATRA_LOG_ERROR << "bind port: " << port_ << " error: " << ec.message();
538-
acceptor_.cancel(ec);
539-
acceptor_.close(ec);
540-
return std::errc::address_in_use;
539+
std::error_code ignore_ec;
540+
acceptor_.cancel(ignore_ec);
541+
acceptor_.close(ignore_ec);
542+
return ec;
541543
}
542544
#ifdef _MSC_VER
543545
acceptor_.set_option(tcp::acceptor::reuse_address(true));
@@ -546,22 +548,22 @@ class coro_http_server {
546548
if (ec) {
547549
CINATRA_LOG_ERROR << "get local endpoint port: " << port_
548550
<< " listen error: " << ec.message();
549-
return std::errc::io_error;
551+
return ec;
550552
}
551553

552554
auto end_point = acceptor_.local_endpoint(ec);
553555
if (ec) {
554556
CINATRA_LOG_ERROR << "get local endpoint port: " << port_
555557
<< " error: " << ec.message();
556-
return std::errc::address_in_use;
558+
return ec;
557559
}
558560
port_ = end_point.port();
559561

560562
CINATRA_LOG_INFO << "listen port " << port_ << " successfully";
561563
return {};
562564
}
563565

564-
async_simple::coro::Lazy<std::errc> accept() {
566+
async_simple::coro::Lazy<std::error_code> accept() {
565567
for (;;) {
566568
coro_io::ExecutorWrapper<> *executor;
567569
if (out_ctx_ == nullptr) {
@@ -580,7 +582,7 @@ class coro_http_server {
580582
if (error == asio::error::operation_aborted ||
581583
error == asio::error::bad_descriptor) {
582584
acceptor_close_waiter_.set_value();
583-
co_return std::errc::operation_canceled;
585+
co_return error;
584586
}
585587
continue;
586588
}
@@ -765,17 +767,28 @@ class coro_http_server {
765767
}
766768

767769
async_simple::coro::Lazy<void> reply(coro_http_client &client,
768-
std::string url_path,
770+
std::string_view host,
769771
coro_http_request &req,
770772
coro_http_response &response) {
773+
uri_t uri;
774+
std::string proxy_host;
775+
776+
if (host.find("//") == std::string_view::npos) {
777+
proxy_host.append("http://").append(host);
778+
uri.parse_from(proxy_host.data());
779+
}
780+
else {
781+
uri.parse_from(host.data());
782+
}
771783
std::unordered_map<std::string, std::string> req_headers;
772-
for (auto &[k, v] : req_headers) {
784+
for (auto &[k, v] : req.get_headers()) {
773785
req_headers.emplace(k, v);
774786
}
787+
req_headers["Host"] = uri.host;
775788

776789
auto ctx = req_context<std::string_view>{.content = req.get_body()};
777790
auto result = co_await client.async_request(
778-
std::move(url_path), method_type(req.get_method()), std::move(ctx),
791+
req.full_url(), method_type(req.get_method()), std::move(ctx),
779792
std::move(req_headers));
780793

781794
for (auto &[k, v] : result.resp_headers) {
@@ -789,6 +802,8 @@ class coro_http_server {
789802
}
790803

791804
void init_address(std::string address) {
805+
CINATRA_LOG_ERROR << "init log"; // init easylog singleton to make sure
806+
// server destruct before easylog.
792807
if (size_t pos = address.find(':'); pos != std::string::npos) {
793808
auto port_sv = std::string_view(address).substr(pos + 1);
794809

@@ -813,7 +828,7 @@ class coro_http_server {
813828
std::unique_ptr<coro_io::ExecutorWrapper<>> out_executor_ = nullptr;
814829
uint16_t port_;
815830
std::string address_;
816-
std::errc errc_ = {};
831+
std::error_code errc_ = {};
817832
asio::ip::tcp::acceptor acceptor_;
818833
std::thread thd_;
819834
std::promise<void> acceptor_close_waiter_;

include/cinatra/http_parser.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class http_parser {
100100
}
101101
}
102102

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

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

129+
std::string_view full_url() { return full_url_; }
130+
128131
std::string_view get_query_value(std::string_view key) {
129132
if (auto it = queries_.find(key); it != queries_.end()) {
130133
return it->second;
@@ -270,6 +273,7 @@ class http_parser {
270273
std::array<http_header, CINATRA_MAX_HTTP_HEADER_FIELD_SIZE> headers_;
271274
std::string_view method_;
272275
std::string_view url_;
276+
std::string_view full_url_;
273277
std::unordered_map<std::string_view, std::string_view> queries_;
274278
};
275279
} // namespace cinatra

tests/test_cinatra.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,56 +322,56 @@ TEST_CASE("test bad address") {
322322
coro_http_server server(1, 9001, "127.0.0.1");
323323
server.async_start();
324324
auto ec = server.get_errc();
325-
CHECK(ec == std::errc{});
325+
CHECK(!ec);
326326
}
327327
{
328328
coro_http_server server(1, 9001, "localhost");
329329
server.async_start();
330330
auto ec = server.get_errc();
331-
CHECK(ec == std::errc{});
331+
CHECK(!ec);
332332
}
333333
{
334334
coro_http_server server(1, 9001, "0.0.0.0");
335335
server.async_start();
336336
auto ec = server.get_errc();
337-
CHECK(ec == std::errc{});
337+
CHECK(!ec);
338338
}
339339
{
340340
coro_http_server server(1, 9001);
341341
server.async_start();
342342
auto ec = server.get_errc();
343-
CHECK(ec == std::errc{});
343+
CHECK(!ec);
344344
}
345345
{
346346
coro_http_server server(1, "0.0.0.0:9001");
347347
server.async_start();
348348
auto ec = server.get_errc();
349-
CHECK(ec == std::errc{});
349+
CHECK(!ec);
350350
}
351351
{
352352
coro_http_server server(1, "127.0.0.1:9001");
353353
server.async_start();
354354
auto ec = server.get_errc();
355-
CHECK(ec == std::errc{});
355+
CHECK(!ec);
356356
}
357357
{
358358
coro_http_server server(1, "localhost:9001");
359359
server.async_start();
360360
auto ec = server.get_errc();
361-
CHECK(ec == std::errc{});
361+
CHECK(!ec);
362362
}
363363

364364
{
365365
coro_http_server server(1, 9001, "x.x.x.x");
366366
server.async_start();
367367
auto ec = server.get_errc();
368-
CHECK(ec == std::errc::bad_address);
368+
CHECK(ec);
369369
}
370370
{
371371
coro_http_server server(1, "localhost:aaa");
372372
server.async_start();
373373
auto ec = server.get_errc();
374-
CHECK(ec == std::errc::bad_address);
374+
CHECK(ec);
375375
}
376376
}
377377

tests/test_coro_http_server.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -391,14 +391,14 @@ TEST_CASE("test server start and stop") {
391391
auto future2 = server2.async_start();
392392
future2.wait();
393393
auto ec = future2.value();
394-
CHECK(ec == std::errc::address_in_use);
394+
CHECK(ec == asio::error::address_in_use);
395395
}
396396

397397
TEST_CASE("test server sync_start and stop") {
398398
cinatra::coro_http_server server(1, 0);
399399

400400
std::promise<void> promise;
401-
std::errc ec;
401+
std::error_code ec;
402402
std::thread thd([&] {
403403
promise.set_value();
404404
ec = server.sync_start();
@@ -408,7 +408,7 @@ TEST_CASE("test server sync_start and stop") {
408408
server.stop();
409409
thd.join();
410410
CHECK(server.port() > 0);
411-
CHECK(ec == std::errc::operation_canceled);
411+
CHECK(ec == asio::error::operation_aborted);
412412
}
413413

414414
TEST_CASE("get post") {
@@ -1532,21 +1532,21 @@ TEST_CASE("test reverse proxy") {
15321532

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

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

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

15471547
coro_http_server proxy_all(2, 8093);
15481548
proxy_all.set_http_proxy_handler(
1549-
"/all", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"});
1549+
"/", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"});
15501550

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

15581558
coro_http_client client_rr;
1559-
resp_data resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
1559+
resp_data resp_rr = client_rr.get("http://127.0.0.1:8091/");
15601560
CHECK(resp_rr.resp_body == "web1");
1561-
resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
1561+
resp_rr = client_rr.get("http://127.0.0.1:8091/");
15621562
CHECK(resp_rr.resp_body == "web2");
1563-
resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
1563+
resp_rr = client_rr.get("http://127.0.0.1:8091/");
15641564
CHECK(resp_rr.resp_body == "web3");
1565-
resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
1565+
resp_rr = client_rr.get("http://127.0.0.1:8091/");
15661566
CHECK(resp_rr.resp_body == "web1");
1567-
resp_rr = client_rr.get("http://127.0.0.1:8091/rr");
1567+
resp_rr = client_rr.get("http://127.0.0.1:8091/");
15681568
CHECK(resp_rr.resp_body == "web2");
1569-
resp_rr = client_rr.post("http://127.0.0.1:8091/rr", "test content",
1569+
resp_rr = client_rr.post("http://127.0.0.1:8091/", "test content",
15701570
req_content_type::text);
15711571
CHECK(resp_rr.resp_body == "web3");
15721572

15731573
coro_http_client client_wrr;
1574-
resp_data resp = client_wrr.get("http://127.0.0.1:8090/wrr");
1574+
resp_data resp = client_wrr.get("http://127.0.0.1:8090/");
15751575
CHECK(resp.resp_body == "web1");
1576-
resp = client_wrr.get("http://127.0.0.1:8090/wrr");
1576+
resp = client_wrr.get("http://127.0.0.1:8090/");
15771577
CHECK(resp.resp_body == "web1");
1578-
resp = client_wrr.get("http://127.0.0.1:8090/wrr");
1578+
resp = client_wrr.get("http://127.0.0.1:8090/");
15791579
CHECK(resp.resp_body == "web2");
1580-
resp = client_wrr.get("http://127.0.0.1:8090/wrr");
1580+
resp = client_wrr.get("http://127.0.0.1:8090/");
15811581
CHECK(resp.resp_body == "web3");
15821582

15831583
coro_http_client client_random;
1584-
resp_data resp_random = client_random.get("http://127.0.0.1:8092/random");
1584+
resp_data resp_random = client_random.get("http://127.0.0.1:8092/");
15851585
std::cout << resp_random.resp_body << "\n";
15861586
CHECK(!resp_random.resp_body.empty());
15871587

15881588
coro_http_client client_all;
1589-
resp_random = client_all.post("http://127.0.0.1:8093/all", "test content",
1589+
resp_random = client_all.post("http://127.0.0.1:8093/", "test content",
15901590
req_content_type::text);
15911591
std::cout << resp_random.resp_body << "\n";
15921592
CHECK(!resp_random.resp_body.empty());

0 commit comments

Comments
 (0)