aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-20 04:38:04 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-20 04:38:04 -0700
commitbc85dd2330763189e7f28941cc6e35903d6b49a9 (patch)
treef9ba5b865615c1f4a4032d28aea47e7b6fda4a7b
parenta6b128590d104aa38a12ff20d820d02f0b6a8e6c (diff)
downloadbun-bc85dd2330763189e7f28941cc6e35903d6b49a9.tar.gz
bun-bc85dd2330763189e7f28941cc6e35903d6b49a9.tar.zst
bun-bc85dd2330763189e7f28941cc6e35903d6b49a9.zip
the events, they loop
-rw-r--r--.vscode/settings.json1
-rw-r--r--Makefile32
-rw-r--r--build.zig9
-rwxr-xr-xintegration/scripts/bun.lockbbin15683 -> 15723 bytes
-rwxr-xr-xpackages/bun-error/bun.lockbbin12997 -> 12182 bytes
-rw-r--r--src/bun_js.zig8
-rw-r--r--src/bundler/entry_points.zig4
-rw-r--r--src/deps/_libusockets.h289
-rw-r--r--src/deps/libuwsockets.cpp984
-rw-r--r--src/deps/uws.zig626
-rw-r--r--src/http_client_async.zig2
-rw-r--r--src/javascript/jsc/api/bun.zig26
-rw-r--r--src/javascript/jsc/api/server.zig320
-rw-r--r--src/javascript/jsc/bindings/BunBuiltinNames.h8
-rw-r--r--src/javascript/jsc/bindings/ZigGlobalObject.cpp3
-rw-r--r--src/javascript/jsc/bindings/bindings.cpp43
-rw-r--r--src/javascript/jsc/bindings/bindings.zig44
-rw-r--r--src/javascript/jsc/bindings/headers-cpp.h2
-rw-r--r--src/javascript/jsc/bindings/headers.h3
-rw-r--r--src/javascript/jsc/bindings/headers.zig1
-rw-r--r--src/javascript/jsc/javascript.zig6
-rw-r--r--src/javascript/jsc/node/node_fs.zig2
-rw-r--r--src/jsc.zig2
-rw-r--r--src/runtime.footer.bun.js2
24 files changed, 2391 insertions, 26 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index dcd7498a0..bb90dc1fe 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -40,6 +40,7 @@
"src/deps/s2n-tls": true,
"src/deps/boringssl": true,
"src/deps/openssl": true,
+ "src/deps/uws": true,
"src/deps/zlib": true,
"src/deps/lol-html": true,
"integration/snippets/package-json-exports/_node_modules_copy": true
diff --git a/Makefile b/Makefile
index de7bd11c3..988653f3c 100644
--- a/Makefile
+++ b/Makefile
@@ -164,7 +164,7 @@ POSIX_PKG_MANAGER=sudo apt
STRIP=
ifeq ($(OS_NAME),darwin)
-STRIP=strip
+STRIP=/usr/bin/strip
endif
ifeq ($(OS_NAME),linux)
@@ -188,7 +188,7 @@ MAC_INCLUDE_DIRS := -I$(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders \
LINUX_INCLUDE_DIRS := -I$(JSC_INCLUDE_DIR) \
-Isrc/javascript/jsc/bindings/
-INCLUDE_DIRS :=
+INCLUDE_DIRS := -I$(BUN_DEPS_DIR)/uws
@@ -243,7 +243,8 @@ CLANG_FLAGS = $(INCLUDE_DIRS) \
-DBUILDING_JSCONLY__ \
-DASSERT_ENABLED=0 \
-fvisibility=hidden \
- -fvisibility-inlines-hidden
+ -fvisibility-inlines-hidden \
+ -fPIC -fno-semantic-interposition
PLATFORM_LINKER_FLAGS =
@@ -266,13 +267,13 @@ ARCHIVE_FILES_WITHOUT_LIBCRYPTO = $(MIMALLOC_FILE_PATH) \
$(BUN_DEPS_OUT_DIR)/libarchive.a \
$(BUN_DEPS_OUT_DIR)/libssl.a \
$(BUN_DEPS_OUT_DIR)/picohttpparser.o \
- $(BUN_DEPS_OUT_DIR)/liblolhtml.a
+ $(BUN_DEPS_OUT_DIR)/liblolhtml.a \
+ $(BUN_DEPS_OUT_DIR)/uSockets.a \
+ $(BUN_DEPS_OUT_DIR)/libuwsockets.o
ARCHIVE_FILES = $(ARCHIVE_FILES_WITHOUT_LIBCRYPTO) $(BUN_DEPS_OUT_DIR)/libcrypto.boring.a
-
-
STATIC_MUSL_FLAG ?=
ifeq ($(OS_NAME), linux)
@@ -289,7 +290,8 @@ PLATFORM_LINKER_FLAGS = \
-static-libgcc \
-fno-omit-frame-pointer $(CFLAGS) \
-Wl,--compress-debug-sections,zlib \
- ${STATIC_MUSL_FLAG}
+ ${STATIC_MUSL_FLAG} \
+ -Wl,-Bsymbolic-functions
ARCHIVE_FILES_WITHOUT_LIBCRYPTO += $(BUN_DEPS_OUT_DIR)/libbacktrace.a
endif
@@ -428,6 +430,19 @@ build-obj-wasm-small:
build-obj-safe:
$(ZIG) build obj -Drelease-safe
+UWS_CC_FLAGS = -pthread -DLIBUS_USE_OPENSSL=1 -DLIBUS_USE_BORINGSSL=1 -DWITH_BORINGSSL=1 -Wpedantic -Wall -Wextra -Wsign-conversion -Wconversion -Isrc -IuSockets/src -DUWS_WITH_PROXY
+UWS_CXX_FLAGS = $(UWS_CC_FLAGS) -std=gnu++17
+UWS_LDFLAGS = -I$(BUN_DEPS_DIR)/boringssl/include
+
+usockets:
+ rm -rf $(BUN_DEPS_DIR)/uws/uSockets/*.o $(BUN_DEPS_DIR)/uws/uSockets/*.a
+ cd $(BUN_DEPS_DIR)/uws/uSockets && \
+ $(CC) $(CFLAGS) $(UWS_CC_FLAGS) $(UWS_LDFLAGS) $(DEFAULT_LINKER_FLAGS) $(PLATFORM_LINKER_FLAGS) -O3 -g -c -c src/*.c src/eventing/*.c src/crypto/*.c -flto && \
+ $(CXX) $(CXXFLAGS) $(UWS_CXX_FLAGS) $(UWS_LDFLAGS) $(DEFAULT_LINKER_FLAGS) $(PLATFORM_LINKER_FLAGS) -O3 -g -c src/crypto/*.cpp && \
+ ar rvs $(BUN_DEPS_OUT_DIR)/uSockets.a *.o
+
+uws: usockets
+ $(CXX) -I$(BUN_DEPS_DIR)/uws/uSockets/src $(CLANG_FLAGS) $(UWS_CXX_FLAGS) $(UWS_LDFLAGS) -c -flto -I$(BUN_DEPS_DIR) $(BUN_DEPS_OUT_DIR)/uSockets.a $(BUN_DEPS_DIR)/libuwsockets.cpp -o $(BUN_DEPS_OUT_DIR)/libuwsockets.o
@@ -984,7 +999,8 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
-g \
-fno-exceptions \
-ffunction-sections -fdata-sections -g \
- -ferror-limit=1000
+ -ferror-limit=1000 \
+ -emit-llvm -flto -fno-semantic-interposition
sizegen:
$(CXX) src/javascript/jsc/headergen/sizegen.cpp -o $(BUN_TMP_DIR)/sizegen $(CLANG_FLAGS) -O1
diff --git a/build.zig b/build.zig
index 3cdea2678..4f1052910 100644
--- a/build.zig
+++ b/build.zig
@@ -116,6 +116,11 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar
.path = pkgPath("src/jsc_stub.zig"),
};
+ var uws: std.build.Pkg = .{
+ .name = "uws",
+ .path = pkgPath("src/deps/uws.zig"),
+ };
+
var javascript_core = if (target.getOsTag() == .freestanding)
javascript_core_stub
else
@@ -128,7 +133,7 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar
io.dependencies = &.{analytics};
- javascript_core.dependencies = &.{ http, strings, picohttp, io };
+ javascript_core.dependencies = &.{ http, strings, picohttp, io, uws };
http.dependencies = &.{
strings,
picohttp,
@@ -162,6 +167,7 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar
step.addPackage(crash_reporter);
step.addPackage(datetime);
step.addPackage(lol_html);
+ step.addPackage(uws);
}
var output_dir: []const u8 = "";
fn panicIfNotFound(comptime filepath: []const u8) []const u8 {
@@ -519,6 +525,7 @@ pub fn linkObjectFiles(b: *std.build.Builder, obj: *std.build.LibExeObjStep, tar
.{ "libbmalloc.a", "libbmalloc.a" },
.{ "libbacktrace.a", "libbacktrace.a" },
.{ "liblolhtml.a", "liblolhtml.a" },
+ .{ "uSockets.a", "uSockets.a" },
});
for (dirs_to_search.slice()) |deps_path| {
diff --git a/integration/scripts/bun.lockb b/integration/scripts/bun.lockb
index 0dd841934..2d9937d57 100755
--- a/integration/scripts/bun.lockb
+++ b/integration/scripts/bun.lockb
Binary files differ
diff --git a/packages/bun-error/bun.lockb b/packages/bun-error/bun.lockb
index eede4f91d..1c7c459d1 100755
--- a/packages/bun-error/bun.lockb
+++ b/packages/bun-error/bun.lockb
Binary files differ
diff --git a/src/bun_js.zig b/src/bun_js.zig
index 716b1dfa7..618691afc 100644
--- a/src/bun_js.zig
+++ b/src/bun_js.zig
@@ -115,18 +115,14 @@ pub const Run = struct {
pub fn start(this: *Run) void {
var promise = this.vm.loadEntryPoint(this.entry_path) catch return;
- this.vm.tick();
-
- while (promise.status(this.vm.global.vm()) == .Pending) {
- this.vm.tick();
- }
if (promise.status(this.vm.global.vm()) == .Rejected) {
this.vm.defaultErrorHandler(promise.result(this.vm.global.vm()), null);
Global.exit(1);
}
- _ = promise.result(this.vm.global.vm());
+ const result = promise.result(this.vm.global.vm());
+ JSC.C.JSValueProtect(this.vm.global.ref(), result.asObjectRef());
if (this.vm.log.msgs.items.len > 0) {
if (Output.enable_ansi_colors) {
diff --git a/src/bundler/entry_points.zig b/src/bundler/entry_points.zig
index 4fafbf4ec..376043122 100644
--- a/src/bundler/entry_points.zig
+++ b/src/bundler/entry_points.zig
@@ -185,9 +185,11 @@ pub const ServerEntryPoint = struct {
\\//Auto-generated file
\\import * as start from '{s}{s}';
\\export * from '{s}{s}';
+ \\var entryNamespace = start;
\\if ('default' in start && "__internalIsCommonJSNamespace" in globalThis && __internalIsCommonJSNamespace(start)) {{
- \\ start.default();
+ \\ entryNamespace = start.default();
\\}}
+ \\if(entryNamespace && 'serverless' in entryNamespace) Bun.startServer(entryNamespace.serverless);
,
.{
dir_to_use,
diff --git a/src/deps/_libusockets.h b/src/deps/_libusockets.h
new file mode 100644
index 000000000..5456ff921
--- /dev/null
+++ b/src/deps/_libusockets.h
@@ -0,0 +1,289 @@
+
+#ifndef LIBUWS_CAPI_HEADER
+#define LIBUWS_CAPI_HEADER
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <uws/uSockets/src/libusockets.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ /* These are not actual compression options */
+ _COMPRESSOR_MASK = 0x00FF,
+ _DECOMPRESSOR_MASK = 0x0F00,
+ /* Disabled, shared, shared are "special" values */
+ DISABLED = 0,
+ SHARED_COMPRESSOR = 1,
+ SHARED_DECOMPRESSOR = 1 << 8,
+ /* Highest 4 bits describe decompressor */
+ DEDICATED_DECOMPRESSOR_32KB = 15 << 8,
+ DEDICATED_DECOMPRESSOR_16KB = 14 << 8,
+ DEDICATED_DECOMPRESSOR_8KB = 13 << 8,
+ DEDICATED_DECOMPRESSOR_4KB = 12 << 8,
+ DEDICATED_DECOMPRESSOR_2KB = 11 << 8,
+ DEDICATED_DECOMPRESSOR_1KB = 10 << 8,
+ DEDICATED_DECOMPRESSOR_512B = 9 << 8,
+ /* Same as 32kb */
+ DEDICATED_DECOMPRESSOR = 15 << 8,
+
+ /* Lowest 8 bit describe compressor */
+ DEDICATED_COMPRESSOR_3KB = 9 << 4 | 1,
+ DEDICATED_COMPRESSOR_4KB = 9 << 4 | 2,
+ DEDICATED_COMPRESSOR_8KB = 10 << 4 | 3,
+ DEDICATED_COMPRESSOR_16KB = 11 << 4 | 4,
+ DEDICATED_COMPRESSOR_32KB = 12 << 4 | 5,
+ DEDICATED_COMPRESSOR_64KB = 13 << 4 | 6,
+ DEDICATED_COMPRESSOR_128KB = 14 << 4 | 7,
+ DEDICATED_COMPRESSOR_256KB = 15 << 4 | 8,
+ /* Same as 256kb */
+ DEDICATED_COMPRESSOR = 15 << 4 | 8
+} uws_compress_options_t;
+
+typedef enum {
+ CONTINUATION = 0,
+ TEXT = 1,
+ BINARY = 2,
+ CLOSE = 8,
+ PING = 9,
+ PONG = 10
+} uws_opcode_t;
+
+typedef enum { BACKPRESSURE, SUCCESS, DROPPED } uws_sendstatus_t;
+
+typedef struct {
+
+ int port;
+ const char *host;
+ int options;
+} uws_app_listen_config_t;
+
+struct uws_app_s;
+struct uws_req_s;
+struct uws_res_s;
+struct uws_websocket_s;
+struct uws_header_iterator_s;
+typedef struct uws_app_s uws_app_t;
+typedef struct uws_req_s uws_req_t;
+typedef struct uws_res_s uws_res_t;
+typedef struct uws_socket_context_s uws_socket_context_t;
+typedef struct uws_websocket_s uws_websocket_t;
+
+typedef void (*uws_websocket_handler)(uws_websocket_t *ws);
+typedef void (*uws_websocket_message_handler)(uws_websocket_t *ws,
+ const char *message,
+ size_t length,
+ uws_opcode_t opcode);
+typedef void (*uws_websocket_ping_pong_handler)(uws_websocket_t *ws,
+ const char *message,
+ size_t length);
+typedef void (*uws_websocket_close_handler)(uws_websocket_t *ws, int code,
+ const char *message, size_t length);
+typedef void (*uws_websocket_upgrade_handler)(uws_res_t *response,
+ uws_req_t *request,
+ uws_socket_context_t *context);
+
+typedef struct {
+ uws_compress_options_t compression;
+ /* Maximum message size we can receive */
+ unsigned int maxPayloadLength;
+ /* 2 minutes timeout is good */
+ unsigned short idleTimeout;
+ /* 64kb backpressure is probably good */
+ unsigned int maxBackpressure;
+ bool closeOnBackpressureLimit;
+ /* This one depends on kernel timeouts and is a bad default */
+ bool resetIdleTimeoutOnSend;
+ /* A good default, esp. for newcomers */
+ bool sendPingsAutomatically;
+ /* Maximum socket lifetime in seconds before forced closure (defaults to
+ * disabled) */
+ unsigned short maxLifetime;
+
+ uws_websocket_upgrade_handler upgrade;
+ uws_websocket_handler open;
+ uws_websocket_message_handler message;
+ uws_websocket_handler drain;
+ uws_websocket_ping_pong_handler ping;
+ uws_websocket_ping_pong_handler pong;
+ uws_websocket_close_handler close;
+} uws_socket_behavior_t;
+
+typedef void (*uws_listen_handler)(struct us_listen_socket_t *listen_socket,
+ uws_app_listen_config_t config,
+ void *user_data);
+typedef void (*uws_method_handler)(uws_res_t *response, uws_req_t *request,
+ void *user_data);
+typedef void (*uws_filter_handler)(uws_res_t *response, int, void *user_data);
+typedef void (*uws_missing_server_handler)(const char *hostname,
+ void *user_data);
+// Basic HTTP
+uws_app_t *uws_create_app(int ssl, struct us_socket_context_options_t options);
+void uws_app_destroy(int ssl, uws_app_t *app);
+void uws_app_get(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_post(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_options(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_delete(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_patch(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_put(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_head(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_connect(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_trace(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+void uws_app_any(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data);
+
+void uws_app_run(int ssl, uws_app_t *);
+
+void uws_app_listen(int ssl, uws_app_t *app, int port,
+ uws_listen_handler handler, void *user_data);
+void uws_app_listen_with_config(int ssl, uws_app_t *app,
+ uws_app_listen_config_t config,
+ uws_listen_handler handler, void *user_data);
+bool uws_constructor_failed(int ssl, uws_app_t *app);
+unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic);
+bool uws_publish(int ssl, uws_app_t *app, const char *topic,
+ size_t topic_length, const char *message,
+ size_t message_length, uws_opcode_t opcode, bool compress);
+void *uws_get_native_handle(int ssl, uws_app_t *app);
+void uws_remove_server_name(int ssl, uws_app_t *app,
+ const char *hostname_pattern);
+void uws_add_server_name(int ssl, uws_app_t *app, const char *hostname_pattern);
+void uws_add_server_name_with_options(
+ int ssl, uws_app_t *app, const char *hostname_pattern,
+ struct us_socket_context_options_t options);
+void uws_missing_server_name(int ssl, uws_app_t *app,
+ uws_missing_server_handler handler,
+ void *user_data);
+void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler,
+ void *user_data);
+
+// WebSocket
+void uws_ws(int ssl, uws_app_t *app, const char *pattern,
+ uws_socket_behavior_t behavior);
+void *uws_ws_get_user_data(int ssl, uws_websocket_t *ws);
+void uws_ws_close(int ssl, uws_websocket_t *ws);
+uws_sendstatus_t uws_ws_send(int ssl, uws_websocket_t *ws, const char *message,
+ size_t length, uws_opcode_t opcode);
+uws_sendstatus_t uws_ws_send_with_options(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ uws_opcode_t opcode, bool compress,
+ bool fin);
+uws_sendstatus_t uws_ws_send_fragment(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ bool compress);
+uws_sendstatus_t uws_ws_send_first_fragment(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ bool compress);
+uws_sendstatus_t
+uws_ws_send_first_fragment_with_opcode(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ uws_opcode_t opcode, bool compress);
+uws_sendstatus_t uws_ws_send_last_fragment(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ bool compress);
+void uws_ws_end(int ssl, uws_websocket_t *ws, int code, const char *message,
+ size_t length);
+void uws_ws_cork(int ssl, uws_websocket_t *ws, void (*handler)(void *user_data),
+ void *user_data);
+bool uws_ws_subscribe(int ssl, uws_websocket_t *ws, const char *topic,
+ size_t length);
+bool uws_ws_unsubscribe(int ssl, uws_websocket_t *ws, const char *topic,
+ size_t length);
+bool uws_ws_is_subscribed(int ssl, uws_websocket_t *ws, const char *topic,
+ size_t length);
+void uws_ws_iterate_topics(int ssl, uws_websocket_t *ws,
+ void (*callback)(const char *topic, size_t length,
+ void *user_data),
+ void *user_data);
+bool uws_ws_publish(int ssl, uws_websocket_t *ws, const char *topic,
+ size_t topic_length, const char *message,
+ size_t message_length);
+bool uws_ws_publish_with_options(int ssl, uws_websocket_t *ws,
+ const char *topic, size_t topic_length,
+ const char *message, size_t message_length,
+ uws_opcode_t opcode, bool compress);
+unsigned int uws_ws_get_buffered_amount(int ssl, uws_websocket_t *ws);
+size_t uws_ws_get_remote_address(int ssl, uws_websocket_t *ws,
+ const char **dest);
+size_t uws_ws_get_remote_address_as_text(int ssl, uws_websocket_t *ws,
+ const char **dest);
+
+// Response
+void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length,
+ bool close_connection);
+void uws_res_pause(int ssl, uws_res_t *res);
+void uws_res_resume(int ssl, uws_res_t *res);
+void uws_res_write_continue(int ssl, uws_res_t *res);
+void uws_res_write_status(int ssl, uws_res_t *res, const char *status,
+ size_t length);
+void uws_res_write_header(int ssl, uws_res_t *res, const char *key,
+ size_t key_length, const char *value,
+ size_t value_length);
+
+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);
+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);
+bool uws_res_has_responded(int ssl, uws_res_t *res);
+void uws_res_on_writable(int ssl, uws_res_t *res,
+ bool (*handler)(uws_res_t *res, uintmax_t,
+ void *opcional_data),
+ void *user_data);
+void uws_res_on_aborted(int ssl, uws_res_t *res,
+ void (*handler)(uws_res_t *res, void *opcional_data),
+ void *opcional_data);
+void uws_res_on_data(int ssl, uws_res_t *res,
+ void (*handler)(uws_res_t *res, const char *chunk,
+ size_t chunk_length, bool is_end,
+ void *opcional_data),
+ void *opcional_data);
+void uws_res_upgrade(int ssl, uws_res_t *res, void *data,
+ const char *sec_web_socket_key,
+ size_t sec_web_socket_key_length,
+ const char *sec_web_socket_protocol,
+ size_t sec_web_socket_protocol_length,
+ const char *sec_web_socket_extensions,
+ size_t sec_web_socket_extensions_length,
+ uws_socket_context_t *ws);
+
+// Request
+bool uws_req_is_ancient(uws_req_t *res);
+bool uws_req_get_yield(uws_req_t *res);
+void uws_req_set_field(uws_req_t *res, bool yield);
+size_t uws_req_get_url(uws_req_t *res, const char **dest);
+size_t uws_req_get_method(uws_req_t *res, const char **dest);
+size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header,
+ size_t lower_case_header_length, const char **dest);
+size_t uws_req_get_query(uws_req_t *res, const char *key, size_t key_length,
+ const char **dest);
+size_t uws_req_get_parameter(uws_req_t *res, unsigned short index,
+ const char **dest);
+
+struct us_loop_t *uws_get_loop();
+
+void uws_loop_addPostHandler(us_loop_t *loop, void *ctx_,
+ void (*cb)(void *ctx, us_loop_t *loop));
+void uws_loop_removePostHandler(us_loop_t *loop, void *key);
+void uws_loop_addPreHandler(us_loop_t *loop, void *key,
+ void (*cb)(void *ctx, us_loop_t *loop));
+void uws_loop_removePreHandler(us_loop_t *loop, void *ctx_);
+void uws_loop_defer(us_loop_t *loop, void *ctx, void (*cb)(void *ctx));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif \ No newline at end of file
diff --git a/src/deps/libuwsockets.cpp b/src/deps/libuwsockets.cpp
new file mode 100644
index 000000000..ec082db43
--- /dev/null
+++ b/src/deps/libuwsockets.cpp
@@ -0,0 +1,984 @@
+#include "_libusockets.h"
+#include <string_view>
+#include <uws/src/App.h>
+
+extern "C" {
+
+uws_app_t *uws_create_app(int ssl, struct us_socket_context_options_t options) {
+ if (ssl) {
+ uWS::SocketContextOptions sco;
+ sco.ca_file_name = options.ca_file_name;
+ sco.cert_file_name = options.cert_file_name;
+ sco.dh_params_file_name = options.dh_params_file_name;
+ sco.key_file_name = options.key_file_name;
+ sco.passphrase = options.passphrase;
+ sco.ssl_prefer_low_memory_usage = options.ssl_prefer_low_memory_usage;
+ return (uws_app_t *)new uWS::SSLApp(sco);
+ }
+
+ return (uws_app_t *)new uWS::App();
+}
+
+void uws_app_get(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->get(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->get(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+void uws_app_post(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->post(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->post(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+void uws_app_options(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->options(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->options(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+void uws_app_delete(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->del(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->del(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+void uws_app_patch(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->patch(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->patch(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+void uws_app_put(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->put(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->put(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+void uws_app_head(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->head(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->head(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+void uws_app_connect(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->connect(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->connect(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+
+void uws_app_trace(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->trace(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->trace(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+void uws_app_any(int ssl, uws_app_t *app, const char *pattern,
+ uws_method_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->any(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->any(pattern, [handler, user_data](auto *res, auto *req) {
+ handler((uws_res_t *)res, (uws_req_t *)req, user_data);
+ });
+ }
+}
+
+void uws_app_run(int ssl, uws_app_t *app) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->run();
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->run();
+ }
+}
+
+void uws_app_listen(int ssl, uws_app_t *app, int port,
+ uws_listen_handler handler, void *user_data) {
+ uws_app_listen_config_t config;
+ config.port = port;
+ config.host = nullptr;
+ config.options = 0;
+
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->listen(port, [handler, config,
+ user_data](struct us_listen_socket_t *listen_socket) {
+ handler((struct us_listen_socket_t *)listen_socket, config, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+
+ uwsApp->listen(port, [handler, config,
+ user_data](struct us_listen_socket_t *listen_socket) {
+ handler((struct us_listen_socket_t *)listen_socket, config, user_data);
+ });
+ }
+}
+
+void uws_app_listen_with_config(int ssl, uws_app_t *app,
+ uws_app_listen_config_t config,
+ uws_listen_handler handler, void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->listen(
+ config.host, config.port, config.options,
+ [handler, config, user_data](struct us_listen_socket_t *listen_socket) {
+ handler((struct us_listen_socket_t *)listen_socket, config,
+ user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->listen(
+ config.host, config.port, config.options,
+ [handler, config, user_data](struct us_listen_socket_t *listen_socket) {
+ handler((struct us_listen_socket_t *)listen_socket, config,
+ user_data);
+ });
+ }
+}
+
+void uws_app_destroy(int ssl, uws_app_t *app) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ delete uwsApp;
+ } else {
+
+ uWS::App *uwsApp = (uWS::App *)app;
+ delete uwsApp;
+ }
+}
+
+bool uws_constructor_failed(int ssl, uws_app_t *app) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ if (!uwsApp)
+ return true;
+ return uwsApp->constructorFailed();
+ }
+ uWS::App *uwsApp = (uWS::App *)app;
+ if (!uwsApp)
+ return true;
+ return uwsApp->constructorFailed();
+}
+
+unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ return uwsApp->numSubscribers(topic);
+ }
+ uWS::App *uwsApp = (uWS::App *)app;
+ return uwsApp->numSubscribers(topic);
+}
+bool uws_publish(int ssl, uws_app_t *app, const char *topic,
+ size_t topic_length, const char *message,
+ size_t message_length, uws_opcode_t opcode, bool compress) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ return uwsApp->publish(std::string_view(topic, topic_length),
+ std::string_view(message, message_length),
+ (unsigned char)opcode, compress);
+ }
+ uWS::App *uwsApp = (uWS::App *)app;
+ return uwsApp->publish(std::string_view(topic, topic_length),
+ std::string_view(message, message_length),
+ (unsigned char)opcode, compress);
+}
+void *uws_get_native_handle(int ssl, uws_app_t *app) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ return uwsApp->getNativeHandle();
+ }
+ uWS::App *uwsApp = (uWS::App *)app;
+ return uwsApp->getNativeHandle();
+}
+void uws_remove_server_name(int ssl, uws_app_t *app,
+ const char *hostname_pattern) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->removeServerName(hostname_pattern);
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->removeServerName(hostname_pattern);
+ }
+}
+void uws_add_server_name(int ssl, uws_app_t *app,
+ const char *hostname_pattern) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->addServerName(hostname_pattern);
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->addServerName(hostname_pattern);
+ }
+}
+void uws_add_server_name_with_options(
+ int ssl, uws_app_t *app, const char *hostname_pattern,
+ struct us_socket_context_options_t options) {
+ uWS::SocketContextOptions sco;
+ sco.ca_file_name = options.ca_file_name;
+ sco.cert_file_name = options.cert_file_name;
+ sco.dh_params_file_name = options.dh_params_file_name;
+ sco.key_file_name = options.key_file_name;
+ sco.passphrase = options.passphrase;
+ sco.ssl_prefer_low_memory_usage = options.ssl_prefer_low_memory_usage;
+
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->addServerName(hostname_pattern, sco);
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->addServerName(hostname_pattern, sco);
+ }
+}
+
+void uws_missing_server_name(int ssl, uws_app_t *app,
+ uws_missing_server_handler handler,
+ void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->missingServerName(
+ [handler, user_data](auto hostname) { handler(hostname, user_data); });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->missingServerName(
+ [handler, user_data](auto hostname) { handler(hostname, user_data); });
+ }
+}
+void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler,
+ void *user_data) {
+ if (ssl) {
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+ uwsApp->filter([handler, user_data](auto res, auto i) {
+ handler((uws_res_t *)res, i, user_data);
+ });
+ } else {
+ uWS::App *uwsApp = (uWS::App *)app;
+
+ uwsApp->filter([handler, user_data](auto res, auto i) {
+ handler((uws_res_t *)res, i, user_data);
+ });
+ }
+}
+
+void uws_ws(int ssl, uws_app_t *app, const char *pattern,
+ uws_socket_behavior_t behavior) {
+ if (ssl) {
+ auto generic_handler = uWS::SSLApp::WebSocketBehavior<void *>{
+ .compression = (uWS::CompressOptions)(uint64_t)behavior.compression,
+ .maxPayloadLength = behavior.maxPayloadLength,
+ .idleTimeout = behavior.idleTimeout,
+ .maxBackpressure = behavior.maxBackpressure,
+ .closeOnBackpressureLimit = behavior.closeOnBackpressureLimit,
+ .resetIdleTimeoutOnSend = behavior.resetIdleTimeoutOnSend,
+ .sendPingsAutomatically = behavior.sendPingsAutomatically,
+ .maxLifetime = behavior.maxLifetime,
+ };
+
+ if (behavior.upgrade)
+ generic_handler.upgrade = [behavior](auto *res, auto *req,
+ auto *context) {
+ behavior.upgrade((uws_res_t *)res, (uws_req_t *)req,
+ (uws_socket_context_t *)context);
+ };
+ if (behavior.open)
+ generic_handler.open = [behavior](auto *ws) {
+ behavior.open((uws_websocket_t *)ws);
+ };
+ if (behavior.message)
+ generic_handler.message = [behavior](auto *ws, auto message,
+ auto opcode) {
+ behavior.message((uws_websocket_t *)ws, message.data(),
+ message.length(), (uws_opcode_t)opcode);
+ };
+ if (behavior.drain)
+ generic_handler.drain = [behavior](auto *ws) {
+ behavior.drain((uws_websocket_t *)ws);
+ };
+ if (behavior.ping)
+ generic_handler.ping = [behavior](auto *ws, auto message) {
+ behavior.ping((uws_websocket_t *)ws, message.data(), message.length());
+ };
+ if (behavior.pong)
+ generic_handler.pong = [behavior](auto *ws, auto message) {
+ behavior.pong((uws_websocket_t *)ws, message.data(), message.length());
+ };
+ if (behavior.close)
+ generic_handler.close = [behavior](auto *ws, int code, auto message) {
+ behavior.close((uws_websocket_t *)ws, code, message.data(),
+ message.length());
+ };
+ uWS::SSLApp *uwsApp = (uWS::SSLApp *)app;
+
+ uwsApp->ws<void *>(pattern, std::move(generic_handler));
+ } else {
+ auto generic_handler = uWS::App::WebSocketBehavior<void *>{
+ .compression = (uWS::CompressOptions)(uint64_t)behavior.compression,
+ .maxPayloadLength = behavior.maxPayloadLength,
+ .idleTimeout = behavior.idleTimeout,
+ .maxBackpressure = behavior.maxBackpressure,
+ .closeOnBackpressureLimit = behavior.closeOnBackpressureLimit,
+ .resetIdleTimeoutOnSend = behavior.resetIdleTimeoutOnSend,
+ .sendPingsAutomatically = behavior.sendPingsAutomatically,
+ .maxLifetime = behavior.maxLifetime,
+ };
+
+ if (behavior.upgrade)
+ generic_handler.upgrade = [behavior](auto *res, auto *req,
+ auto *context) {
+ behavior.upgrade((uws_res_t *)res, (uws_req_t *)req,
+ (uws_socket_context_t *)context);
+ };
+ if (behavior.open)
+ generic_handler.open = [behavior](auto *ws) {
+ behavior.open((uws_websocket_t *)ws);
+ };
+ if (behavior.message)
+ generic_handler.message = [behavior](auto *ws, auto message,
+ auto opcode) {
+ behavior.message((uws_websocket_t *)ws, message.data(),
+ message.length(), (uws_opcode_t)opcode);
+ };
+ if (behavior.drain)
+ generic_handler.drain = [behavior](auto *ws) {
+ behavior.drain((uws_websocket_t *)ws);
+ };
+ if (behavior.ping)
+ generic_handler.ping = [behavior](auto *ws, auto message) {
+ behavior.ping((uws_websocket_t *)ws, message.data(), message.length());
+ };
+ if (behavior.pong)
+ generic_handler.pong = [behavior](auto *ws, auto message) {
+ behavior.pong((uws_websocket_t *)ws, message.data(), message.length());
+ };
+ if (behavior.close)
+ generic_handler.close = [behavior](auto *ws, int code, auto message) {
+ behavior.close((uws_websocket_t *)ws, code, message.data(),
+ message.length());
+ };
+ uWS::App *uwsApp = (uWS::App *)app;
+ uwsApp->ws<void *>(pattern, std::move(generic_handler));
+ }
+}
+
+void *uws_ws_get_user_data(int ssl, uws_websocket_t *ws) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return *uws->getUserData();
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return *uws->getUserData();
+}
+
+void uws_ws_close(int ssl, uws_websocket_t *ws) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ uws->close();
+ } else {
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ uws->close();
+ }
+}
+
+uws_sendstatus_t uws_ws_send(int ssl, uws_websocket_t *ws, const char *message,
+ size_t length, uws_opcode_t opcode) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->send(std::string_view(message, length),
+ (uWS::OpCode)(unsigned char)opcode);
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->send(std::string_view(message, length),
+ (uWS::OpCode)(unsigned char)opcode);
+}
+
+uws_sendstatus_t uws_ws_send_with_options(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ uws_opcode_t opcode, bool compress,
+ bool fin) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->send(std::string_view(message),
+ (uWS::OpCode)(unsigned char)opcode,
+ compress, fin);
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->send(std::string_view(message),
+ (uWS::OpCode)(unsigned char)opcode,
+ compress, fin);
+}
+
+uws_sendstatus_t uws_ws_send_fragment(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ bool compress) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->sendFragment(
+ std::string_view(message, length), compress);
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->sendFragment(std::string_view(message, length),
+ compress);
+}
+uws_sendstatus_t uws_ws_send_first_fragment(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ bool compress) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->sendFirstFragment(
+ std::string_view(message), uWS::OpCode::BINARY, compress);
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->sendFirstFragment(
+ std::string_view(message), uWS::OpCode::BINARY, compress);
+}
+uws_sendstatus_t
+uws_ws_send_first_fragment_with_opcode(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ uws_opcode_t opcode, bool compress) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->sendFirstFragment(
+ std::string_view(message, length), (uWS::OpCode)(unsigned char)opcode,
+ compress);
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->sendFirstFragment(
+ std::string_view(message, length), (uWS::OpCode)(unsigned char)opcode,
+ compress);
+}
+uws_sendstatus_t uws_ws_send_last_fragment(int ssl, uws_websocket_t *ws,
+ const char *message, size_t length,
+ bool compress) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->sendLastFragment(
+ std::string_view(message, length), compress);
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return (uws_sendstatus_t)uws->sendLastFragment(
+ std::string_view(message, length), compress);
+}
+
+void uws_ws_end(int ssl, uws_websocket_t *ws, int code, const char *message,
+ size_t length) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ uws->end(code, std::string_view(message, length));
+ } else {
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ uws->end(code, std::string_view(message, length));
+ }
+}
+
+void uws_ws_cork(int ssl, uws_websocket_t *ws, void (*handler)(void *user_data),
+ void *user_data) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ uws->cork([handler, user_data]() { handler(user_data); });
+ } else {
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+
+ uws->cork([handler, user_data]() { handler(user_data); });
+ }
+}
+bool uws_ws_subscribe(int ssl, uws_websocket_t *ws, const char *topic,
+ size_t length) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return uws->subscribe(std::string_view(topic, length));
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return uws->subscribe(std::string_view(topic, length));
+}
+bool uws_ws_unsubscribe(int ssl, uws_websocket_t *ws, const char *topic,
+ size_t length) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return uws->unsubscribe(std::string_view(topic, length));
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return uws->unsubscribe(std::string_view(topic, length));
+}
+
+bool uws_ws_is_subscribed(int ssl, uws_websocket_t *ws, const char *topic,
+ size_t length) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return uws->isSubscribed(std::string_view(topic, length));
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return uws->isSubscribed(std::string_view(topic, length));
+}
+void uws_ws_iterate_topics(int ssl, uws_websocket_t *ws,
+ void (*callback)(const char *topic, size_t length,
+ void *user_data),
+ void *user_data) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ uws->iterateTopics([callback, user_data](auto topic) {
+ callback(topic.data(), topic.length(), user_data);
+ });
+ } else {
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+
+ uws->iterateTopics([callback, user_data](auto topic) {
+ callback(topic.data(), topic.length(), user_data);
+ });
+ }
+}
+
+bool uws_ws_publish(int ssl, uws_websocket_t *ws, const char *topic,
+ size_t topic_length, const char *message,
+ size_t message_length) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return uws->publish(std::string_view(topic, topic_length),
+ std::string_view(message, message_length));
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return uws->publish(std::string_view(topic, topic_length),
+ std::string_view(message, message_length));
+}
+
+bool uws_ws_publish_with_options(int ssl, uws_websocket_t *ws,
+ const char *topic, size_t topic_length,
+ const char *message, size_t message_length,
+ uws_opcode_t opcode, bool compress) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return uws->publish(std::string_view(topic, topic_length),
+ std::string_view(message, message_length),
+ (uWS::OpCode)(unsigned char)opcode, compress);
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return uws->publish(std::string_view(topic, topic_length),
+ std::string_view(message, message_length),
+ (uWS::OpCode)(unsigned char)opcode, compress);
+}
+
+unsigned int uws_ws_get_buffered_amount(int ssl, uws_websocket_t *ws) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ return uws->getBufferedAmount();
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+ return uws->getBufferedAmount();
+}
+
+size_t uws_ws_get_remote_address(int ssl, uws_websocket_t *ws,
+ const char **dest) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+ std::string_view value = uws->getRemoteAddress();
+ *dest = value.data();
+ return value.length();
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+
+ std::string_view value = uws->getRemoteAddress();
+ *dest = value.data();
+ return value.length();
+}
+
+size_t uws_ws_get_remote_address_as_text(int ssl, uws_websocket_t *ws,
+ const char **dest) {
+ if (ssl) {
+ uWS::WebSocket<true, true, void *> *uws =
+ (uWS::WebSocket<true, true, void *> *)ws;
+
+ std::string_view value = uws->getRemoteAddressAsText();
+ *dest = value.data();
+ return value.length();
+ }
+ uWS::WebSocket<false, true, void *> *uws =
+ (uWS::WebSocket<false, true, void *> *)ws;
+
+ std::string_view value = uws->getRemoteAddressAsText();
+ *dest = value.data();
+ return value.length();
+}
+
+void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length,
+ bool close_connection) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->end(std::string_view(data, length), close_connection);
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->end(std::string_view(data, length), close_connection);
+ }
+}
+
+void uws_res_pause(int ssl, uws_res_t *res) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->pause();
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->pause();
+ }
+}
+
+void uws_res_resume(int ssl, uws_res_t *res) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->pause();
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->pause();
+ }
+}
+
+void uws_res_write_continue(int ssl, uws_res_t *res) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->writeContinue();
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->writeContinue();
+ }
+}
+
+void uws_res_write_status(int ssl, uws_res_t *res, const char *status,
+ size_t length) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->writeStatus(std::string_view(status, length));
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->writeStatus(std::string_view(status, length));
+ }
+}
+
+void uws_res_write_header(int ssl, uws_res_t *res, const char *key,
+ size_t key_length, const char *value,
+ size_t value_length) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->writeHeader(std::string_view(key, key_length),
+ std::string_view(value, value_length));
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->writeHeader(std::string_view(key, key_length),
+ std::string_view(value, value_length));
+ }
+}
+void uws_res_write_header_int(int ssl, uws_res_t *res, const char *key,
+ size_t key_length, uint64_t value) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->writeHeader(std::string_view(key, key_length), value);
+ } else {
+
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->writeHeader(std::string_view(key, key_length), value);
+ }
+}
+
+void uws_res_end_without_body(int ssl, uws_res_t *res) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->endWithoutBody(0);
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->endWithoutBody(0);
+ }
+}
+
+bool uws_res_write(int ssl, uws_res_t *res, const char *data, size_t length) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ return uwsRes->write(std::string_view(data));
+ }
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ return uwsRes->write(std::string_view(data));
+}
+uintmax_t uws_res_get_write_offset(int ssl, uws_res_t *res) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ return uwsRes->getWriteOffset();
+ }
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ return uwsRes->getWriteOffset();
+}
+
+bool uws_res_has_responded(int ssl, uws_res_t *res) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ return uwsRes->hasResponded();
+ }
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ return uwsRes->hasResponded();
+}
+
+void uws_res_on_writable(int ssl, uws_res_t *res,
+ bool (*handler)(uws_res_t *res, uintmax_t,
+ void *opcional_data),
+ void *opcional_data) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->onWritable([handler, res, opcional_data](uintmax_t a) {
+ return handler(res, a, opcional_data);
+ });
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->onWritable([handler, res, opcional_data](uintmax_t a) {
+ return handler(res, a, opcional_data);
+ });
+ }
+}
+
+void uws_res_on_aborted(int ssl, uws_res_t *res,
+ void (*handler)(uws_res_t *res, void *opcional_data),
+ void *opcional_data) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->onAborted(
+ [handler, res, opcional_data] { handler(res, opcional_data); });
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->onAborted(
+ [handler, res, opcional_data] { handler(res, opcional_data); });
+ }
+}
+
+void uws_res_on_data(int ssl, uws_res_t *res,
+ void (*handler)(uws_res_t *res, const char *chunk,
+ size_t chunk_length, bool is_end,
+ void *opcional_data),
+ void *opcional_data) {
+ if (ssl) {
+ uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
+ uwsRes->onData([handler, res, opcional_data](auto chunk, bool is_end) {
+ handler(res, chunk.data(), chunk.length(), is_end, opcional_data);
+ });
+ } else {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+ uwsRes->onData([handler, res, opcional_data](auto chunk, bool is_end) {
+ handler(res, chunk.data(), chunk.length(), is_end, opcional_data);
+ });
+ }
+}
+
+bool uws_req_is_ancient(uws_req_t *res) {
+ uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res;
+ return uwsReq->isAncient();
+}
+
+bool uws_req_get_yield(uws_req_t *res) {
+ uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res;
+ return uwsReq->getYield();
+}
+
+void uws_req_set_field(uws_req_t *res, bool yield) {
+ uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res;
+ return uwsReq->setYield(yield);
+}
+
+size_t uws_req_get_url(uws_req_t *res, const char **dest) {
+ uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res;
+ std::string_view value = uwsReq->getUrl();
+ *dest = value.data();
+ return value.length();
+}
+
+size_t uws_req_get_method(uws_req_t *res, const char **dest) {
+ uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res;
+ std::string_view value = uwsReq->getMethod();
+ *dest = value.data();
+ return value.length();
+}
+
+size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header,
+ size_t lower_case_header_length, const char **dest) {
+ uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res;
+
+ std::string_view value = uwsReq->getHeader(
+ std::string_view(lower_case_header, lower_case_header_length));
+ *dest = value.data();
+ return value.length();
+}
+
+size_t uws_req_get_query(uws_req_t *res, const char *key, size_t key_length,
+ const char **dest) {
+ uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res;
+
+ std::string_view value = uwsReq->getQuery(std::string_view(key, key_length));
+ *dest = value.data();
+ return value.length();
+}
+
+size_t uws_req_get_parameter(uws_req_t *res, unsigned short index,
+ const char **dest) {
+ uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res;
+ std::string_view value = uwsReq->getParameter(index);
+ *dest = value.data();
+ return value.length();
+}
+
+void uws_res_upgrade(int ssl, uws_res_t *res, void *data,
+ const char *sec_web_socket_key,
+ size_t sec_web_socket_key_length,
+ const char *sec_web_socket_protocol,
+ size_t sec_web_socket_protocol_length,
+ const char *sec_web_socket_extensions,
+ size_t sec_web_socket_extensions_length,
+ uws_socket_context_t *ws) {
+ uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
+
+ uwsRes->template upgrade<void *>(
+ data ? std::move(data) : NULL,
+ std::string_view(sec_web_socket_key, sec_web_socket_key_length),
+ std::string_view(sec_web_socket_protocol, sec_web_socket_protocol_length),
+ std::string_view(sec_web_socket_extensions,
+ sec_web_socket_extensions_length),
+ (struct us_socket_context_t *)ws);
+}
+
+struct us_loop_t *uws_get_loop() {
+ return (struct us_loop_t *)uWS::Loop::get();
+}
+
+void uws_loop_addPostHandler(us_loop_t *loop, void *ctx_,
+ void (*cb)(void *ctx, us_loop_t *loop)) {
+ uWS::Loop *uwsLoop = (uWS::Loop *)loop;
+ uwsLoop->addPostHandler(ctx_, [ctx_, cb](uWS::Loop *uwsLoop_) {
+ cb(ctx_, (us_loop_t *)uwsLoop_);
+ });
+}
+void uws_loop_removePostHandler(us_loop_t *loop, void *key) {
+ uWS::Loop *uwsLoop = (uWS::Loop *)loop;
+ uwsLoop->removePostHandler(key);
+}
+void uws_loop_addPreHandler(us_loop_t *loop, void *ctx_,
+ void (*cb)(void *ctx, us_loop_t *loop)) {
+ uWS::Loop *uwsLoop = (uWS::Loop *)loop;
+ uwsLoop->addPreHandler(ctx_, [ctx_, cb](uWS::Loop *uwsLoop_) {
+ cb(ctx_, (us_loop_t *)uwsLoop_);
+ });
+}
+void uws_loop_removePreHandler(us_loop_t *loop, void *ctx_) {
+ uWS::Loop *uwsLoop = (uWS::Loop *)loop;
+ uwsLoop->removePreHandler(ctx_);
+}
+void uws_loop_defer(us_loop_t *loop, void *ctx, void (*cb)(void *ctx)) {
+ uWS::Loop *uwsLoop = (uWS::Loop *)loop;
+ uwsLoop->defer([ctx, cb]() { cb(ctx); });
+}
+} \ No newline at end of file
diff --git a/src/deps/uws.zig b/src/deps/uws.zig
new file mode 100644
index 000000000..fc7a32865
--- /dev/null
+++ b/src/deps/uws.zig
@@ -0,0 +1,626 @@
+pub const u_int8_t = u8;
+pub const u_int16_t = c_ushort;
+pub const u_int32_t = c_uint;
+pub const u_int64_t = c_ulonglong;
+pub const LIBUS_LISTEN_DEFAULT: c_int = 0;
+pub const LIBUS_LISTEN_EXCLUSIVE_PORT: c_int = 1;
+pub const us_socket_t = opaque {};
+pub const us_timer_t = opaque {};
+pub const us_socket_context_t = opaque {};
+pub const Loop = opaque {
+ pub fn get() ?*Loop {
+ return uws_get_loop();
+ }
+
+ pub fn wakeup(this: *Loop) void {
+ return us_wakeup_loop(this);
+ }
+
+ pub fn nextTick(this: *Loop, comptime UserType: type, user_data: UserType, comptime deferCallback: fn (ctx: UserType) void) void {
+ const Handler = struct {
+ pub fn callback(data: *anyopaque) callconv(.C) void {
+ deferCallback(@ptrCast(UserType, @alignCast(@alignOf(UserType), data)));
+ }
+ };
+ uws_loop_defer(this, user_data, Handler.callback);
+ }
+
+ extern fn uws_loop_defer(loop: *Loop, ctx: *anyopaque, cb: fn (ctx: *anyopaque) callconv(.C) void) void;
+
+ extern fn uws_get_loop() ?*Loop;
+ extern fn us_create_loop(hint: ?*anyopaque, wakeup_cb: ?fn (?*Loop) callconv(.C) void, pre_cb: ?fn (?*Loop) callconv(.C) void, post_cb: ?fn (?*Loop) callconv(.C) void, ext_size: c_uint) ?*Loop;
+ extern fn us_loop_free(loop: ?*Loop) void;
+ extern fn us_loop_ext(loop: ?*Loop) ?*anyopaque;
+ extern fn us_loop_run(loop: ?*Loop) void;
+ extern fn us_wakeup_loop(loop: ?*Loop) void;
+ extern fn us_loop_integrate(loop: ?*Loop) void;
+ extern fn us_loop_iteration_number(loop: ?*Loop) c_longlong;
+};
+const uintmax_t = c_ulong;
+
+extern fn us_create_timer(loop: ?*Loop, fallthrough: c_int, ext_size: c_uint) ?*us_timer_t;
+extern fn us_timer_ext(timer: ?*us_timer_t) ?*anyopaque;
+extern fn us_timer_close(timer: ?*us_timer_t) void;
+extern fn us_timer_set(timer: ?*us_timer_t, cb: ?fn (?*us_timer_t) callconv(.C) void, ms: c_int, repeat_ms: c_int) void;
+extern fn us_timer_loop(t: ?*us_timer_t) ?*Loop;
+pub const us_socket_context_options_t = extern struct {
+ key_file_name: [*c]const u8 = null,
+ cert_file_name: [*c]const u8 = null,
+ passphrase: [*c]const u8 = null,
+ dh_params_file_name: [*c]const u8 = null,
+ ca_file_name: [*c]const u8 = null,
+ ssl_prefer_low_memory_usage: c_int = 0,
+};
+
+extern fn us_socket_context_timestamp(ssl: c_int, context: ?*us_socket_context_t) c_ushort;
+extern fn us_socket_context_add_server_name(ssl: c_int, context: ?*us_socket_context_t, hostname_pattern: [*c]const u8, options: us_socket_context_options_t) void;
+extern fn us_socket_context_remove_server_name(ssl: c_int, context: ?*us_socket_context_t, hostname_pattern: [*c]const u8) void;
+extern fn us_socket_context_on_server_name(ssl: c_int, context: ?*us_socket_context_t, cb: ?fn (?*us_socket_context_t, [*c]const u8) callconv(.C) void) void;
+extern fn us_socket_context_get_native_handle(ssl: c_int, context: ?*us_socket_context_t) ?*anyopaque;
+extern fn us_create_socket_context(ssl: c_int, loop: ?*Loop, ext_size: c_int, options: us_socket_context_options_t) ?*us_socket_context_t;
+extern fn us_socket_context_free(ssl: c_int, context: ?*us_socket_context_t) void;
+extern fn us_socket_context_on_open(ssl: c_int, context: ?*us_socket_context_t, on_open: ?fn (?*us_socket_t, c_int, [*c]u8, c_int) callconv(.C) ?*us_socket_t) void;
+extern fn us_socket_context_on_close(ssl: c_int, context: ?*us_socket_context_t, on_close: ?fn (?*us_socket_t, c_int, ?*anyopaque) callconv(.C) ?*us_socket_t) void;
+extern fn us_socket_context_on_data(ssl: c_int, context: ?*us_socket_context_t, on_data: ?fn (?*us_socket_t, [*c]u8, c_int) callconv(.C) ?*us_socket_t) void;
+extern fn us_socket_context_on_writable(ssl: c_int, context: ?*us_socket_context_t, on_writable: ?fn (?*us_socket_t) callconv(.C) ?*us_socket_t) void;
+extern fn us_socket_context_on_timeout(ssl: c_int, context: ?*us_socket_context_t, on_timeout: ?fn (?*us_socket_t) callconv(.C) ?*us_socket_t) void;
+extern fn us_socket_context_on_connect_error(ssl: c_int, context: ?*us_socket_context_t, on_connect_error: ?fn (?*us_socket_t, c_int) callconv(.C) ?*us_socket_t) void;
+extern fn us_socket_context_on_end(ssl: c_int, context: ?*us_socket_context_t, on_end: ?fn (?*us_socket_t) callconv(.C) ?*us_socket_t) void;
+extern fn us_socket_context_ext(ssl: c_int, context: ?*us_socket_context_t) ?*anyopaque;
+
+extern fn us_socket_context_listen(ssl: c_int, context: ?*us_socket_context_t, host: [*c]const u8, port: c_int, options: c_int, socket_ext_size: c_int) ?*listen_socket_t;
+
+extern fn us_socket_context_connect(ssl: c_int, context: ?*us_socket_context_t, host: [*c]const u8, port: c_int, source_host: [*c]const u8, options: c_int, socket_ext_size: c_int) ?*us_socket_t;
+extern fn us_socket_is_established(ssl: c_int, s: ?*us_socket_t) c_int;
+extern fn us_socket_close_connecting(ssl: c_int, s: ?*us_socket_t) ?*us_socket_t;
+extern fn us_socket_context_loop(ssl: c_int, context: ?*us_socket_context_t) ?*Loop;
+extern fn us_socket_context_adopt_socket(ssl: c_int, context: ?*us_socket_context_t, s: ?*us_socket_t, ext_size: c_int) ?*us_socket_t;
+extern fn us_create_child_socket_context(ssl: c_int, context: ?*us_socket_context_t, context_ext_size: c_int) ?*us_socket_context_t;
+
+pub const Poll = opaque {
+ extern fn us_create_poll(loop: ?*Loop, fallthrough: c_int, ext_size: c_uint) ?*Poll;
+ extern fn us_poll_free(p: ?*Poll, loop: ?*Loop) void;
+ extern fn us_poll_init(p: ?*Poll, fd: c_int, poll_type: c_int) void;
+ extern fn us_poll_start(p: ?*Poll, loop: ?*Loop, events: c_int) void;
+ extern fn us_poll_change(p: ?*Poll, loop: ?*Loop, events: c_int) void;
+ extern fn us_poll_stop(p: ?*Poll, loop: ?*Loop) void;
+ extern fn us_poll_events(p: ?*Poll) c_int;
+ extern fn us_poll_ext(p: ?*Poll) ?*anyopaque;
+ extern fn us_poll_fd(p: ?*Poll) c_int;
+ extern fn us_poll_resize(p: ?*Poll, loop: ?*Loop, ext_size: c_uint) ?*Poll;
+};
+
+extern fn us_socket_get_native_handle(ssl: c_int, s: ?*us_socket_t) ?*anyopaque;
+extern fn us_socket_write(ssl: c_int, s: ?*us_socket_t, data: [*c]const u8, length: c_int, msg_more: c_int) c_int;
+extern fn us_socket_timeout(ssl: c_int, s: ?*us_socket_t, seconds: c_uint) void;
+extern fn us_socket_ext(ssl: c_int, s: ?*us_socket_t) ?*anyopaque;
+extern fn us_socket_context(ssl: c_int, s: ?*us_socket_t) ?*us_socket_context_t;
+extern fn us_socket_flush(ssl: c_int, s: ?*us_socket_t) void;
+extern fn us_socket_shutdown(ssl: c_int, s: ?*us_socket_t) void;
+extern fn us_socket_shutdown_read(ssl: c_int, s: ?*us_socket_t) void;
+extern fn us_socket_is_shut_down(ssl: c_int, s: ?*us_socket_t) c_int;
+extern fn us_socket_is_closed(ssl: c_int, s: ?*us_socket_t) c_int;
+extern fn us_socket_close(ssl: c_int, s: ?*us_socket_t, code: c_int, reason: ?*anyopaque) ?*us_socket_t;
+extern fn us_socket_local_port(ssl: c_int, s: ?*us_socket_t) c_int;
+extern fn us_socket_remote_address(ssl: c_int, s: ?*us_socket_t, buf: [*c]u8, length: [*c]c_int) void;
+pub const uws_app_s = opaque {};
+pub const uws_req_s = opaque {};
+pub const uws_websocket_s = opaque {};
+pub const uws_header_iterator_s = opaque {};
+pub const uws_app_t = uws_app_s;
+
+pub const uws_socket_context_s = opaque {};
+pub const uws_socket_context_t = uws_socket_context_s;
+pub const uws_websocket_t = uws_websocket_s;
+pub const uws_websocket_handler = ?fn (?*uws_websocket_t) callconv(.C) void;
+pub const uws_websocket_message_handler = ?fn (?*uws_websocket_t, [*c]const u8, usize, uws_opcode_t) callconv(.C) void;
+pub const uws_websocket_ping_pong_handler = ?fn (?*uws_websocket_t, [*c]const u8, usize) callconv(.C) void;
+pub const uws_websocket_close_handler = ?fn (?*uws_websocket_t, c_int, [*c]const u8, usize) callconv(.C) void;
+pub const uws_websocket_upgrade_handler = ?fn (*uws_res, ?*Request, ?*uws_socket_context_t) callconv(.C) void;
+pub const uws_socket_behavior_t = extern struct {
+ compression: uws_compress_options_t,
+ maxPayloadLength: c_uint,
+ idleTimeout: c_ushort,
+ maxBackpressure: c_uint,
+ closeOnBackpressureLimit: bool,
+ resetIdleTimeoutOnSend: bool,
+ sendPingsAutomatically: bool,
+ maxLifetime: c_ushort,
+ upgrade: uws_websocket_upgrade_handler,
+ open: uws_websocket_handler,
+ message: uws_websocket_message_handler,
+ drain: uws_websocket_handler,
+ ping: uws_websocket_ping_pong_handler,
+ pong: uws_websocket_ping_pong_handler,
+ close: uws_websocket_close_handler,
+};
+pub const uws_listen_handler = ?fn (?*listen_socket_t, uws_app_listen_config_t, ?*anyopaque) callconv(.C) void;
+pub const uws_method_handler = ?fn (*uws_res, *Request, ?*anyopaque) callconv(.C) void;
+pub const uws_filter_handler = ?fn (*uws_res, c_int, ?*anyopaque) callconv(.C) void;
+pub const uws_missing_server_handler = ?fn ([*c]const u8, ?*anyopaque) callconv(.C) void;
+
+pub const Request = opaque {
+ pub fn isAncient(req: *Request) bool {
+ return uws_req_is_ancient(req);
+ }
+ pub fn getYield(req: *Request) bool {
+ return uws_req_get_yield(req);
+ }
+ pub fn setYield(req: *Request, yield: bool) void {
+ uws_req_set_field(req, yield);
+ }
+ pub fn url(req: *Request) []const u8 {
+ var ptr: [*]const u8 = undefined;
+ return ptr[0..req.uws_req_get_url(&ptr)];
+ }
+ pub fn method(req: *Request) []const u8 {
+ var ptr: [*]const u8 = undefined;
+ return ptr[0..req.uws_req_get_method(&ptr)];
+ }
+ pub fn header(req: *Request, name: []const u8) []const u8 {
+ var ptr: [*]const u8 = undefined;
+ return ptr[0..req.uws_req_get_header(req, name.ptr, name.len, &ptr)];
+ }
+ pub fn query(req: *Request, name: []const u8) []const u8 {
+ var ptr: [*]const u8 = undefined;
+ return ptr[0..req.uws_req_get_query(req, name.ptr, name.len, &ptr)];
+ }
+ pub fn parameter(req: *Request, index: u16) []const u8 {
+ var ptr: [*]const u8 = undefined;
+ return ptr[0..req.uws_req_get_parameter(@intCast(c_ushort, index), &ptr)];
+ }
+ extern fn uws_req_is_ancient(res: *Request) bool;
+ extern fn uws_req_get_yield(res: *Request) bool;
+ extern fn uws_req_set_field(res: *Request, yield: bool) void;
+ extern fn uws_req_get_url(res: *Request, dest: *[*]const u8) usize;
+ extern fn uws_req_get_method(res: *Request, dest: *[*]const u8) usize;
+ extern fn uws_req_get_header(res: *Request, lower_case_header: *[*]const u8, lower_case_header_length: usize, dest: *[*]const u8) usize;
+ extern fn uws_req_get_query(res: *Request, key: [*c]const u8, key_length: usize, dest: *[*]const u8) usize;
+ extern fn uws_req_get_parameter(res: *Request, index: c_ushort, dest: *[*]const u8) usize;
+};
+
+const listen_socket_t = opaque {};
+extern fn us_listen_socket_close(ssl: c_int, ls: *listen_socket_t) void;
+
+pub fn NewApp(comptime ssl: bool) type {
+ return opaque {
+ const ssl_flag = @as(c_int, @boolToInt(ssl));
+ const ThisApp = @This();
+
+ pub fn create(opts: us_socket_context_options_t) *ThisApp {
+ return @ptrCast(*ThisApp, uws_create_app(ssl_flag, opts));
+ }
+ pub fn destroy(app: *ThisApp) void {
+ return uws_app_destroy(ssl_flag, @ptrCast(*uws_app_s, app));
+ }
+
+ fn RouteHandler(comptime UserDataType: type, comptime handler: fn (UserDataType, *Request, *Response) void) type {
+ return struct {
+ pub fn handle(res: *uws_res, req: *Request, user_data: ?*anyopaque) callconv(.C) void {
+ if (comptime UserDataType == void) {
+ return @call(
+ .{ .modifier = .always_inline },
+ handler,
+ .{
+ void{},
+ req,
+ @ptrCast(*Response, @alignCast(@alignOf(*Response), res)),
+ },
+ );
+ } else {
+ return @call(
+ .{ .modifier = .always_inline },
+ handler,
+ .{
+ @ptrCast(UserDataType, @alignCast(@alignOf(UserDataType), user_data.?)),
+ req,
+ @ptrCast(*Response, @alignCast(@alignOf(*Response), res)),
+ },
+ );
+ }
+ }
+ };
+ }
+
+ pub const ListenSocket = opaque {
+ pub inline fn close(this: *ListenSocket) void {
+ return us_listen_socket_close(ssl_flag, @ptrCast(*listen_socket_t, this));
+ }
+ };
+
+ pub fn get(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_get(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn post(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_post(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn options(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_options(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn delete(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_delete(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn patch(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_patch(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn put(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_put(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn head(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_head(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn connect(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_connect(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn trace(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_trace(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn any(
+ app: *ThisApp,
+ pattern: [:0]const u8,
+ comptime UserDataType: type,
+ user_data: UserDataType,
+ comptime handler: (fn (UserDataType, *Request, *Response) void),
+ ) void {
+ uws_app_any(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data);
+ }
+ pub fn run(app: *ThisApp) void {
+ return uws_app_run(ssl_flag, @ptrCast(*uws_app_t, app));
+ }
+ pub fn listen(
+ app: *ThisApp,
+ port: c_int,
+ comptime UserData: type,
+ user_data: UserData,
+ comptime handler: fn (UserData, ?*ListenSocket, uws_app_listen_config_t) void,
+ ) void {
+ const Wrapper = struct {
+ pub fn handle(socket: ?*listen_socket_t, conf: uws_app_listen_config_t, data: ?*anyopaque) callconv(.C) void {
+ if (comptime UserData == void) {
+ @call(.{ .modifier = .always_inline }, handler, .{ void{}, @ptrCast(?*ListenSocket, socket), conf });
+ } else {
+ @call(.{ .modifier = .always_inline }, handler, .{
+ @ptrCast(UserData, @alignCast(@alignOf(UserData), data.?)),
+ @ptrCast(?*ListenSocket, socket),
+ conf,
+ });
+ }
+ }
+ };
+ return uws_app_listen(ssl_flag, @ptrCast(*uws_app_t, app), port, Wrapper.handle, user_data);
+ }
+
+ pub fn listenWithConfig(
+ app: *ThisApp,
+ comptime UserData: type,
+ user_data: UserData,
+ comptime handler: fn (UserData, ?*ListenSocket, uws_app_listen_config_t) void,
+ config: uws_app_listen_config_t,
+ ) void {
+ const Wrapper = struct {
+ pub fn handle(socket: ?*listen_socket_t, conf: uws_app_listen_config_t, data: ?*anyopaque) callconv(.C) void {
+ if (comptime UserData == void) {
+ @call(.{ .modifier = .always_inline }, handler, .{ void{}, @ptrCast(?*ListenSocket, socket), conf });
+ } else {
+ @call(.{ .modifier = .always_inline }, handler, .{
+ @ptrCast(UserData, @alignCast(@alignOf(UserData), data.?)),
+ @ptrCast(?*ListenSocket, socket),
+ conf,
+ });
+ }
+ }
+ };
+ return uws_app_listen_with_config(ssl_flag, @ptrCast(*uws_app_t, app), config, Wrapper.handle, user_data);
+ }
+ pub fn constructorFailed(app: *ThisApp) bool {
+ return uws_constructor_failed(ssl_flag, app);
+ }
+ pub fn num_subscribers(app: *ThisApp, topic: [:0]const u8) c_uint {
+ return uws_num_subscribers(ssl_flag, @ptrCast(*uws_app_t, app), topic);
+ }
+ pub fn publish(app: *ThisApp, topic: []const u8, message: []const u8, opcode: uws_opcode_t, compress: bool) bool {
+ return uws_publish(ssl_flag, @ptrCast(*uws_app_t, app), topic.ptr, topic.len, message.ptr, message.len, opcode, compress);
+ }
+ pub fn getNativeHandle(app: *ThisApp) ?*anyopaque {
+ return uws_get_native_handle(ssl_flag, app);
+ }
+ pub fn removeServerName(app: *ThisApp, hostname_pattern: [:0]const u8) void {
+ return uws_remove_server_name(ssl_flag, @ptrCast(*uws_app_t, app), hostname_pattern);
+ }
+ pub fn addServerName(app: *ThisApp, hostname_pattern: [:0]const u8) void {
+ return uws_add_server_name(ssl_flag, @ptrCast(*uws_app_t, app), hostname_pattern);
+ }
+ pub fn addServerNameWithOptions(app: *ThisApp, hostname_pattern: [:0]const u8, opts: us_socket_context_options_t) void {
+ return uws_add_server_name_with_options(ssl_flag, @ptrCast(*uws_app_t, app), hostname_pattern, opts);
+ }
+ pub fn missingServerName(app: *ThisApp, handler: uws_missing_server_handler, user_data: ?*anyopaque) void {
+ return uws_missing_server_name(ssl_flag, @ptrCast(*uws_app_t, app), handler, user_data);
+ }
+ pub fn filter(app: *ThisApp, handler: uws_filter_handler, user_data: ?*anyopaque) void {
+ return uws_filter(ssl_flag, @ptrCast(*uws_app_t, app), handler, user_data);
+ }
+ pub fn ws(app: *ThisApp, pattern: [:0]const u8, behavior: uws_socket_behavior_t) void {
+ return uws_ws(ssl_flag, @ptrCast(*uws_app_t, app), pattern, behavior);
+ }
+
+ pub const Response = opaque {
+ inline fn castRes(res: *uws_res) *Response {
+ return @ptrCast(*Response, @alignCast(@alignOf(*Response), res));
+ }
+
+ pub inline fn downcast(res: *Response) *uws_res {
+ return @ptrCast(*uws_res, @alignCast(@alignOf(*uws_res), res));
+ }
+
+ pub fn end(res: *Response, data: []const u8, close_connection: bool) void {
+ uws_res_end(ssl_flag, res.downcast(), data.ptr, data.len, close_connection);
+ }
+ pub fn pause(res: *Response) void {
+ uws_res_pause(ssl_flag, res.downcast());
+ }
+ pub fn @"resume"(res: *Response) void {
+ uws_res_resume(ssl_flag, res.downcast());
+ }
+ pub fn writeContinue(res: *Response) void {
+ uws_res_write_continue(ssl_flag, res.downcast());
+ }
+ pub fn writeStatus(res: *Response, status: []const u8) void {
+ uws_res_write_status(ssl_flag, res.downcast(), status.ptr, status.len);
+ }
+ pub fn writeHeader(res: *Response, key: []const u8, value: []const u8) void {
+ uws_res_write_header(ssl_flag, res.downcast(), key.ptr, key.len, value.ptr, value.len);
+ }
+ pub fn writeHeaderInt(res: *Response, key: []const u8, value: u64) void {
+ uws_res_write_header(ssl_flag, res.downcast(), key.ptr, key.len, value);
+ }
+ pub fn endWithoutBody(res: *Response) void {
+ uws_res_end_without_body(ssl_flag, res.downcast());
+ }
+ pub fn write(res: *Response, data: []const u8) bool {
+ return uws_res_write(ssl_flag, res.downcast(), data.ptr, data.len);
+ }
+ pub fn getWriteOffset(res: *Response) uintmax_t {
+ return uws_res_get_write_offset(ssl_flag, res.downcast());
+ }
+ pub fn hasResponded(res: *Response) bool {
+ return uws_res_has_responded(ssl_flag, res.downcast());
+ }
+ pub fn onWritable(
+ res: *Response,
+ comptime UserDataType: type,
+ comptime handler: fn (*Response, uintmax_t, UserDataType) callconv(.C) bool,
+ user_data: UserDataType,
+ ) void {
+ const Wrapper = struct {
+ pub fn handle(this: *uws_res, amount: uintmax_t, data: ?*anyopaque) callconv(.C) void {
+ if (comptime UserDataType == void) {
+ @call(.{ .modifier = .always_inline }, handler, .{ void{}, castRes(this), amount });
+ } else {
+ @call(.{ .modifier = .always_inline }, handler, .{ @ptrCast(UserDataType, @alignCast(@alignOf(UserDataType), data.?)), castRes(this), amount });
+ }
+ }
+ };
+ uws_res_on_writable(ssl_flag, res.downcast(), Wrapper.handle, user_data);
+ }
+ pub fn onAborted(res: *Response, comptime UserDataType: type, comptime handler: fn (UserDataType, *Response) void, opcional_data: UserDataType) void {
+ const Wrapper = struct {
+ pub fn handle(this: *uws_res, user_data: ?*anyopaque) callconv(.C) void {
+ if (comptime UserDataType == void) {
+ @call(.{ .modifier = .always_inline }, handler, .{ void{}, castRes(this), void{} });
+ } else {
+ @call(.{ .modifier = .always_inline }, handler, .{ @ptrCast(UserDataType, @alignCast(@alignOf(UserDataType), user_data.?)), castRes(this) });
+ }
+ }
+ };
+ uws_res_on_aborted(ssl_flag, res.downcast(), Wrapper.handle, opcional_data);
+ }
+
+ pub fn onData(
+ res: *Response,
+ comptime UserDataType: type,
+ comptime handler: fn (*Response, chunk: []const u8, last: bool, UserDataType) void,
+ opcional_data: UserDataType,
+ ) void {
+ const Wrapper = struct {
+ pub fn handle(this: *uws_res, chunk_ptr: [*c]const u8, len: usize, last: bool, user_data: ?*anyopaque) callconv(.C) void {
+ if (comptime UserDataType == void) {
+ @call(.{ .modifier = .always_inline }, handler, .{
+ void{},
+ castRes(this),
+ chunk_ptr[0..len],
+ last,
+ });
+ } else {
+ @call(.{ .modifier = .always_inline }, handler, .{
+ @ptrCast(UserDataType, @alignCast(@alignOf(UserDataType), user_data.?)),
+ castRes(this),
+ chunk_ptr[0..len],
+ last,
+ });
+ }
+ }
+ };
+
+ uws_res_on_data(ssl_flag, res.downcast(), Wrapper.handle, opcional_data);
+ }
+ };
+ };
+}
+
+extern fn uws_create_app(ssl: c_int, options: us_socket_context_options_t) *uws_app_t;
+extern fn uws_app_destroy(ssl: c_int, app: *uws_app_t) void;
+extern fn uws_app_get(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_post(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_options(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_delete(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_patch(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_put(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_head(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_connect(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_trace(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_any(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_run(ssl: c_int, *uws_app_t) void;
+extern fn uws_app_listen(ssl: c_int, app: *uws_app_t, port: c_int, handler: uws_listen_handler, user_data: ?*anyopaque) void;
+extern fn uws_app_listen_with_config(ssl: c_int, app: *uws_app_t, config: uws_app_listen_config_t, handler: uws_listen_handler, user_data: ?*anyopaque) void;
+extern fn uws_constructor_failed(ssl: c_int, app: *uws_app_t) bool;
+extern fn uws_num_subscribers(ssl: c_int, app: *uws_app_t, topic: [*c]const u8) c_uint;
+extern fn uws_publish(ssl: c_int, app: *uws_app_t, topic: [*c]const u8, topic_length: usize, message: [*c]const u8, message_length: usize, opcode: uws_opcode_t, compress: bool) bool;
+extern fn uws_get_native_handle(ssl: c_int, app: *uws_app_t) ?*anyopaque;
+extern fn uws_remove_server_name(ssl: c_int, app: *uws_app_t, hostname_pattern: [*c]const u8) void;
+extern fn uws_add_server_name(ssl: c_int, app: *uws_app_t, hostname_pattern: [*c]const u8) void;
+extern fn uws_add_server_name_with_options(ssl: c_int, app: *uws_app_t, hostname_pattern: [*c]const u8, options: us_socket_context_options_t) void;
+extern fn uws_missing_server_name(ssl: c_int, app: *uws_app_t, handler: uws_missing_server_handler, user_data: ?*anyopaque) void;
+extern fn uws_filter(ssl: c_int, app: *uws_app_t, handler: uws_filter_handler, user_data: ?*anyopaque) void;
+extern fn uws_ws(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, behavior: uws_socket_behavior_t) void;
+
+extern fn uws_ws_get_user_data(ssl: c_int, ws: ?*uws_websocket_t) ?*anyopaque;
+extern fn uws_ws_close(ssl: c_int, ws: ?*uws_websocket_t) void;
+extern fn uws_ws_send(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, opcode: uws_opcode_t) uws_sendstatus_t;
+extern fn uws_ws_send_with_options(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, opcode: uws_opcode_t, compress: bool, fin: bool) uws_sendstatus_t;
+extern fn uws_ws_send_fragment(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, compress: bool) uws_sendstatus_t;
+extern fn uws_ws_send_first_fragment(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, compress: bool) uws_sendstatus_t;
+extern fn uws_ws_send_first_fragment_with_opcode(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, opcode: uws_opcode_t, compress: bool) uws_sendstatus_t;
+extern fn uws_ws_send_last_fragment(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, compress: bool) uws_sendstatus_t;
+extern fn uws_ws_end(ssl: c_int, ws: ?*uws_websocket_t, code: c_int, message: [*c]const u8, length: usize) void;
+extern fn uws_ws_cork(ssl: c_int, ws: ?*uws_websocket_t, handler: ?fn (?*anyopaque) callconv(.C) void, user_data: ?*anyopaque) void;
+extern fn uws_ws_subscribe(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, length: usize) bool;
+extern fn uws_ws_unsubscribe(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, length: usize) bool;
+extern fn uws_ws_is_subscribed(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, length: usize) bool;
+extern fn uws_ws_iterate_topics(ssl: c_int, ws: ?*uws_websocket_t, callback: ?fn ([*c]const u8, usize, ?*anyopaque) callconv(.C) void, user_data: ?*anyopaque) void;
+extern fn uws_ws_publish(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, topic_length: usize, message: [*c]const u8, message_length: usize) bool;
+extern fn uws_ws_publish_with_options(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, topic_length: usize, message: [*c]const u8, message_length: usize, opcode: uws_opcode_t, compress: bool) bool;
+extern fn uws_ws_get_buffered_amount(ssl: c_int, ws: ?*uws_websocket_t) c_uint;
+extern fn uws_ws_get_remote_address(ssl: c_int, ws: ?*uws_websocket_t, dest: [*c][*c]const u8) usize;
+extern fn uws_ws_get_remote_address_as_text(ssl: c_int, ws: ?*uws_websocket_t, dest: [*c][*c]const u8) usize;
+const uws_res = opaque {};
+extern fn uws_res_end(ssl: c_int, res: *uws_res, data: [*c]const u8, length: usize, close_connection: bool) void;
+extern fn uws_res_pause(ssl: c_int, res: *uws_res) void;
+extern fn uws_res_resume(ssl: c_int, res: *uws_res) void;
+extern fn uws_res_write_continue(ssl: c_int, res: *uws_res) void;
+extern fn uws_res_write_status(ssl: c_int, res: *uws_res, status: [*c]const u8, length: usize) void;
+extern fn uws_res_write_header(ssl: c_int, 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: c_int, res: *uws_res, key: [*c]const u8, key_length: usize, value: u64) void;
+extern fn uws_res_end_without_body(ssl: c_int, res: *uws_res) void;
+extern fn uws_res_write(ssl: c_int, res: *uws_res, data: [*c]const u8, length: usize) bool;
+extern fn uws_res_get_write_offset(ssl: c_int, res: *uws_res) uintmax_t;
+extern fn uws_res_has_responded(ssl: c_int, res: *uws_res) bool;
+extern fn uws_res_on_writable(ssl: c_int, res: *uws_res, handler: ?fn (*uws_res, uintmax_t, ?*anyopaque) callconv(.C) bool, user_data: ?*anyopaque) void;
+extern fn uws_res_on_aborted(ssl: c_int, res: *uws_res, handler: ?fn (*uws_res, ?*anyopaque) callconv(.C) void, opcional_data: ?*anyopaque) void;
+extern fn uws_res_on_data(
+ ssl: c_int,
+ res: *uws_res,
+ handler: ?fn (*uws_res, [*c]const u8, usize, bool, ?*anyopaque) callconv(.C) void,
+ opcional_data: ?*anyopaque,
+) void;
+extern fn uws_res_upgrade(
+ ssl: c_int,
+ res: *uws_res,
+ data: ?*anyopaque,
+ sec_web_socket_key: [*c]const u8,
+ sec_web_socket_key_length: usize,
+ sec_web_socket_protocol: [*c]const u8,
+ sec_web_socket_protocol_length: usize,
+ sec_web_socket_extensions: [*c]const u8,
+ sec_web_socket_extensions_length: usize,
+ ws: ?*uws_socket_context_t,
+) void;
+
+pub const LIBUS_RECV_BUFFER_LENGTH = @import("std").zig.c_translation.promoteIntLiteral(c_int, 524288, .decimal);
+pub const LIBUS_TIMEOUT_GRANULARITY = @as(c_int, 4);
+pub const LIBUS_RECV_BUFFER_PADDING = @as(c_int, 32);
+pub const LIBUS_EXT_ALIGNMENT = @as(c_int, 16);
+pub const LIBUS_SOCKET_DESCRIPTOR = c_int;
+
+pub const _COMPRESSOR_MASK: c_int = 255;
+pub const _DECOMPRESSOR_MASK: c_int = 3840;
+pub const DISABLED: c_int = 0;
+pub const SHARED_COMPRESSOR: c_int = 1;
+pub const SHARED_DECOMPRESSOR: c_int = 256;
+pub const DEDICATED_DECOMPRESSOR_32KB: c_int = 3840;
+pub const DEDICATED_DECOMPRESSOR_16KB: c_int = 3584;
+pub const DEDICATED_DECOMPRESSOR_8KB: c_int = 3328;
+pub const DEDICATED_DECOMPRESSOR_4KB: c_int = 3072;
+pub const DEDICATED_DECOMPRESSOR_2KB: c_int = 2816;
+pub const DEDICATED_DECOMPRESSOR_1KB: c_int = 2560;
+pub const DEDICATED_DECOMPRESSOR_512B: c_int = 2304;
+pub const DEDICATED_DECOMPRESSOR: c_int = 3840;
+pub const DEDICATED_COMPRESSOR_3KB: c_int = 145;
+pub const DEDICATED_COMPRESSOR_4KB: c_int = 146;
+pub const DEDICATED_COMPRESSOR_8KB: c_int = 163;
+pub const DEDICATED_COMPRESSOR_16KB: c_int = 180;
+pub const DEDICATED_COMPRESSOR_32KB: c_int = 197;
+pub const DEDICATED_COMPRESSOR_64KB: c_int = 214;
+pub const DEDICATED_COMPRESSOR_128KB: c_int = 231;
+pub const DEDICATED_COMPRESSOR_256KB: c_int = 248;
+pub const DEDICATED_COMPRESSOR: c_int = 248;
+pub const uws_compress_options_t = c_uint;
+pub const CONTINUATION: c_int = 0;
+pub const TEXT: c_int = 1;
+pub const BINARY: c_int = 2;
+pub const CLOSE: c_int = 8;
+pub const PING: c_int = 9;
+pub const PONG: c_int = 10;
+pub const uws_opcode_t = c_uint;
+pub const BACKPRESSURE: c_int = 0;
+pub const SUCCESS: c_int = 1;
+pub const DROPPED: c_int = 2;
+pub const uws_sendstatus_t = c_uint;
+pub const uws_app_listen_config_t = extern struct {
+ port: c_int,
+ host: [*c]const u8 = null,
+ options: c_int,
+};
diff --git a/src/http_client_async.zig b/src/http_client_async.zig
index 0f29b7638..27a046a9b 100644
--- a/src/http_client_async.zig
+++ b/src/http_client_async.zig
@@ -11,7 +11,7 @@ const stringZ = bun.stringZ;
const C = bun.C;
const std = @import("std");
const URL = @import("./url.zig").URL;
-const Method = @import("./http/method.zig").Method;
+pub const Method = @import("./http/method.zig").Method;
const Api = @import("./api/schema.zig").Api;
const Lock = @import("./lock.zig").Lock;
const HTTPClient = @This();
diff --git a/src/javascript/jsc/api/bun.zig b/src/javascript/jsc/api/bun.zig
index 64cc72ecc..d3b230243 100644
--- a/src/javascript/jsc/api/bun.zig
+++ b/src/javascript/jsc/api/bun.zig
@@ -954,6 +954,10 @@ pub const Class = NewClass(
.rfn = Bun.readAllStdinSync,
.ts = d.ts{},
},
+ .startServer = .{
+ .rfn = Bun.startServer,
+ .ts = d.ts{},
+ },
},
.{
.main = .{
@@ -1001,6 +1005,28 @@ pub const Class = NewClass(
},
);
+pub fn startServer(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSObjectRef,
+ _: js.JSObjectRef,
+ arguments: []const js.JSValueRef,
+ _: js.ExceptionRef,
+) js.JSValueRef {
+ var vm = JSC.VirtualMachine.vm;
+ const handler = if (arguments.len > 0) JSC.JSValue.fromRef(arguments[0]) else JSC.JSValue.zero;
+ if (handler.isEmpty() or handler.isUndefinedOrNull() or !handler.isCell() or !handler.isCallable(ctx.ptr().vm())) {
+ Output.prettyWarnln("\"serverless\" export should be a function", .{});
+ Output.flush();
+ return JSC.JSValue.jsUndefined().asObjectRef();
+ }
+
+ JSC.C.JSValueProtect(ctx.ptr().ref(), handler.asObjectRef());
+ var server = JSC.API.Server.init(vm.bundler.options.origin.getPortAuto(), handler, ctx.ptr());
+ server.listen();
+ return JSC.JSValue.jsUndefined().asObjectRef();
+}
+
pub fn allocUnsafe(
_: void,
ctx: js.JSContextRef,
diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig
new file mode 100644
index 000000000..4b7805adb
--- /dev/null
+++ b/src/javascript/jsc/api/server.zig
@@ -0,0 +1,320 @@
+const Bun = @This();
+const default_allocator = @import("../../../global.zig").default_allocator;
+const bun = @import("../../../global.zig");
+const Environment = bun.Environment;
+const NetworkThread = @import("http").NetworkThread;
+const Global = bun.Global;
+const strings = bun.strings;
+const string = bun.string;
+const Output = @import("../../../global.zig").Output;
+const MutableString = @import("../../../global.zig").MutableString;
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const IdentityContext = @import("../../../identity_context.zig").IdentityContext;
+const Fs = @import("../../../fs.zig");
+const Resolver = @import("../../../resolver/resolver.zig");
+const ast = @import("../../../import_record.zig");
+const NodeModuleBundle = @import("../../../node_module_bundle.zig").NodeModuleBundle;
+const MacroEntryPoint = @import("../../../bundler.zig").MacroEntryPoint;
+const logger = @import("../../../logger.zig");
+const Api = @import("../../../api/schema.zig").Api;
+const options = @import("../../../options.zig");
+const Bundler = @import("../../../bundler.zig").Bundler;
+const ServerEntryPoint = @import("../../../bundler.zig").ServerEntryPoint;
+const js_printer = @import("../../../js_printer.zig");
+const js_parser = @import("../../../js_parser.zig");
+const js_ast = @import("../../../js_ast.zig");
+const hash_map = @import("../../../hash_map.zig");
+const http = @import("../../../http.zig");
+const NodeFallbackModules = @import("../../../node_fallbacks.zig");
+const ImportKind = ast.ImportKind;
+const Analytics = @import("../../../analytics/analytics_thread.zig");
+const ZigString = @import("../../../jsc.zig").ZigString;
+const Runtime = @import("../../../runtime.zig");
+const Router = @import("./router.zig");
+const ImportRecord = ast.ImportRecord;
+const DotEnv = @import("../../../env_loader.zig");
+const ParseResult = @import("../../../bundler.zig").ParseResult;
+const PackageJSON = @import("../../../resolver/package_json.zig").PackageJSON;
+const MacroRemap = @import("../../../resolver/package_json.zig").MacroMap;
+const WebCore = @import("../../../jsc.zig").WebCore;
+const Request = WebCore.Request;
+const Response = WebCore.Response;
+const Headers = WebCore.Headers;
+const Fetch = WebCore.Fetch;
+const HTTP = @import("http");
+const FetchEvent = WebCore.FetchEvent;
+const js = @import("../../../jsc.zig").C;
+const JSC = @import("../../../jsc.zig");
+const JSError = @import("../base.zig").JSError;
+const d = @import("../base.zig").d;
+const MarkedArrayBuffer = @import("../base.zig").MarkedArrayBuffer;
+const getAllocator = @import("../base.zig").getAllocator;
+const JSValue = @import("../../../jsc.zig").JSValue;
+const NewClass = @import("../base.zig").NewClass;
+const Microtask = @import("../../../jsc.zig").Microtask;
+const JSGlobalObject = @import("../../../jsc.zig").JSGlobalObject;
+const ExceptionValueRef = @import("../../../jsc.zig").ExceptionValueRef;
+const JSPrivateDataPtr = @import("../../../jsc.zig").JSPrivateDataPtr;
+const ZigConsoleClient = @import("../../../jsc.zig").ZigConsoleClient;
+const Node = @import("../../../jsc.zig").Node;
+const ZigException = @import("../../../jsc.zig").ZigException;
+const ZigStackTrace = @import("../../../jsc.zig").ZigStackTrace;
+const ErrorableResolvedSource = @import("../../../jsc.zig").ErrorableResolvedSource;
+const ResolvedSource = @import("../../../jsc.zig").ResolvedSource;
+const JSPromise = @import("../../../jsc.zig").JSPromise;
+const JSInternalPromise = @import("../../../jsc.zig").JSInternalPromise;
+const JSModuleLoader = @import("../../../jsc.zig").JSModuleLoader;
+const JSPromiseRejectionOperation = @import("../../../jsc.zig").JSPromiseRejectionOperation;
+const Exception = @import("../../../jsc.zig").Exception;
+const ErrorableZigString = @import("../../../jsc.zig").ErrorableZigString;
+const ZigGlobalObject = @import("../../../jsc.zig").ZigGlobalObject;
+const VM = @import("../../../jsc.zig").VM;
+const JSFunction = @import("../../../jsc.zig").JSFunction;
+const Config = @import("../config.zig");
+const URL = @import("../../../url.zig").URL;
+const Transpiler = @import("./transpiler.zig");
+const VirtualMachine = @import("../javascript.zig").VirtualMachine;
+const IOTask = JSC.IOTask;
+const is_bindgen = JSC.is_bindgen;
+const uws = @import("uws");
+
+pub fn NewServer(comptime ssl_enabled: bool) type {
+ return struct {
+ const ThisServer = @This();
+ const RequestContextStackAllocator = std.heap.StackFallbackAllocator(@sizeOf(RequestContext) * 2048 + 4096);
+
+ pub const App = uws.NewApp(ssl_enabled);
+
+ listener: ?*App.ListenSocket = null,
+ callback: JSC.JSValue = JSC.JSValue.zero,
+ port: u16 = 3000,
+ app: *App = undefined,
+ globalThis: *JSGlobalObject,
+ default_server: URL = URL{ .host = "localhost", .port = "3000" },
+
+ request_pool_allocator: std.mem.Allocator = undefined,
+
+ pub fn init(port: u16, callback: JSC.JSValue, globalThis: *JSGlobalObject) *ThisServer {
+ var server = bun.default_allocator.create(ThisServer) catch @panic("Out of memory!");
+ server.* = .{
+ .port = port,
+ .callback = callback,
+ .globalThis = globalThis,
+ };
+ RequestContext.pool = bun.default_allocator.create(RequestContextStackAllocator) catch @panic("Out of memory!");
+ server.request_pool_allocator = RequestContext.pool.get();
+ return server;
+ }
+
+ pub fn onListen(this: *ThisServer, socket: ?*App.ListenSocket, _: uws.uws_app_listen_config_t) void {
+ if (socket == null) {
+ Output.prettyErrorln("Failed to start socket", .{});
+ Output.flush();
+ return;
+ }
+
+ this.listener = socket;
+ VirtualMachine.vm.uws_event_loop = uws.Loop.get();
+ this.app.run();
+ }
+
+ pub const RequestContext = struct {
+ server: *ThisServer,
+ resp: *App.Response,
+ req: *uws.Request,
+ url: string,
+ method: HTTP.Method,
+ aborted: bool = false,
+ response_jsvalue: JSC.JSValue = JSC.JSValue.zero,
+ blob: JSC.WebCore.Blob = JSC.WebCore.Blob{},
+ promise: ?*JSC.JSValue = null,
+ response_headers: ?*JSC.WebCore.Headers.RefCountedHeaders = null,
+
+ pub threadlocal var pool: *RequestContextStackAllocator = undefined;
+
+ pub fn onResolve(
+ ctx: *RequestContext,
+ _: *JSC.JSGlobalObject,
+ arguments: []const JSC.JSValue,
+ ) void {
+ if (ctx.aborted) {
+ ctx.finalize();
+ return;
+ }
+
+ if (arguments.len == 0) {
+ ctx.req.setYield(true);
+ ctx.finalize();
+ return;
+ }
+
+ var response = arguments[0].as(JSC.WebCore.Response) orelse {
+ Output.prettyErrorln("Expected serverless to return a Response", .{});
+ ctx.req.setYield(true);
+ ctx.finalize();
+ return;
+ };
+ ctx.render(response);
+ }
+
+ pub fn onReject(
+ ctx: *RequestContext,
+ _: *JSC.JSGlobalObject,
+ arguments: []const JSC.JSValue,
+ ) void {
+ if (ctx.aborted) {
+ ctx.finalize();
+ return;
+ }
+
+ JSC.VirtualMachine.vm.defaultErrorHandler(arguments[0], null);
+ ctx.req.setYield(true);
+ ctx.finalize();
+ }
+
+ pub fn create(this: *RequestContext, server: *ThisServer, req: *uws.Request, resp: *App.Response) void {
+ this.* = .{
+ .resp = resp,
+ .req = req,
+ .url = req.url(),
+ .method = HTTP.Method.which(req.method()) orelse .GET,
+ .server = server,
+ };
+ resp.onAborted(*RequestContext, onAbort, this);
+ }
+
+ pub fn onAbort(this: *RequestContext, _: *App.Response) void {
+ this.aborted = true;
+ this.req = undefined;
+ if (!this.response_jsvalue.isEmpty()) {
+ JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.response_jsvalue.asObjectRef());
+ this.response_jsvalue = JSC.JSValue.zero;
+ }
+ }
+
+ pub fn finalize(this: *RequestContext) void {
+ this.blob.detach();
+ if (!this.response_jsvalue.isEmpty()) {
+ JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.response_jsvalue.asObjectRef());
+ this.response_jsvalue = JSC.JSValue.zero;
+ }
+
+ if (this.promise != null) {
+ JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.promise.?.asObjectRef());
+ this.promise = null;
+ }
+
+ if (this.response_headers != null) {
+ this.response_headers.?.deref();
+ this.response_headers = null;
+ }
+
+ this.server.request_pool_allocator.destroy(this);
+ }
+
+ pub fn render(this: *RequestContext, response: *JSC.WebCore.Response) void {
+ if (this.aborted) {
+ return;
+ }
+
+ this.blob = response.body.use();
+ const status = response.statusCode();
+
+ if (response.body.init.headers) |headers_| {
+ var headers: *JSC.WebCore.Headers = headers_.get();
+ defer headers_.deref();
+ var entries = headers.entries.slice();
+ const names = entries.items(.name);
+ const values = entries.items(.value);
+
+ var status_text_buf: [48]u8 = undefined;
+
+ if (status == 302) {
+ this.resp.writeStatus("302 Found");
+ } else {
+ this.resp.writeStatus(std.fmt.bufPrint(&status_text_buf, "{d} HM", .{response.body.init.status_code}) catch unreachable);
+ }
+
+ for (names) |name, i| {
+ this.resp.writeHeader(headers.asStr(name), headers.asStr(values[i]));
+ }
+ }
+
+ if (status == 302 or status == 202 or this.blob.size == 0) {
+ this.resp.endWithoutBody();
+ this.finalize();
+ return;
+ }
+
+ this.resp.end(this.blob.sharedView(), false);
+ this.finalize();
+ }
+ };
+
+ pub fn onRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void {
+ req.setYield(false);
+ var ctx = this.request_pool_allocator.create(RequestContext) catch @panic("ran out of memory");
+ ctx.create(this, req, resp);
+
+ var request_object = bun.default_allocator.create(JSC.WebCore.Request) catch unreachable;
+ request_object.* = .{
+ .url = JSC.ZigString.init(ctx.url),
+ .method = ctx.method,
+ };
+ var args = [_]JSC.C.JSValueRef{JSC.WebCore.Request.Class.make(this.globalThis.ref(), request_object)};
+ ctx.response_jsvalue = JSC.C.JSObjectCallAsFunctionReturnValue(this.globalThis.ref(), this.callback.asObjectRef(), null, 1, &args);
+ defer JSC.VirtualMachine.vm.tick();
+ if (ctx.aborted) {
+ ctx.finalize();
+
+ return;
+ }
+
+ if (ctx.response_jsvalue.isUndefinedOrNull()) {
+ req.setYield(true);
+ ctx.finalize();
+ return;
+ }
+
+ JSC.C.JSValueProtect(this.globalThis.ref(), ctx.response_jsvalue.asObjectRef());
+
+ if (ctx.response_jsvalue.as(JSC.WebCore.Response)) |response| {
+ ctx.render(response);
+
+ return;
+ }
+
+ if (ctx.response_jsvalue.jsTypeLoose() == .JSPromise) {
+ JSC.VirtualMachine.vm.tick();
+
+ ctx.response_jsvalue.then(
+ this.globalThis,
+ RequestContext,
+ ctx,
+ RequestContext.onResolve,
+ RequestContext.onReject,
+ );
+ }
+
+ // switch (ctx.response_jsvalue.jsTypeLoose()) {
+ // .JSPromise => {
+ // JSPromise.
+ // },
+ // }
+ }
+
+ pub fn listen(this: *ThisServer) void {
+ this.app = App.create(.{});
+ this.app.any("/*", *ThisServer, this, onRequest);
+ this.app.listenWithConfig(*ThisServer, this, onListen, .{
+ .port = this.default_server.getPort().?,
+ .host = bun.default_allocator.dupeZ(u8, this.default_server.displayHostname()) catch unreachable,
+ .options = 0,
+ });
+ }
+ };
+}
+
+pub const Server = NewServer(false);
+pub const SSLServer = NewServer(true);
diff --git a/src/javascript/jsc/bindings/BunBuiltinNames.h b/src/javascript/jsc/bindings/BunBuiltinNames.h
index 709ab28a5..9619f62a6 100644
--- a/src/javascript/jsc/bindings/BunBuiltinNames.h
+++ b/src/javascript/jsc/bindings/BunBuiltinNames.h
@@ -72,6 +72,14 @@ using namespace JSC;
macro(delimiter) \
macro(toNamespacedPath) \
macro(isWindows) \
+ macro(get) \
+ macro(put) \
+ macro(post) \
+ macro(patch) \
+ macro(trace) \
+ macro(connect) \
+ macro(options) \
+ macro(port) \
BUN_ADDITIONAL_PRIVATE_IDENTIFIERS(macro) \
class BunBuiltinNames {
diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
index 4c6a0f9c2..cf853e2d4 100644
--- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp
+++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
@@ -557,7 +557,8 @@ static JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve,
}
}
-extern "C" void Bun__reportError(JSC::JSGlobalObject*, JSC__JSValue);
+extern "C" void Bun__reportError(JSC__JSGlobalObject*, JSC__JSValue);
+
static JSC_DECLARE_HOST_FUNCTION(functionReportError);
static JSC_DEFINE_HOST_FUNCTION(functionReportError,
(JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp
index 112ca81b7..85f7e6f1e 100644
--- a/src/javascript/jsc/bindings/bindings.cpp
+++ b/src/javascript/jsc/bindings/bindings.cpp
@@ -246,6 +246,45 @@ unsigned char JSC__JSValue__jsType(JSC__JSValue JSValue0)
return 0;
}
+// TODO: prevent this from allocating so much memory
+void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* ctx, void (*ArgFn3)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3), void (*ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3))
+{
+
+ JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create(
+ globalObject->vm(), globalObject, 1, String(), [ctx, ArgFn3](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> JSC::EncodedJSValue {
+ auto argCount = static_cast<uint16_t>(callFrame->argumentCount());
+ WTF::Vector<JSC::EncodedJSValue, 16> arguments;
+ arguments.reserveInitialCapacity(argCount);
+ if (argCount) {
+ for (uint16_t i = 0; i < argCount; ++i) {
+ arguments.uncheckedAppend(JSC::JSValue::encode(callFrame->uncheckedArgument(i)));
+ }
+ }
+
+ ArgFn3(globalObject, ctx, reinterpret_cast<JSC__JSValue>(arguments.data()), argCount);
+ return JSC::JSValue::encode(JSC::jsUndefined());
+ });
+ JSC::JSNativeStdFunction* rejecterFunction = JSC::JSNativeStdFunction::create(
+ globalObject->vm(), globalObject, 1, String(),
+ [ctx, ArgFn4](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> JSC::EncodedJSValue {
+ auto argCount = static_cast<uint16_t>(callFrame->argumentCount());
+ WTF::Vector<JSC::EncodedJSValue, 16> arguments;
+ arguments.reserveInitialCapacity(argCount);
+ if (argCount) {
+ for (uint16_t i = 0; i < argCount; ++i) {
+ arguments.uncheckedAppend(JSC::JSValue::encode(callFrame->uncheckedArgument(i)));
+ }
+ }
+
+ ArgFn4(globalObject, ctx, reinterpret_cast<JSC__JSValue>(arguments.data()), argCount);
+ return JSC::JSValue::encode(JSC::jsUndefined());
+ });
+
+ globalObject->vm().drainMicrotasks();
+ JSC::JSPromise* promise = JSC::jsDynamicCast<JSC::JSPromise*>(globalObject->vm(), JSC::JSValue::decode(JSValue0).asCell());
+ promise->performPromiseThen(globalObject, resolverFunction, rejecterFunction, JSC::jsUndefined());
+}
+
JSC__JSValue JSC__JSValue__parseJSON(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1)
{
JSC::JSValue jsValue = JSC::JSValue::decode(JSValue0);
@@ -728,10 +767,8 @@ JSC__JSValue JSC__JSGlobalObject__createAggregateError(JSC__JSGlobalObject* glob
}
JSC::Structure* errorStructure = globalObject->errorStructure(JSC::ErrorType::AggregateError);
- scope.release();
- return JSC::JSValue::encode(JSC::createAggregateError(
- globalObject, vm, errorStructure, array, message, options, nullptr, JSC::TypeNothing, false));
+ RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::createAggregateError(globalObject, vm, errorStructure, array, message, options, nullptr, JSC::TypeNothing, false)));
}
// static JSC::JSNativeStdFunction* resolverFunction;
// static JSC::JSNativeStdFunction* rejecterFunction;
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig
index 88ecb6bfe..da65d38d5 100644
--- a/src/javascript/jsc/bindings/bindings.zig
+++ b/src/javascript/jsc/bindings/bindings.zig
@@ -2179,6 +2179,48 @@ pub const JSValue = enum(u64) {
return cppFn("symbolKeyFor", .{ this, global, str });
}
+ const Thenable = fn (
+ global: [*c]JSGlobalObject,
+ ctx: ?*anyopaque,
+ arguments_ptr: JSC.JSValue,
+ arguments_len: usize,
+ ) callconv(.C) void;
+ pub fn _then(this: JSValue, global: *JSGlobalObject, ctx: ?*anyopaque, resolve: Thenable, reject: Thenable) void {
+ return cppFn("_then", .{ this, global, ctx, resolve, reject });
+ }
+ pub fn then(this: JSValue, global: *JSGlobalObject, comptime Then: type, ctx: *Then, comptime onResolve: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void, comptime onReject: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void) void {
+ const Handler = struct {
+ fn resolve(
+ globalThis: [*c]JSGlobalObject,
+ ptr: ?*anyopaque,
+ arguments_ptr_: JSC.JSValue,
+ arguments_len: usize,
+ ) callconv(.C) void {
+ @setRuntimeSafety(false);
+ var arguments_ptr = @intToPtr([*]const JSC.JSValue, @enumToInt(arguments_ptr_));
+ onResolve(bun.cast(*Then, ptr.?), globalThis, arguments_ptr[0..arguments_len]);
+ }
+
+ pub fn reject(
+ globalThis: [*c]JSGlobalObject,
+ ptr: ?*anyopaque,
+ arguments_ptr_: JSC.JSValue,
+ arguments_len: usize,
+ ) callconv(.C) void {
+ @setRuntimeSafety(false);
+ var arguments_ptr = @intToPtr([*]const JSC.JSValue, @enumToInt(arguments_ptr_));
+ onReject(bun.cast(*Then, ptr.?), globalThis, arguments_ptr[0..arguments_len]);
+ }
+ };
+
+ this._then(
+ global,
+ ctx,
+ Handler.resolve,
+ Handler.reject,
+ );
+ }
+
pub fn getDescription(this: JSValue, global: *JSGlobalObject) ZigString {
var zig_str = ZigString.init("");
getSymbolDescription(this, global, &zig_str);
@@ -2314,7 +2356,7 @@ pub const JSValue = enum(u64) {
return @intToPtr(*anyopaque, @enumToInt(this));
}
- pub const Extern = [_][]const u8{ "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "getReadableStreamState", "getWritableStreamState", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" };
+ pub const Extern = [_][]const u8{ "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "getReadableStreamState", "getWritableStreamState", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" };
};
extern "c" fn Microtask__run(*Microtask, *JSGlobalObject) void;
diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h
index ba8175a74..3e8e7af5d 100644
--- a/src/javascript/jsc/bindings/headers-cpp.h
+++ b/src/javascript/jsc/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1647600299
+//-- AUTOGENERATED FILE -- 1647769923
// clang-format off
#pragma once
diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h
index 1d36062da..fb72e3798 100644
--- a/src/javascript/jsc/bindings/headers.h
+++ b/src/javascript/jsc/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format: off
-//-- AUTOGENERATED FILE -- 1647600299
+//-- AUTOGENERATED FILE -- 1647769923
#pragma once
#include <stddef.h>
@@ -426,6 +426,7 @@ CPP_DECL size_t WTF__String__length(WTF__String* arg0);
#pragma mark - JSC::JSValue
+CPP_DECL void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, void* arg2, void (* ArgFn3)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3), void (* ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3));
CPP_DECL bool JSC__JSValue__asArrayBuffer_(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, Bun__ArrayBuffer* arg2);
CPP_DECL JSC__JSCell* JSC__JSValue__asCell(JSC__JSValue JSValue0);
CPP_DECL JSC__JSInternalPromise* JSC__JSValue__asInternalPromise(JSC__JSValue JSValue0);
diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig
index f9d09821a..f920c74d9 100644
--- a/src/javascript/jsc/bindings/headers.zig
+++ b/src/javascript/jsc/bindings/headers.zig
@@ -274,6 +274,7 @@ pub extern fn WTF__String__isEmpty(arg0: [*c]WTF__String) bool;
pub extern fn WTF__String__isExternal(arg0: [*c]WTF__String) bool;
pub extern fn WTF__String__isStatic(arg0: [*c]WTF__String) bool;
pub extern fn WTF__String__length(arg0: [*c]WTF__String) usize;
+pub extern fn JSC__JSValue___then(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?fn ([*c]JSC__JSGlobalObject, ?*anyopaque, JSC__JSValue, usize) callconv(.C) void, ArgFn4: ?fn ([*c]JSC__JSGlobalObject, ?*anyopaque, JSC__JSValue, usize) callconv(.C) void) void;
pub extern fn JSC__JSValue__asArrayBuffer_(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c]Bun__ArrayBuffer) bool;
pub extern fn JSC__JSValue__asCell(JSValue0: JSC__JSValue) [*c]JSC__JSCell;
pub extern fn JSC__JSValue__asInternalPromise(JSValue0: JSC__JSValue) [*c]JSC__JSInternalPromise;
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 7bd8e0244..4a8fefd3c 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -422,6 +422,7 @@ pub const SavedSourceMap = struct {
return SourceMap.Mapping.find(mappings, line, column);
}
};
+const uws = @import("uws");
// If you read JavascriptCore/API/JSVirtualMachine.mm - https://github.com/WebKit/WebKit/blob/acff93fb303baa670c055cb24c2bad08691a01a0/Source/JavaScriptCore/API/JSVirtualMachine.mm#L101
// We can see that it's sort of like std.mem.Allocator but for JSGlobalContextRef, to support Automatic Reference Counting
@@ -450,6 +451,7 @@ pub const VirtualMachine = struct {
node_fs: ?*Node.NodeFS = null,
has_loaded_node_modules: bool = false,
timer: Bun.Timer = Bun.Timer{},
+ uws_event_loop: ?*uws.Loop = null,
arena: *Arena = undefined,
has_loaded: bool = false,
@@ -596,6 +598,9 @@ pub const VirtualMachine = struct {
this.concurrent_lock.lock();
defer this.concurrent_lock.unlock();
this.concurrent_tasks.writeItem(task) catch unreachable;
+ if (this.virtual_machine.uws_event_loop) |loop| {
+ loop.nextTick(*EventLoop, this, EventLoop.tick);
+ }
_ = this.ready_tasks_count.fetchAdd(1, .Monotonic);
}
};
@@ -728,7 +733,6 @@ pub const VirtualMachine = struct {
.origin_timer = std.time.Timer.start() catch @panic("Please don't mess with timers."),
.ref_strings = JSC.RefString.Map.init(allocator),
};
-
VirtualMachine.vm.regular_event_loop.tasks = EventLoop.Queue.init(
default_allocator,
);
diff --git a/src/javascript/jsc/node/node_fs.zig b/src/javascript/jsc/node/node_fs.zig
index 0c47d3aa9..b7aacbf97 100644
--- a/src/javascript/jsc/node/node_fs.zig
+++ b/src/javascript/jsc/node/node_fs.zig
@@ -2168,7 +2168,7 @@ const Arguments = struct {
};
};
-pub const Constants = struct {
+const Constants = struct {
// File Access Constants
/// Constant for fs.access(). File is visible to the calling process.
pub const F_OK = std.os.F_OK;
diff --git a/src/jsc.zig b/src/jsc.zig
index cd1744f21..e159441bb 100644
--- a/src/jsc.zig
+++ b/src/jsc.zig
@@ -21,6 +21,8 @@ pub const Cloudflare = struct {
pub const Jest = @import("./javascript/jsc/test/jest.zig");
pub const API = struct {
pub const Transpiler = @import("./javascript/jsc/api/transpiler.zig");
+ pub const Server = @import("./javascript/jsc/api/server.zig").Server;
+ pub const SSLServer = @import("./javascript/jsc/api/server.zig").SSLServer;
pub const Bun = @import("./javascript/jsc/api/bun.zig");
pub const Router = @import("./javascript/jsc/api/router.zig");
};
diff --git a/src/runtime.footer.bun.js b/src/runtime.footer.bun.js
index a7f7942bd..9415ede08 100644
--- a/src/runtime.footer.bun.js
+++ b/src/runtime.footer.bun.js
@@ -15,3 +15,5 @@ export var $$bun_runtime_json_parse = JSON.parse;
export var __internalIsCommonJSNamespace =
BUN_RUNTIME.__internalIsCommonJSNamespace;
globalThis.require ||= BUN_RUNTIME.__require;
+globalThis.__internalIsCommonJSNamespace ||=
+ BUN_RUNTIME.__internalIsCommonJSNamespace;