aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Ai Hoshino <ambiguous404@gmail.com> 2023-10-06 07:43:58 +0800
committerGravatar GitHub <noreply@github.com> 2023-10-05 20:43:58 -0300
commite0e9bc16bffb7fe331b85de607235168b553d6e5 (patch)
treed62eba8455216ad809060e5e7bfcc525a71dfbd4
parent30b8993eddfda43618789774a20d5505e42d99be (diff)
downloadbun-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.h5
-rw-r--r--src/deps/libuwsockets.cpp29
-rw-r--r--src/deps/uws.zig6
-rw-r--r--test/js/bun/http/serve.test.ts28
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);
+});