Skip to content

Commit db90069

Browse files
authored
[coro_http][improve]support user response (#854)
1 parent 5d1a580 commit db90069

File tree

6 files changed

+133
-17
lines changed

6 files changed

+133
-17
lines changed

include/ylt/standalone/cinatra/coro_http_client.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ class coro_http_client : public std::enable_shared_from_this<coro_http_client> {
370370
}
371371

372372
async_simple::coro::Lazy<resp_data> read_websocket() {
373+
auto time_out_guard =
374+
timer_guard(this, req_timeout_duration_, "websocket timer");
373375
co_return co_await async_read_ws();
374376
}
375377

@@ -2141,6 +2143,9 @@ class coro_http_client : public std::enable_shared_from_this<coro_http_client> {
21412143
if (auto [ec, _] = co_await async_read_ws(
21422144
sock, read_buf, ws.left_header_len(), has_init_ssl);
21432145
ec) {
2146+
if (socket_->is_timeout_) {
2147+
co_return resp_data{std::make_error_code(std::errc::timed_out), 404};
2148+
}
21442149
data.net_err = ec;
21452150
data.status = 404;
21462151

include/ylt/standalone/cinatra/coro_http_connection.hpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,9 @@ class coro_http_connection
295295
}
296296
}
297297
// not found
298-
if (!is_matched_regex_router)
298+
if (!is_matched_regex_router) {
299299
response_.set_status(status_type::not_found);
300+
}
300301
}
301302
}
302303
}
@@ -305,10 +306,12 @@ class coro_http_connection
305306

306307
if (!response_.get_delay()) {
307308
if (head_buf_.size()) {
308-
if (type == content_type::multipart) {
309-
response_.set_status_and_content(
310-
status_type::not_implemented,
311-
"mutipart handler not implemented or incorrect implemented");
309+
if (type == content_type::multipart ||
310+
type == content_type::chunked) {
311+
if (response_.content().empty())
312+
response_.set_status_and_content(
313+
status_type::not_implemented,
314+
"mutipart handler not implemented or incorrect implemented");
312315
co_await reply();
313316
close();
314317
CINATRA_LOG_ERROR
@@ -405,10 +408,6 @@ class coro_http_connection
405408
if (need_to_bufffer) {
406409
response_.to_buffers(buffers_, chunk_size_str_);
407410
}
408-
int64_t send_size = 0;
409-
for (auto &buf : buffers_) {
410-
send_size += buf.size();
411-
}
412411
std::tie(ec, size) = co_await async_write(buffers_);
413412
}
414413
else {

include/ylt/standalone/cinatra/coro_http_router.hpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class coro_http_router {
6666
if (ok) {
6767
co_await handler(req, resp);
6868
}
69+
ok = true;
6970
(do_after(asps, req, resp, ok), ...);
7071
};
7172
}
@@ -113,6 +114,7 @@ class coro_http_router {
113114
if (ok) {
114115
handler(req, resp);
115116
}
117+
ok = true;
116118
(do_after(asps, req, resp, ok), ...);
117119
};
118120
}
@@ -155,20 +157,17 @@ class coro_http_router {
155157
}
156158
ok = aspect.before(req, resp);
157159
}
158-
else {
159-
ok = true;
160-
}
161160
}
162161

163162
template <typename T>
164163
void do_after(T& aspect, coro_http_request& req, coro_http_response& resp,
165164
bool& ok) {
166165
if constexpr (has_after_v<T>) {
166+
if (!ok) {
167+
return;
168+
}
167169
ok = aspect.after(req, resp);
168170
}
169-
else {
170-
ok = true;
171-
}
172171
}
173172

174173
std::function<void(coro_http_request& req, coro_http_response& resp)>*

include/ylt/standalone/cinatra/session.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class session {
6262
return std::nullopt;
6363
}
6464

65+
const auto &get_all_data() const { return data_; }
66+
6567
const std::string &get_session_id() {
6668
std::unique_lock<std::mutex> lock(mtx_);
6769
return session_id_;

src/coro_http/tests/test_cinatra.cpp

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,15 +549,32 @@ struct add_more_data {
549549
}
550550
};
551551

552+
std::vector<std::string> aspect_test_vec;
553+
552554
struct auth_t {
553555
bool before(coro_http_request &req, coro_http_response &res) { return true; }
556+
bool after(coro_http_request &req, coro_http_response &res) {
557+
aspect_test_vec.push_back("enter auth_t after");
558+
return false;
559+
}
554560
};
555561

556562
struct dely_t {
557563
bool before(coro_http_request &req, coro_http_response &res) {
558564
res.set_status_and_content(status_type::unauthorized, "unauthorized");
559565
return false;
560566
}
567+
bool after(coro_http_request &req, coro_http_response &res) {
568+
aspect_test_vec.push_back("enter delay_t after");
569+
return true;
570+
}
571+
};
572+
573+
struct another_t {
574+
bool after(coro_http_request &req, coro_http_response &res) {
575+
// won't comming
576+
return true;
577+
}
561578
};
562579

