diff options
author | 2023-10-06 07:43:58 +0800 | |
---|---|---|
committer | 2023-10-05 20:43:58 -0300 | |
commit | e0e9bc16bffb7fe331b85de607235168b553d6e5 (patch) | |
tree | d62eba8455216ad809060e5e7bfcc525a71dfbd4 | |
parent | 30b8993eddfda43618789774a20d5505e42d99be (diff) | |
download | bun-e0e9bc16bffb7fe331b85de607235168b553d6e5.tar.gz bun-e0e9bc16bffb7fe331b85de607235168b553d6e5.tar.zst bun-e0e9bc16bffb7fe331b85de607235168b553d6e5.zip |
fix(serve): fix `close_connection` behaviour in `endWithoutBody` (#6315)
Close: #6031
-rw-r--r-- | src/deps/_libusockets.h | 5 | ||||
-rw-r--r-- | src/deps/libuwsockets.cpp | 29 | ||||
-rw-r--r-- | src/deps/uws.zig | 6 | ||||
-rw-r--r-- | test/js/bun/http/serve.test.ts | 28 |
4 files changed, 60 insertions, 8 deletions
diff --git a/src/deps/_libusockets.h b/src/deps/_libusockets.h index 5ca0e7df8..e9dbb6938 100644 --- a/src/deps/_libusockets.h +++ b/src/deps/_libusockets.h @@ -264,7 +264,7 @@ void uws_res_write_header(int ssl, uws_res_t *res, const char *key, void uws_res_write_header_int(int ssl, uws_res_t *res, const char *key, size_t key_length, uint64_t value); -void uws_res_end_without_body(int ssl, uws_res_t *res); +void uws_res_end_without_body(int ssl, uws_res_t *res, bool close_connection); void uws_res_end_stream(int ssl, uws_res_t *res, bool close_connection); bool uws_res_write(int ssl, uws_res_t *res, const char *data, size_t length); uintmax_t uws_res_get_write_offset(int ssl, uws_res_t *res); @@ -304,7 +304,6 @@ size_t uws_req_get_parameter(uws_req_t *res, unsigned short index, const char **dest); void uws_req_for_each_header(uws_req_t *res, uws_get_headers_server_handler handler, void *user_data); - struct us_loop_t *uws_get_loop(); struct us_loop_t *uws_get_loop_with_native(void* existing_native_loop); @@ -336,4 +335,4 @@ void uws_app_close(int ssl, uws_app_t *app); } #endif -#endif
\ No newline at end of file +#endif diff --git a/src/deps/libuwsockets.cpp b/src/deps/libuwsockets.cpp index bb89b33a8..a815e87df 100644 --- a/src/deps/libuwsockets.cpp +++ b/src/deps/libuwsockets.cpp @@ -1142,21 +1142,46 @@ extern "C" } } - void uws_res_end_without_body(int ssl, uws_res_t *res) + void uws_res_end_without_body(int ssl, uws_res_t *res, bool close_connection) { if (ssl) { uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; auto *data = uwsRes->getHttpResponseData(); + if (close_connection) + { + if (!(data->state & uWS::HttpResponseData<true>::HTTP_CONNECTION_CLOSE)) + { + uwsRes->writeHeader("Connection", "close"); + } + data->state |= uWS::HttpResponseData<true>::HTTP_CONNECTION_CLOSE; + } + if (!(data->state & uWS::HttpResponseData<true>::HTTP_END_CALLED)) + { + uwsRes->AsyncSocket<true>::write("\r\n", 2); + } data->state |= uWS::HttpResponseData<true>::HTTP_END_CALLED; data->markDone(); us_socket_timeout(true, (us_socket_t *)uwsRes, uWS::HTTP_TIMEOUT_S); } else { - uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; auto *data = uwsRes->getHttpResponseData(); + if (close_connection) + { + if (!(data->state & uWS::HttpResponseData<false>::HTTP_CONNECTION_CLOSE)) + { + uwsRes->writeHeader("Connection", "close"); + } + data->state |= uWS::HttpResponseData<false>::HTTP_CONNECTION_CLOSE; + } + if (!(data->state & uWS::HttpResponseData<false>::HTTP_END_CALLED)) + { + // Some HTTP clients require the complete "<header>\r\n\r\n" to be sent. + // If not, they may throw a ConnectionError. + uwsRes->AsyncSocket<false>::write("\r\n", 2); + } data->state |= uWS::HttpResponseData<false>::HTTP_END_CALLED; data->markDone(); us_socket_timeout(false, (us_socket_t *)uwsRes, uWS::HTTP_TIMEOUT_S); diff --git a/src/deps/uws.zig b/src/deps/uws.zig index 7a79e9c0f..1d6bae0c0 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -1806,8 +1806,8 @@ pub fn NewApp(comptime ssl: bool) type { pub fn writeHeaderInt(res: *Response, key: []const u8, value: u64) void { uws_res_write_header_int(ssl_flag, res.downcast(), key.ptr, key.len, value); } - pub fn endWithoutBody(res: *Response, _: bool) void { - uws_res_end_without_body(ssl_flag, res.downcast()); + pub fn endWithoutBody(res: *Response, close_connection: bool) void { + uws_res_end_without_body(ssl_flag, res.downcast(), close_connection); } pub fn write(res: *Response, data: []const u8) bool { return uws_res_write(ssl_flag, res.downcast(), data.ptr, data.len); @@ -2209,7 +2209,7 @@ extern fn uws_res_write_continue(ssl: i32, res: *uws_res) void; extern fn uws_res_write_status(ssl: i32, res: *uws_res, status: [*c]const u8, length: usize) void; extern fn uws_res_write_header(ssl: i32, res: *uws_res, key: [*c]const u8, key_length: usize, value: [*c]const u8, value_length: usize) void; extern fn uws_res_write_header_int(ssl: i32, res: *uws_res, key: [*c]const u8, key_length: usize, value: u64) void; -extern fn uws_res_end_without_body(ssl: i32, res: *uws_res) void; +extern fn uws_res_end_without_body(ssl: i32, res: *uws_res, close_connection: bool) void; extern fn uws_res_write(ssl: i32, res: *uws_res, data: [*c]const u8, length: usize) bool; extern fn uws_res_get_write_offset(ssl: i32, res: *uws_res) uintmax_t; extern fn uws_res_override_write_offset(ssl: i32, res: *uws_res, uintmax_t) void; diff --git a/test/js/bun/http/serve.test.ts b/test/js/bun/http/serve.test.ts index 67b7614b2..9b8448b55 100644 --- a/test/js/bun/http/serve.test.ts +++ b/test/js/bun/http/serve.test.ts @@ -1276,3 +1276,31 @@ it("server.requestIP (unix)", async () => { connection.end(); server.stop(true); }); + +it("should response with HTTP 413 when request body is larger than maxRequestBodySize, issue#6031", async () => { + const server = Bun.serve({ + port: 0, + maxRequestBodySize: 10, + fetch(req, server) { + return new Response("OK"); + }, + }); + + { + const resp = await fetch(`http://${server.hostname}:${server.port}`, { + method: "POST", + body: "A".repeat(10), + }); + expect(resp.status).toBe(200); + expect(await resp.text()).toBe("OK"); + } + { + const resp = await fetch(`http://${server.hostname}:${server.port}`, { + method: "POST", + body: "A".repeat(11), + }); + expect(resp.status).toBe(413); + } + + server.stop(true); +}); |