mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Merge branch 'ciro/fetch-upgrade' into ciro/fetch-upgrade-node-http
This commit is contained in:
5
packages/bun-types/bun.d.ts
vendored
5
packages/bun-types/bun.d.ts
vendored
@@ -3846,6 +3846,11 @@ declare module "bun" {
|
||||
* @category HTTP & Networking
|
||||
*/
|
||||
interface Server extends Disposable {
|
||||
/*
|
||||
* Closes all connections connected to this server which are not sending a request or waiting for a response. Does not close the listen socket.
|
||||
*/
|
||||
closeIdleConnections(): void;
|
||||
|
||||
/**
|
||||
* Stop listening to prevent new connections from being accepted.
|
||||
*
|
||||
|
||||
@@ -153,7 +153,7 @@ void us_internal_socket_context_unlink_connecting_socket(int ssl, struct us_sock
|
||||
}
|
||||
|
||||
/* We always add in the top, so we don't modify any s.next */
|
||||
void us_internal_socket_context_link_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *ls) {
|
||||
void us_internal_socket_context_link_listen_socket(int ssl, struct us_socket_context_t *context, struct us_listen_socket_t *ls) {
|
||||
struct us_socket_t* s = &ls->s;
|
||||
s->context = context;
|
||||
s->next = (struct us_socket_t *) context->head_listen_sockets;
|
||||
@@ -162,7 +162,7 @@ void us_internal_socket_context_link_listen_socket(struct us_socket_context_t *c
|
||||
context->head_listen_sockets->s.prev = s;
|
||||
}
|
||||
context->head_listen_sockets = ls;
|
||||
us_socket_context_ref(0, context);
|
||||
us_socket_context_ref(ssl, context);
|
||||
}
|
||||
|
||||
void us_internal_socket_context_link_connecting_socket(int ssl, struct us_socket_context_t *context, struct us_connecting_socket_t *c) {
|
||||
@@ -179,7 +179,7 @@ void us_internal_socket_context_link_connecting_socket(int ssl, struct us_socket
|
||||
|
||||
|
||||
/* We always add in the top, so we don't modify any s.next */
|
||||
void us_internal_socket_context_link_socket(struct us_socket_context_t *context, struct us_socket_t *s) {
|
||||
void us_internal_socket_context_link_socket(int ssl, struct us_socket_context_t *context, struct us_socket_t *s) {
|
||||
s->context = context;
|
||||
s->next = context->head_sockets;
|
||||
s->prev = 0;
|
||||
@@ -187,7 +187,7 @@ void us_internal_socket_context_link_socket(struct us_socket_context_t *context,
|
||||
context->head_sockets->prev = s;
|
||||
}
|
||||
context->head_sockets = s;
|
||||
us_socket_context_ref(0, context);
|
||||
us_socket_context_ref(ssl, context);
|
||||
us_internal_enable_sweep_timer(context->loop);
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ struct us_listen_socket_t *us_socket_context_listen(int ssl, struct us_socket_co
|
||||
s->flags.is_ipc = 0;
|
||||
s->next = 0;
|
||||
s->flags.allow_half_open = (options & LIBUS_SOCKET_ALLOW_HALF_OPEN);
|
||||
us_internal_socket_context_link_listen_socket(context, ls);
|
||||
us_internal_socket_context_link_listen_socket(ssl, context, ls);
|
||||
|
||||
ls->socket_ext_size = socket_ext_size;
|
||||
|
||||
@@ -423,7 +423,7 @@ struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, struct us_sock
|
||||
s->flags.is_paused = 0;
|
||||
s->flags.is_ipc = 0;
|
||||
s->next = 0;
|
||||
us_internal_socket_context_link_listen_socket(context, ls);
|
||||
us_internal_socket_context_link_listen_socket(ssl, context, ls);
|
||||
|
||||
ls->socket_ext_size = socket_ext_size;
|
||||
|
||||
@@ -456,7 +456,7 @@ struct us_socket_t* us_socket_context_connect_resolved_dns(struct us_socket_cont
|
||||
socket->connect_state = NULL;
|
||||
socket->connect_next = NULL;
|
||||
|
||||
us_internal_socket_context_link_socket(context, socket);
|
||||
us_internal_socket_context_link_socket(0, context, socket);
|
||||
|
||||
return socket;
|
||||
}
|
||||
@@ -584,7 +584,7 @@ int start_connections(struct us_connecting_socket_t *c, int count) {
|
||||
flags->is_paused = 0;
|
||||
flags->is_ipc = 0;
|
||||
/* Link it into context so that timeout fires properly */
|
||||
us_internal_socket_context_link_socket(context, s);
|
||||
us_internal_socket_context_link_socket(0, context, s);
|
||||
|
||||
// TODO check this, specifically how it interacts with the SSL code
|
||||
// does this work when we create multiple sockets at once? will we need multiple SSL contexts?
|
||||
@@ -762,7 +762,7 @@ struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_con
|
||||
connect_socket->flags.is_ipc = 0;
|
||||
connect_socket->connect_state = NULL;
|
||||
connect_socket->connect_next = NULL;
|
||||
us_internal_socket_context_link_socket(context, connect_socket);
|
||||
us_internal_socket_context_link_socket(ssl, context, connect_socket);
|
||||
|
||||
return connect_socket;
|
||||
}
|
||||
@@ -804,12 +804,9 @@ struct us_socket_t *us_socket_context_adopt_socket(int ssl, struct us_socket_con
|
||||
}
|
||||
|
||||
struct us_connecting_socket_t *c = s->connect_state;
|
||||
|
||||
struct us_socket_t *new_s = s;
|
||||
|
||||
if (ext_size != -1) {
|
||||
struct us_poll_t *pool_ref = &s->p;
|
||||
|
||||
new_s = (struct us_socket_t *) us_poll_resize(pool_ref, loop, sizeof(struct us_socket_t) + ext_size);
|
||||
if (c) {
|
||||
c->connecting_head = new_s;
|
||||
@@ -831,7 +828,7 @@ struct us_socket_t *us_socket_context_adopt_socket(int ssl, struct us_socket_con
|
||||
/* We manually ref/unref context to handle context life cycle with low-priority queue */
|
||||
us_socket_context_ref(ssl, context);
|
||||
} else {
|
||||
us_internal_socket_context_link_socket(context, new_s);
|
||||
us_internal_socket_context_link_socket(ssl, context, new_s);
|
||||
}
|
||||
/* We can safely unref the old context here with can potentially be freed */
|
||||
us_socket_context_unref(ssl, old_context);
|
||||
|
||||
@@ -150,16 +150,12 @@ void us_internal_init_loop_ssl_data(us_loop_r loop);
|
||||
void us_internal_free_loop_ssl_data(us_loop_r loop);
|
||||
|
||||
/* Socket context related */
|
||||
void us_internal_socket_context_link_socket(us_socket_context_r context,
|
||||
us_socket_r s);
|
||||
void us_internal_socket_context_unlink_socket(int ssl,
|
||||
us_socket_context_r context, us_socket_r s);
|
||||
void us_internal_socket_context_link_socket(int ssl, us_socket_context_r context, us_socket_r s);
|
||||
void us_internal_socket_context_unlink_socket(int ssl, us_socket_context_r context, us_socket_r s);
|
||||
|
||||
void us_internal_socket_after_resolve(struct us_connecting_socket_t *s);
|
||||
void us_internal_socket_after_open(us_socket_r s, int error);
|
||||
struct us_internal_ssl_socket_t *
|
||||
us_internal_ssl_socket_close(us_internal_ssl_socket_r s, int code,
|
||||
void *reason);
|
||||
struct us_internal_ssl_socket_t *us_internal_ssl_socket_close(us_internal_ssl_socket_r s, int code, void *reason);
|
||||
|
||||
int us_internal_handle_dns_results(us_loop_r loop);
|
||||
|
||||
@@ -271,7 +267,7 @@ struct us_listen_socket_t {
|
||||
};
|
||||
|
||||
/* Listen sockets are keps in their own list */
|
||||
void us_internal_socket_context_link_listen_socket(
|
||||
void us_internal_socket_context_link_listen_socket(int ssl,
|
||||
us_socket_context_r context, struct us_listen_socket_t *s);
|
||||
void us_internal_socket_context_unlink_listen_socket(int ssl,
|
||||
us_socket_context_r context, struct us_listen_socket_t *s);
|
||||
@@ -288,8 +284,7 @@ struct us_socket_context_t {
|
||||
struct us_socket_t *iterator;
|
||||
struct us_socket_context_t *prev, *next;
|
||||
|
||||
struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip,
|
||||
int ip_length);
|
||||
struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip, int ip_length);
|
||||
struct us_socket_t *(*on_data)(struct us_socket_t *, char *data, int length);
|
||||
struct us_socket_t *(*on_fd)(struct us_socket_t *, int fd);
|
||||
struct us_socket_t *(*on_writable)(struct us_socket_t *);
|
||||
@@ -301,7 +296,6 @@ struct us_socket_context_t {
|
||||
struct us_connecting_socket_t *(*on_connect_error)(struct us_connecting_socket_t *, int code);
|
||||
struct us_socket_t *(*on_socket_connect_error)(struct us_socket_t *, int code);
|
||||
int (*is_low_prio)(struct us_socket_t *);
|
||||
|
||||
};
|
||||
|
||||
/* Internal SSL interface */
|
||||
|
||||
@@ -40,7 +40,6 @@ void us_internal_enable_sweep_timer(struct us_loop_t *loop) {
|
||||
us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, LIBUS_TIMEOUT_GRANULARITY * 1000, LIBUS_TIMEOUT_GRANULARITY * 1000);
|
||||
Bun__internal_ensureDateHeaderTimerIsEnabled(loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void us_internal_disable_sweep_timer(struct us_loop_t *loop) {
|
||||
@@ -183,7 +182,7 @@ void us_internal_handle_low_priority_sockets(struct us_loop_t *loop) {
|
||||
if (s->next) s->next->prev = 0;
|
||||
s->next = 0;
|
||||
|
||||
us_internal_socket_context_link_socket(s->context, s);
|
||||
us_internal_socket_context_link_socket(0, s->context, s);
|
||||
us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) | LIBUS_SOCKET_READABLE);
|
||||
|
||||
s->flags.low_prio_state = 2;
|
||||
@@ -340,7 +339,7 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in
|
||||
/* We always use nodelay */
|
||||
bsd_socket_nodelay(client_fd, 1);
|
||||
|
||||
us_internal_socket_context_link_socket(listen_socket->s.context, s);
|
||||
us_internal_socket_context_link_socket(0, listen_socket->s.context, s);
|
||||
|
||||
listen_socket->s.context->on_open(s, 0, bsd_addr_get_ip(&addr), bsd_addr_get_ip_length(&addr));
|
||||
|
||||
@@ -364,7 +363,7 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in
|
||||
/* Note: if we failed a write as a socket of one loop then adopted
|
||||
* to another loop, this will be wrong. Absurd case though */
|
||||
loop->data.last_write_failed = 0;
|
||||
|
||||
|
||||
s = s->context->on_writable(s);
|
||||
|
||||
if (!s || us_socket_is_closed(0, s)) {
|
||||
|
||||
@@ -329,7 +329,7 @@ struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socke
|
||||
bsd_socket_nodelay(fd, 1);
|
||||
apple_no_sigpipe(fd);
|
||||
bsd_set_nonblocking(fd);
|
||||
us_internal_socket_context_link_socket(ctx, s);
|
||||
us_internal_socket_context_link_socket(0, ctx, s);
|
||||
|
||||
return s;
|
||||
#endif
|
||||
|
||||
@@ -298,6 +298,22 @@ public:
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
/** Closes all connections connected to this server which are not sending a request or waiting for a response. Does not close the listen socket. */
|
||||
TemplatedApp &&closeIdle() {
|
||||
auto context = (struct us_socket_context_t *)this->httpContext;
|
||||
struct us_socket_t *s = context->head_sockets;
|
||||
while (s) {
|
||||
HttpResponseData<SSL> *httpResponseData = HttpResponse<SSL>::getHttpResponseDataS(s);
|
||||
httpResponseData->shouldCloseOnceIdle = true;
|
||||
struct us_socket_t *next = s->next;
|
||||
if (httpResponseData->isIdle) {
|
||||
us_socket_close(SSL, s, LIBUS_SOCKET_CLOSE_CODE_CLEAN_SHUTDOWN, 0);
|
||||
}
|
||||
s = next;
|
||||
}
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
template <typename UserData>
|
||||
TemplatedApp &&ws(std::string_view pattern, WebSocketBehavior<UserData> &&behavior) {
|
||||
/* Don't compile if alignment rules cannot be satisfied */
|
||||
|
||||
@@ -386,6 +386,9 @@ public:
|
||||
/* We do not need to care for buffering here, write does that */
|
||||
return {0, true};
|
||||
}
|
||||
if (length == 0) {
|
||||
return {written, failed};
|
||||
}
|
||||
}
|
||||
|
||||
/* We should only return with new writes, not things written to cork already */
|
||||
|
||||
@@ -137,10 +137,6 @@ private:
|
||||
return (HttpContextData<SSL> *) us_socket_context_ext(SSL, getSocketContext());
|
||||
}
|
||||
|
||||
static HttpContextData<SSL> *getSocketContextDataS(us_socket_t *s) {
|
||||
return (HttpContextData<SSL> *) us_socket_context_ext(SSL, getSocketContext(s));
|
||||
}
|
||||
|
||||
/* Init the HttpContext by registering libusockets event handlers */
|
||||
HttpContext<SSL> *init() {
|
||||
|
||||
@@ -247,6 +243,7 @@ private:
|
||||
|
||||
/* Mark that we are inside the parser now */
|
||||
httpContextData->flags.isParsingHttp = true;
|
||||
httpResponseData->isIdle = false;
|
||||
// clients need to know the cursor after http parse, not servers!
|
||||
// how far did we read then? we need to know to continue with websocket parsing data? or?
|
||||
|
||||
@@ -398,6 +395,7 @@ private:
|
||||
/* Timeout on uncork failure */
|
||||
auto [written, failed] = ((AsyncSocket<SSL> *) returnedData)->uncork();
|
||||
if (written > 0 || failed) {
|
||||
httpResponseData->isIdle = true;
|
||||
/* All Http sockets timeout by this, and this behavior match the one in HttpResponse::cork */
|
||||
((HttpResponse<SSL> *) s)->resetTimeout();
|
||||
}
|
||||
@@ -642,6 +640,10 @@ public:
|
||||
}, priority);
|
||||
}
|
||||
|
||||
static HttpContextData<SSL> *getSocketContextDataS(us_socket_t *s) {
|
||||
return (HttpContextData<SSL> *) us_socket_context_ext(SSL, getSocketContext(s));
|
||||
}
|
||||
|
||||
/* Listen to port using this HttpContext */
|
||||
us_listen_socket_t *listen(const char *host, int port, int options) {
|
||||
int error = 0;
|
||||
|
||||
@@ -63,7 +63,6 @@ private:
|
||||
OnSocketClosedCallback onSocketClosed = nullptr;
|
||||
OnClientErrorCallback onClientError = nullptr;
|
||||
|
||||
HttpFlags flags;
|
||||
uint64_t maxHeaderSize = 0; // 0 means no limit
|
||||
|
||||
// TODO: SNI
|
||||
@@ -73,10 +72,8 @@ private:
|
||||
filterHandlers.clear();
|
||||
}
|
||||
|
||||
public:
|
||||
bool isAuthorized() const {
|
||||
return flags.isAuthorized;
|
||||
}
|
||||
public:
|
||||
HttpFlags flags;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ public:
|
||||
HttpResponseData<SSL> *getHttpResponseData() {
|
||||
return (HttpResponseData<SSL> *) Super::getAsyncSocketData();
|
||||
}
|
||||
|
||||
static HttpResponseData<SSL> *getHttpResponseDataS(us_socket_t *s) {
|
||||
return (HttpResponseData<SSL> *) us_socket_ext(SSL, s);
|
||||
}
|
||||
|
||||
void setTimeout(uint8_t seconds) {
|
||||
auto* data = getHttpResponseData();
|
||||
data->idleTimeout = seconds;
|
||||
@@ -132,7 +137,7 @@ public:
|
||||
|
||||
/* Terminating 0 chunk */
|
||||
Super::write("0\r\n\r\n", 5);
|
||||
httpResponseData->markDone();
|
||||
httpResponseData->markDone(this);
|
||||
|
||||
/* We need to check if we should close this socket here now */
|
||||
if (!Super::isCorked()) {
|
||||
@@ -198,7 +203,7 @@ public:
|
||||
|
||||
/* Remove onAborted function if we reach the end */
|
||||
if (httpResponseData->offset == totalSize) {
|
||||
httpResponseData->markDone();
|
||||
httpResponseData->markDone(this);
|
||||
|
||||
/* We need to check if we should close this socket here now */
|
||||
if (!Super::isCorked()) {
|
||||
|
||||
@@ -22,11 +22,15 @@
|
||||
#include "HttpParser.h"
|
||||
#include "AsyncSocketData.h"
|
||||
#include "ProxyParser.h"
|
||||
#include "HttpContext.h"
|
||||
|
||||
#include "MoveOnlyFunction.h"
|
||||
|
||||
namespace uWS {
|
||||
|
||||
template <bool SSL>
|
||||
struct HttpContext;
|
||||
|
||||
template <bool SSL>
|
||||
struct HttpResponseData : AsyncSocketData<SSL>, HttpParser {
|
||||
template <bool> friend struct HttpResponse;
|
||||
@@ -38,7 +42,7 @@ struct HttpResponseData : AsyncSocketData<SSL>, HttpParser {
|
||||
using OnDataCallback = void (*)(uWS::HttpResponse<SSL>* response, const char* chunk, size_t chunk_length, bool, void*);
|
||||
|
||||
/* When we are done with a response we mark it like so */
|
||||
void markDone() {
|
||||
void markDone(uWS::HttpResponse<SSL> *uwsRes) {
|
||||
onAborted = nullptr;
|
||||
/* Also remove onWritable so that we do not emit when draining behind the scenes. */
|
||||
onWritable = nullptr;
|
||||
@@ -50,6 +54,9 @@ struct HttpResponseData : AsyncSocketData<SSL>, HttpParser {
|
||||
|
||||
/* We are done with this request */
|
||||
this->state &= ~HttpResponseData<SSL>::HTTP_RESPONSE_PENDING;
|
||||
|
||||
HttpResponseData<SSL> *httpResponseData = uwsRes->getHttpResponseData();
|
||||
httpResponseData->isIdle = true;
|
||||
}
|
||||
|
||||
/* Caller of onWritable. It is possible onWritable calls markDone so we need to borrow it. */
|
||||
@@ -101,6 +108,8 @@ struct HttpResponseData : AsyncSocketData<SSL>, HttpParser {
|
||||
uint8_t state = 0;
|
||||
uint8_t idleTimeout = 10; // default HTTP_TIMEOUT 10 seconds
|
||||
bool fromAncientRequest = false;
|
||||
bool isIdle = true;
|
||||
bool shouldCloseOnceIdle = false;
|
||||
|
||||
|
||||
#ifdef UWS_WITH_PROXY
|
||||
|
||||
@@ -29,6 +29,10 @@ function generate(name) {
|
||||
fn: "dispose",
|
||||
length: 0,
|
||||
},
|
||||
closeIdleConnections: {
|
||||
fn: "closeIdleConnections",
|
||||
length: 0,
|
||||
},
|
||||
stop: {
|
||||
fn: "doStop",
|
||||
length: 1,
|
||||
|
||||
@@ -741,12 +741,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
}
|
||||
}
|
||||
|
||||
pub fn onUpgrade(
|
||||
this: *ThisServer,
|
||||
globalThis: *jsc.JSGlobalObject,
|
||||
object: jsc.JSValue,
|
||||
optional: ?JSValue,
|
||||
) bun.JSError!JSValue {
|
||||
pub fn onUpgrade(this: *ThisServer, globalThis: *jsc.JSGlobalObject, object: jsc.JSValue, optional: ?JSValue) bun.JSError!JSValue {
|
||||
if (this.config.websocket == null) {
|
||||
return globalThis.throwInvalidArguments("To enable websocket support, set the \"websocket\" object in Bun.serve({})", .{});
|
||||
}
|
||||
@@ -1132,11 +1127,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
return this.js_value.get();
|
||||
}
|
||||
|
||||
pub fn onFetch(
|
||||
this: *ThisServer,
|
||||
ctx: *jsc.JSGlobalObject,
|
||||
callframe: *jsc.CallFrame,
|
||||
) bun.JSError!jsc.JSValue {
|
||||
pub fn onFetch(this: *ThisServer, ctx: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue {
|
||||
jsc.markBinding(@src());
|
||||
|
||||
if (this.config.onRequest == .zero) {
|
||||
@@ -1253,6 +1244,14 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
return jsc.JSPromise.resolvedPromiseValue(ctx, response_value);
|
||||
}
|
||||
|
||||
pub fn closeIdleConnections(this: *ThisServer, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue {
|
||||
_ = globalObject;
|
||||
_ = callframe;
|
||||
if (this.app == null) return .js_undefined;
|
||||
this.app.?.closeIdleConnections();
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
pub fn stopFromJS(this: *ThisServer, abruptly: ?JSValue) jsc.JSValue {
|
||||
const rc = this.getAllClosedPromise(this.globalThis);
|
||||
|
||||
@@ -1280,10 +1279,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
pub fn getPort(
|
||||
this: *ThisServer,
|
||||
_: *jsc.JSGlobalObject,
|
||||
) jsc.JSValue {
|
||||
pub fn getPort(this: *ThisServer, _: *jsc.JSGlobalObject) jsc.JSValue {
|
||||
switch (this.config.address) {
|
||||
.unix => return .js_undefined,
|
||||
else => {},
|
||||
@@ -1412,10 +1408,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
return bun.String.static(if (ssl_enabled) "https" else "http").toJS(globalThis);
|
||||
}
|
||||
|
||||
pub fn getDevelopment(
|
||||
_: *ThisServer,
|
||||
_: *jsc.JSGlobalObject,
|
||||
) jsc.JSValue {
|
||||
pub fn getDevelopment(_: *ThisServer, _: *jsc.JSGlobalObject) jsc.JSValue {
|
||||
return jsc.JSValue.jsBoolean(debug_mode);
|
||||
}
|
||||
|
||||
@@ -1989,11 +1982,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
}
|
||||
}
|
||||
|
||||
pub fn onNodeHTTPRequest(
|
||||
this: *ThisServer,
|
||||
req: *uws.Request,
|
||||
resp: *App.Response,
|
||||
) void {
|
||||
pub fn onNodeHTTPRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void {
|
||||
jsc.markBinding(@src());
|
||||
onNodeHTTPRequestWithUpgradeCtx(this, req, resp, null);
|
||||
}
|
||||
@@ -2073,11 +2062,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
ctx.toAsync(req, prepared.request_object);
|
||||
}
|
||||
|
||||
pub fn onRequest(
|
||||
this: *ThisServer,
|
||||
req: *uws.Request,
|
||||
resp: *App.Response,
|
||||
) void {
|
||||
pub fn onRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void {
|
||||
var should_deinit_context = false;
|
||||
const prepared = this.prepareJsRequestContext(req, resp, &should_deinit_context, true, null) orelse return;
|
||||
|
||||
@@ -2094,14 +2079,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
this.handleRequest(&should_deinit_context, prepared, req, response_value);
|
||||
}
|
||||
|
||||
pub fn onRequestFromSaved(
|
||||
this: *ThisServer,
|
||||
req: SavedRequest.Union,
|
||||
resp: *App.Response,
|
||||
callback: JSValue,
|
||||
comptime arg_count: comptime_int,
|
||||
extra_args: [arg_count]JSValue,
|
||||
) void {
|
||||
pub fn onRequestFromSaved(this: *ThisServer, req: SavedRequest.Union, resp: *App.Response, callback: JSValue, comptime arg_count: comptime_int, extra_args: [arg_count]JSValue) void {
|
||||
const prepared: PreparedRequest = switch (req) {
|
||||
.stack => |r| this.prepareJsRequestContext(r, resp, null, true, null) orelse return,
|
||||
.saved => |data| .{
|
||||
@@ -2291,13 +2269,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
server.handleRequest(&should_deinit_context, prepared, req, response_value);
|
||||
}
|
||||
|
||||
pub fn onWebSocketUpgrade(
|
||||
this: *ThisServer,
|
||||
resp: *App.Response,
|
||||
req: *uws.Request,
|
||||
upgrade_ctx: *uws.SocketContext,
|
||||
id: usize,
|
||||
) void {
|
||||
pub fn onWebSocketUpgrade(this: *ThisServer, resp: *App.Response, req: *uws.Request, upgrade_ctx: *uws.SocketContext, id: usize) void {
|
||||
jsc.markBinding(@src());
|
||||
if (id == 1) {
|
||||
// This is actually a UserRoute if id is 1 so it's safe to cast
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
if (!context) return false;
|
||||
auto* data = (uWS::HttpContextData<true>*)us_socket_context_ext(is_ssl, context);
|
||||
if (!data) return false;
|
||||
return data->isAuthorized();
|
||||
return data->flags.isAuthorized;
|
||||
}
|
||||
~JSNodeHTTPServerSocket()
|
||||
{
|
||||
|
||||
@@ -377,6 +377,19 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
void uws_app_close_idle(int ssl, uws_app_t *app)
|
||||
{
|
||||
if (ssl)
|
||||
{
|
||||
uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
|
||||
uwsApp->closeIdle();
|
||||
}
|
||||
else
|
||||
{
|
||||
uWS::App *uwsApp = (uWS::App *)app;
|
||||
uwsApp->closeIdle();
|
||||
}
|
||||
}
|
||||
|
||||
void uws_app_set_on_clienterror(int ssl, uws_app_t *app, void (*handler)(void *user_data, int is_ssl, struct us_socket_t *rawSocket, uint8_t errorCode, char *rawPacket, int rawPacketLength), void *user_data)
|
||||
{
|
||||
@@ -1277,7 +1290,7 @@ extern "C"
|
||||
auto *data = uwsRes->getHttpResponseData();
|
||||
data->offset = offset;
|
||||
data->state |= uWS::HttpResponseData<true>::HTTP_END_CALLED;
|
||||
data->markDone();
|
||||
data->markDone(uwsRes);
|
||||
uwsRes->resetTimeout();
|
||||
}
|
||||
else
|
||||
@@ -1285,8 +1298,8 @@ extern "C"
|
||||
uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
|
||||
auto *data = uwsRes->getHttpResponseData();
|
||||
data->offset = offset;
|
||||
data->state |= uWS::HttpResponseData<true>::HTTP_END_CALLED;
|
||||
data->markDone();
|
||||
data->state |= uWS::HttpResponseData<false>::HTTP_END_CALLED;
|
||||
data->markDone(uwsRes);
|
||||
uwsRes->resetTimeout();
|
||||
}
|
||||
}
|
||||
@@ -1328,7 +1341,7 @@ extern "C"
|
||||
uwsRes->AsyncSocket<true>::write("\r\n", 2);
|
||||
}
|
||||
data->state |= uWS::HttpResponseData<true>::HTTP_END_CALLED;
|
||||
data->markDone();
|
||||
data->markDone(uwsRes);
|
||||
uwsRes->resetTimeout();
|
||||
}
|
||||
else
|
||||
@@ -1350,7 +1363,7 @@ extern "C"
|
||||
uwsRes->AsyncSocket<false>::write("\r\n", 2);
|
||||
}
|
||||
data->state |= uWS::HttpResponseData<false>::HTTP_END_CALLED;
|
||||
data->markDone();
|
||||
data->markDone(uwsRes);
|
||||
uwsRes->resetTimeout();
|
||||
}
|
||||
}
|
||||
@@ -1793,7 +1806,7 @@ __attribute__((callback (corker, ctx)))
|
||||
uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
|
||||
uwsRes->flushHeaders();
|
||||
} else {
|
||||
uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
|
||||
uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
|
||||
uwsRes->flushHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +43,14 @@ pub fn NewApp(comptime ssl: bool) type {
|
||||
return c.uws_app_close(ssl_flag, @as(*uws_app_s, @ptrCast(this)));
|
||||
}
|
||||
|
||||
pub fn closeIdleConnections(this: *ThisApp) void {
|
||||
return c.uws_app_close_idle(ssl_flag, @as(*uws_app_s, @ptrCast(this)));
|
||||
}
|
||||
|
||||
pub fn create(opts: BunSocketContextOptions) ?*ThisApp {
|
||||
return @ptrCast(c.uws_create_app(ssl_flag, opts));
|
||||
}
|
||||
|
||||
pub fn destroy(app: *ThisApp) void {
|
||||
return c.uws_app_destroy(ssl_flag, @as(*uws_app_s, @ptrCast(app)));
|
||||
}
|
||||
@@ -393,6 +398,7 @@ pub const c = struct {
|
||||
pub const uws_missing_server_handler = ?*const fn ([*c]const u8, ?*anyopaque) callconv(.C) void;
|
||||
|
||||
pub extern fn uws_app_close(ssl: i32, app: *uws_app_s) void;
|
||||
pub extern fn uws_app_close_idle(ssl: i32, app: *uws_app_s) void;
|
||||
pub extern fn uws_app_set_on_clienterror(ssl: c_int, app: *uws_app_s, handler: *const fn (*anyopaque, c_int, *us_socket_t, u8, ?[*]u8, c_int) callconv(.C) void, user_data: *anyopaque) void;
|
||||
pub extern fn uws_create_app(ssl: i32, options: BunSocketContextOptions) ?*uws_app_t;
|
||||
pub extern fn uws_app_destroy(ssl: i32, app: *uws_app_t) void;
|
||||
|
||||
@@ -303,7 +303,8 @@ Server.prototype.closeAllConnections = function () {
|
||||
};
|
||||
|
||||
Server.prototype.closeIdleConnections = function () {
|
||||
// not actually implemented
|
||||
const server = this[serverSymbol];
|
||||
server.closeIdleConnections();
|
||||
};
|
||||
|
||||
Server.prototype.close = function (optionalCallback?) {
|
||||
@@ -319,6 +320,7 @@ Server.prototype.close = function (optionalCallback?) {
|
||||
}
|
||||
if (typeof optionalCallback === "function") setCloseCallback(this, optionalCallback);
|
||||
this.listening = false;
|
||||
server.closeIdleConnections();
|
||||
server.stop();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const http = require('http');
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
res.end();
|
||||
}).listen(0, common.mustCall(() => {
|
||||
const agent = new http.Agent({
|
||||
maxSockets: 1,
|
||||
keepAlive: true
|
||||
});
|
||||
|
||||
const port = server.address().port;
|
||||
|
||||
const post = http.request({
|
||||
agent,
|
||||
method: 'POST',
|
||||
port,
|
||||
}, common.mustCall((res) => {
|
||||
res.resume();
|
||||
}));
|
||||
|
||||
// What happens here is that the server `end`s the response before we send
|
||||
// `something`, and the client thought that this is a green light for sending
|
||||
// next GET request
|
||||
post.write(Buffer.alloc(16 * 1024, 'X'));
|
||||
setTimeout(() => {
|
||||
post.end('something');
|
||||
}, 100);
|
||||
|
||||
http.request({
|
||||
agent,
|
||||
method: 'GET',
|
||||
port,
|
||||
}, common.mustCall((res) => {
|
||||
server.close();
|
||||
res.connection.end();
|
||||
})).end();
|
||||
}));
|
||||
@@ -22,6 +22,6 @@ server.listen(0, common.localhostIPv4, function() {
|
||||
function onResponse(res) {
|
||||
assert.strictEqual(res.headers.foo, 'bar');
|
||||
res.destroy();
|
||||
server.closeAllConnections();
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -43,7 +43,7 @@ const assert = require('assert');
|
||||
assert.strictEqual(res.destroyed, false);
|
||||
res.on('close', common.mustCall(() => {
|
||||
assert.strictEqual(res.destroyed, true);
|
||||
server.closeAllConnections();
|
||||
server.close();
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user