563580
TEST_CASE("test aspect") {
@@ -585,7 +602,7 @@ TEST_CASE("test aspect") {
585602
[](coro_http_request &req, coro_http_response &resp) {
586603
resp.set_status_and_content(status_type::ok, "ok");
587604
},
588-
dely_t{}, auth_t{});
605+
dely_t{}, auth_t{}, another_t{});
589606
server.set_http_handler<GET>(
590607
"/exception", [](coro_http_request &req, coro_http_response &resp) {
591608
throw std::invalid_argument("invalid argument");
@@ -619,6 +636,7 @@ TEST_CASE("test aspect") {
619636
CHECK(result.status == 200);
620637
result = async_simple::coro::syncAwait(client.async_get("/auth"));
621638
CHECK(result.status == 401);
639+
CHECK(aspect_test_vec.size() == 2);
622640
CHECK(result.resp_body == "unauthorized");
623641
result = async_simple::coro::syncAwait(client.async_get("/exception"));
624642
CHECK(result.status == 503);
@@ -729,6 +747,9 @@ TEST_CASE("test pipeline") {
729747
coro_http_server server(1, 9001);
730748
server.set_http_handler<GET, POST>(
731749
"/test", [](coro_http_request &req, coro_http_response &res) {
750+
if (req.get_content_type() == content_type::multipart) {
751+
return;
752+
}
732753
res.set_status_and_content(status_type::ok, "hello world");
733754
});
734755
server.set_http_handler<GET, POST>(
@@ -864,6 +885,58 @@ TEST_CASE("test pipeline") {
864885
}
865886
#endif
866887

888+
TEST_CASE("test multipart and chunked return error") {
889+
coro_http_server server(1, 8090);
890+
server.set_http_handler<cinatra::PUT, cinatra::POST>(
891+
"/multipart",
892+
[](request &req, response &resp) -> async_simple::coro::Lazy<void> {
893+
resp.set_status_and_content(status_type::bad_request,
894+
"invalid headers");
895+
co_return;
896+
});
897+
server.set_http_handler<cinatra::PUT, cinatra::POST>(
898+
"/chunked",
899+
[](request &req, response &resp) -> async_simple::coro::Lazy<void> {
900+
resp.set_status_and_content(status_type::bad_request,
901+
"invalid headers");
902+
co_return;
903+
});
904+
server.async_start();
905+
906+
std::string filename = "small_test_file.txt";
907+
create_file(filename, 10);
908+
{
909+
coro_http_client client{};
910+
std::string uri1 = "http://127.0.0.1:8090/chunked";
911+
auto result = async_simple::coro::syncAwait(
912+
client.async_upload_chunked(uri1, http_method::PUT, filename));
913+
CHECK(result.status != 200);
914+
if (!result.resp_body.empty())
915+
CHECK(result.resp_body == "invalid headers");
916+
}
917+
918+
{
919+
coro_http_client client{};
920+
std::string uri2 = "http://127.0.0.1:8090/multipart";
921+
client.add_str_part("test", "test value");
922+
auto result =
923+
async_simple::coro::syncAwait(client.async_upload_multipart(uri2));
924+
CHECK(result.status != 200);
925+
if (!result.resp_body.empty())
926+
CHECK(result.resp_body == "invalid headers");
927+
}
928+
929+
{
930+
coro_http_client client{};
931+
std::string uri1 = "http://127.0.0.1:8090/no_such";
932+
auto result = async_simple::coro::syncAwait(
933+
client.async_upload_chunked(uri1, http_method::PUT, filename));
934+
CHECK(result.status != 200);
935+
}
936+
std::error_code ec;
937+
fs::remove(filename, ec);
938+
}
939+
867940
async_simple::coro::Lazy<void> send_data(auto &ch, size_t count) {
868941
for (int i = 0; i < count; i++) {
869942
co_await coro_io::async_send(ch, i);
@@ -3073,6 +3146,8 @@ TEST_CASE("test session") {
30733146
session_id_check_login = session->get_session_id();
30743147
bool login = session->get_data<bool>("login").value_or(false);
30753148
CHECK(login == true);
3149+
auto &all = session->get_all_data();
3150+
CHECK(all.size() > 0);
30763151
res.set_status(status_type::ok);
30773152
});
30783153
server.set_http_handler<GET>(

src/coro_http/tests/test_cinatra_websocket.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,26 @@ TEST_CASE("test websocket") {
106106
break;
107107
}
108108

109+
auto ec = co_await req.get_conn()->write_websocket(result.data);
110+
if (ec) {
111+
break;
112+
}
113+
}
114+
});
115+
server.set_http_handler<cinatra::GET>(
116+
"/test_client_timeout",
117+
[](coro_http_request &req,
118+
coro_http_response &resp) -> async_simple::coro::Lazy<void> {
119+
CHECK(req.get_content_type() == content_type::websocket);
120+
websocket_result result{};
121+
while (true) {
122+
result = co_await req.get_conn()->read_websocket();
123+
if (result.ec) {
124+
break;
125+
}
126+
127+
std::this_thread::sleep_for(200ms);
128+
109129
auto ec = co_await req.get_conn()->write_websocket(result.data);
110130
if (ec) {
111131
break;
@@ -114,7 +134,23 @@ TEST_CASE("test websocket") {
114134
});
115135
server.async_start();
116136

117-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
137+
auto client_timeout = []() -> async_simple::coro::Lazy<void> {
138+
coro_http_client client{};
139+
client.set_req_timeout(50ms);
140+
client.set_ws_sec_key("s//GYHa/XO7Hd2F2eOGfyA==");
141+
142+
auto r = co_await client.connect("ws://localhost:8090/test_client_timeout");
143+
if (r.net_err) {
144+
co_return;
145+
}
146+
147+
co_await client.write_websocket("hello websocket");
148+
auto data = co_await client.read_websocket();
149+
std::cout << data.net_err.message() << std::endl;
150+
CHECK(data.net_err == std::errc::timed_out);
151+
};
152+
153+
async_simple::coro::syncAwait(client_timeout());
118154

119155
coro_http_client client{};
120156
client.set_ws_sec_key("s//GYHa/XO7Hd2F2eOGfyA==");

0 commit comments

Comments
 (0)