aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js
diff options
context:
space:
mode:
authorGravatar dave caruso <me@paperdave.net> 2023-09-29 03:39:26 -0700
committerGravatar GitHub <noreply@github.com> 2023-09-29 03:39:26 -0700
commit6afa78120ac0512bc55d00a8a1562d8f0eafa2c2 (patch)
tree6a413589452d966f42c1e97e39fd11a82308e565 /src/bun.js
parent6514dcf4cbc63cff89f3cac59598872caf776f0b (diff)
downloadbun-6afa78120ac0512bc55d00a8a1562d8f0eafa2c2.tar.gz
bun-6afa78120ac0512bc55d00a8a1562d8f0eafa2c2.tar.zst
bun-6afa78120ac0512bc55d00a8a1562d8f0eafa2c2.zip
feat(runtime): implement `server.requestIp` + node:http `socket.address()` (#6165)
* [server] requestIp and AnyRequestContext Changed Request.uws_request to the new AnyRequestContext. This allows grabbing the IP from a Request. Unfinished. * [server] basic `requestIp` implementation Currently using uws's requestIpAsText, which always returns a ipv6 string. We should return a `SocketAddress` object to the user instead, which will contain the formatted address string and what type it is. We'll have to use requestIpAsBinary and parse that ourselves. * TypeScript docs, use `bun.String`, return `undefined` instead of `null` if we can't get the ip. * binary address formatting * uws getRemoteAddress binding * remove dead code * working * final touches:sparkles: * I will abide by the results of this poll. --------- Co-authored-by: Parzival-3141 <29632054+Parzival-3141@users.noreply.github.com>
Diffstat (limited to 'src/bun.js')
-rw-r--r--src/bun.js/api/server.classes.ts4
-rw-r--r--src/bun.js/api/server.zig135
-rw-r--r--src/bun.js/bindings/JSSocketAddress.cpp61
-rw-r--r--src/bun.js/bindings/JSSocketAddress.h19
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.cpp128
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp7
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.h2
-rw-r--r--src/bun.js/bindings/generated_classes.zig12
-rw-r--r--src/bun.js/webcore/request.zig12
9 files changed, 354 insertions, 26 deletions
diff --git a/src/bun.js/api/server.classes.ts b/src/bun.js/api/server.classes.ts
index 544f37ce6..80449ed27 100644
--- a/src/bun.js/api/server.classes.ts
+++ b/src/bun.js/api/server.classes.ts
@@ -24,6 +24,10 @@ function generate(name) {
fn: "doStop",
length: 1,
},
+ requestIP: {
+ fn: "doRequestIP",
+ length: 1,
+ },
port: {
getter: "getPort",
},
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index fd6cc1f2b..9d4a8a133 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -1125,6 +1125,92 @@ fn NewFlags(comptime debug_mode: bool) type {
};
}
+/// A generic wrapper for the HTTP(s) Server`RequestContext`s.
+/// Only really exists because of `NewServer()` and `NewRequestContext()` generics.
+pub const AnyRequestContext = struct {
+ pub const Pointer = bun.TaggedPointerUnion(.{
+ HTTPServer.RequestContext,
+ HTTPSServer.RequestContext,
+ DebugHTTPServer.RequestContext,
+ DebugHTTPSServer.RequestContext,
+ });
+
+ tagged_pointer: Pointer,
+
+ pub const Null = .{ .tagged_pointer = Pointer.Null };
+
+ pub fn init(request_ctx: anytype) AnyRequestContext {
+ return .{ .tagged_pointer = Pointer.init(request_ctx) };
+ }
+
+ pub fn getRemoteSocketInfo(self: AnyRequestContext) ?uws.SocketAddress {
+ if (self.tagged_pointer.isNull()) {
+ return null;
+ }
+
+ switch (self.tagged_pointer.tag()) {
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(HTTPServer.RequestContext))) => {
+ return self.tagged_pointer.as(HTTPServer.RequestContext).getRemoteSocketInfo();
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(HTTPSServer.RequestContext))) => {
+ return self.tagged_pointer.as(HTTPSServer.RequestContext).getRemoteSocketInfo();
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(DebugHTTPServer.RequestContext))) => {
+ return self.tagged_pointer.as(DebugHTTPServer.RequestContext).getRemoteSocketInfo();
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(DebugHTTPSServer.RequestContext))) => {
+ return self.tagged_pointer.as(DebugHTTPSServer.RequestContext).getRemoteSocketInfo();
+ },
+ else => @panic("Unexpected AnyRequestContext tag"),
+ }
+ }
+
+ /// Wont actually set anything if `self` is `.none`
+ pub fn setRequest(self: AnyRequestContext, req: *uws.Request) void {
+ if (self.tagged_pointer.isNull()) {
+ return;
+ }
+
+ switch (self.tagged_pointer.tag()) {
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(HTTPServer.RequestContext))) => {
+ self.tagged_pointer.as(HTTPServer.RequestContext).req = req;
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(HTTPSServer.RequestContext))) => {
+ self.tagged_pointer.as(HTTPSServer.RequestContext).req = req;
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(DebugHTTPServer.RequestContext))) => {
+ self.tagged_pointer.as(DebugHTTPServer.RequestContext).req = req;
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(DebugHTTPSServer.RequestContext))) => {
+ self.tagged_pointer.as(DebugHTTPSServer.RequestContext).req = req;
+ },
+ else => @panic("Unexpected AnyRequestContext tag"),
+ }
+ }
+
+ pub fn getRequest(self: AnyRequestContext) ?*uws.Request {
+ if (self.tagged_pointer.isNull()) {
+ return null;
+ }
+
+ switch (self.tagged_pointer.tag()) {
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(HTTPServer.RequestContext))) => {
+ return self.tagged_pointer.as(HTTPServer.RequestContext).req;
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(HTTPSServer.RequestContext))) => {
+ return self.tagged_pointer.as(HTTPSServer.RequestContext).req;
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(DebugHTTPServer.RequestContext))) => {
+ return self.tagged_pointer.as(DebugHTTPServer.RequestContext).req;
+ },
+ @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(DebugHTTPSServer.RequestContext))) => {
+ return self.tagged_pointer.as(DebugHTTPSServer.RequestContext).req;
+ },
+ else => @panic("Unexpected AnyRequestContext tag"),
+ }
+ }
+};
+
// This is defined separately partially to work-around an LLVM debugger bug.
fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comptime ThisServer: type) type {
return struct {
@@ -2282,7 +2368,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}
fn toAsyncWithoutAbortHandler(ctx: *RequestContext, req: *uws.Request, request_object: *Request) void {
- request_object.uws_request = req;
+ request_object.request_context.setRequest(req);
request_object.ensureURL() catch {
request_object.url = bun.String.empty;
@@ -2295,7 +2381,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
// This object dies after the stack frame is popped
// so we have to clear it in here too
- request_object.uws_request = null;
+ request_object.request_context = JSC.API.AnyRequestContext.Null;
}
fn toAsync(
@@ -3168,6 +3254,10 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
return onStartStreamingRequestBody(bun.cast(*RequestContext, this));
}
+ pub fn getRemoteSocketInfo(this: *RequestContext) ?uws.SocketAddress {
+ return (this.resp orelse return null).getRemoteSocketInfo();
+ }
+
pub const Export = shim.exportFunctions(.{
.onResolve = onResolve,
.onReject = onReject,
@@ -4693,17 +4783,6 @@ pub const ServerWebSocket = struct {
return JSValue.jsBoolean(this.websocket.isSubscribed(topic.slice()));
}
- // pub fn getTopics(
- // this: *ServerWebSocket,
- // globalThis: *JSC.JSGlobalObject,
- // ) callconv(.C) JSValue {
- // if (this.closed) {
- // return JSValue.createStringArray(globalThis, bun.default_allocator, null, 0, false);
- // }
-
- // this
- // }
-
pub fn getRemoteAddress(
this: *ServerWebSocket,
globalThis: *JSC.JSGlobalObject,
@@ -4730,7 +4809,7 @@ pub const ServerWebSocket = struct {
pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
return struct {
pub const ssl_enabled = ssl_enabled_;
- const debug_mode = debug_mode_;
+ pub const debug_mode = debug_mode_;
const ThisServer = @This();
pub const RequestContext = NewRequestContext(ssl_enabled, debug_mode, @This());
@@ -4768,6 +4847,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
pub const doPublish = JSC.wrapInstanceMethod(ThisServer, "publish", false);
pub const doReload = onReload;
pub const doFetch = onFetch;
+ pub const doRequestIP = JSC.wrapInstanceMethod(ThisServer, "requestIP", false);
pub usingnamespace NamespaceType;
@@ -4775,6 +4855,21 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
globalThis.throw("Server() is not a constructor", .{});
return null;
}
+
+ extern fn JSSocketAddress__create(global: *JSC.JSGlobalObject, ip: JSValue, port: i32, is_ipv6: bool) JSValue;
+
+ pub fn requestIP(this: *ThisServer, request: *JSC.WebCore.Request) JSC.JSValue {
+ return if (request.request_context.getRemoteSocketInfo()) |info|
+ JSSocketAddress__create(
+ this.globalThis,
+ bun.String.static(info.ip).toJSConst(this.globalThis),
+ info.port,
+ info.is_ipv6,
+ )
+ else
+ JSValue.jsNull();
+ }
+
pub fn publish(this: *ThisServer, globalThis: *JSC.JSGlobalObject, topic: ZigString, message_value: JSValue, compress_value: ?JSValue, exception: JSC.C.ExceptionRef) JSValue {
if (this.config.websocket == null)
return JSValue.jsNumber(0);
@@ -5551,7 +5646,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
request_object.* = .{
.method = ctx.method,
- .uws_request = req,
+ .request_context = AnyRequestContext.init(ctx),
.https = ssl_enabled,
.signal = ctx.signal,
.body = body.ref(),
@@ -5620,7 +5715,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
const response_value = this.config.onRequest.callWithThis(this.globalThis, this.thisObject, &args);
defer {
// uWS request will not live longer than this function
- request_object.uws_request = null;
+ request_object.request_context = JSC.API.AnyRequestContext.Null;
}
var should_deinit_context = false;
@@ -5635,7 +5730,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
ctx.defer_deinit_until_callback_completes = null;
if (should_deinit_context) {
- request_object.uws_request = null;
+ request_object.request_context = JSC.API.AnyRequestContext.Null;
ctx.deinit();
return;
}
@@ -5672,7 +5767,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
request_object.* = .{
.method = ctx.method,
- .uws_request = req,
+ .request_context = AnyRequestContext.init(ctx),
.upgrader = ctx,
.https = ssl_enabled,
.signal = ctx.signal,
@@ -5690,7 +5785,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
const response_value = this.config.onRequest.callWithThis(this.globalThis, this.thisObject, &args);
defer {
// uWS request will not live longer than this function
- request_object.uws_request = null;
+ request_object.request_context = JSC.API.AnyRequestContext.Null;
}
var should_deinit_context = false;
@@ -5705,7 +5800,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
ctx.defer_deinit_until_callback_completes = null;
if (should_deinit_context) {
- request_object.uws_request = null;
+ request_object.request_context = JSC.API.AnyRequestContext.Null;
ctx.deinit();
return;
}
diff --git a/src/bun.js/bindings/JSSocketAddress.cpp b/src/bun.js/bindings/JSSocketAddress.cpp
new file mode 100644
index 000000000..53084adb6
--- /dev/null
+++ b/src/bun.js/bindings/JSSocketAddress.cpp
@@ -0,0 +1,61 @@
+#include "JSSocketAddress.h"
+#include "ZigGlobalObject.h"
+#include "JavaScriptCore/JSObjectInlines.h"
+#include "JavaScriptCore/ObjectConstructor.h"
+#include "JavaScriptCore/JSCast.h"
+
+using namespace JSC;
+
+namespace Bun {
+namespace JSSocketAddress {
+
+// Using a structure with inlined offsets will be more lightweight than a class.
+
+Structure* createStructure(VM& vm, JSGlobalObject* globalObject)
+{
+ JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(
+ globalObject,
+ globalObject->objectPrototype(),
+ 3);
+
+ JSC::PropertyOffset offset;
+ structure = structure->addPropertyTransition(
+ vm,
+ structure,
+ JSC::Identifier::fromString(vm, "address"_s),
+ 0,
+ offset);
+
+ structure = structure->addPropertyTransition(
+ vm,
+ structure,
+ JSC::Identifier::fromString(vm, "family"_s),
+ 0,
+ offset);
+
+ structure = structure->addPropertyTransition(
+ vm,
+ structure,
+ JSC::Identifier::fromString(vm, "port"_s),
+ 0,
+ offset);
+
+ return structure;
+}
+
+} // namespace JSSocketAddress
+} // namespace Bun
+
+extern "C" JSObject* JSSocketAddress__create(JSGlobalObject* globalObject, JSString* value, int32_t port, bool isIPv6)
+{
+ VM& vm = globalObject->vm();
+
+ auto* global = jsCast<Zig::GlobalObject*>(globalObject);
+
+ JSObject* thisObject = constructEmptyObject(vm, global->JSSocketAddressStructure());
+ thisObject->putDirectOffset(vm, 0, value);
+ thisObject->putDirectOffset(vm, 1, isIPv6 ? jsString(vm, Bun::JSSocketAddress::IPv6) : jsString(vm, Bun::JSSocketAddress::IPv4));
+ thisObject->putDirectOffset(vm, 2, jsNumber(port));
+
+ return thisObject;
+}
diff --git a/src/bun.js/bindings/JSSocketAddress.h b/src/bun.js/bindings/JSSocketAddress.h
new file mode 100644
index 000000000..5e374dac3
--- /dev/null
+++ b/src/bun.js/bindings/JSSocketAddress.h
@@ -0,0 +1,19 @@
+// The object returned by Bun.serve's .requestIP()
+#pragma once
+#include "root.h"
+#include "JavaScriptCore/JSObjectInlines.h"
+
+using namespace JSC;
+
+namespace Bun {
+namespace JSSocketAddress {
+
+static const NeverDestroyed<String> IPv4 = MAKE_STATIC_STRING_IMPL("IPv4");
+static const NeverDestroyed<String> IPv6 = MAKE_STATIC_STRING_IMPL("IPv6");
+
+Structure* createStructure(VM& vm, JSGlobalObject* globalObject);
+
+} // namespace JSSocketAddress
+} // namespace Bun
+
+extern "C" JSObject* JSSocketAddress__create(JSGlobalObject* globalObject, JSString* value, int port, bool isIPv6);
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp
index b84c1cd16..45d60d379 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.cpp
+++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp
@@ -4197,6 +4197,9 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__publishCallback);
extern "C" EncodedJSValue DebugHTTPSServerPrototype__doReload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__reloadCallback);
+extern "C" EncodedJSValue DebugHTTPSServerPrototype__doRequestIP(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__requestIPCallback);
+
extern "C" EncodedJSValue DebugHTTPSServerPrototype__doStop(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__stopCallback);
@@ -4216,6 +4219,7 @@ static const HashTableValue JSDebugHTTPSServerPrototypeTableValues[] = {
{ "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__protocolGetterWrap, 0 } },
{ "publish"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__publishCallback, 3 } },
{ "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__reloadCallback, 2 } },
+ { "requestIP"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__requestIPCallback, 1 } },
{ "stop"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__stopCallback, 1 } },
{ "upgrade"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__upgradeCallback, 1 } }
};
@@ -4440,6 +4444,34 @@ JSC_DEFINE_HOST_FUNCTION(DebugHTTPSServerPrototype__reloadCallback, (JSGlobalObj
return DebugHTTPSServerPrototype__doReload(thisObject->wrapped(), lexicalGlobalObject, callFrame);
}
+JSC_DEFINE_HOST_FUNCTION(DebugHTTPSServerPrototype__requestIPCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSDebugHTTPSServer* thisObject = jsDynamicCast<JSDebugHTTPSServer*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof DebugHTTPSServer"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return DebugHTTPSServerPrototype__doRequestIP(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
JSC_DEFINE_HOST_FUNCTION(DebugHTTPSServerPrototype__stopCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
auto& vm = lexicalGlobalObject->vm();
@@ -4679,6 +4711,9 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__publishCallback);
extern "C" EncodedJSValue DebugHTTPServerPrototype__doReload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__reloadCallback);
+extern "C" EncodedJSValue DebugHTTPServerPrototype__doRequestIP(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__requestIPCallback);
+
extern "C" EncodedJSValue DebugHTTPServerPrototype__doStop(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__stopCallback);
@@ -4698,6 +4733,7 @@ static const HashTableValue JSDebugHTTPServerPrototypeTableValues[] = {
{ "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__protocolGetterWrap, 0 } },
{ "publish"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__publishCallback, 3 } },
{ "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__reloadCallback, 2 } },
+ { "requestIP"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__requestIPCallback, 1 } },
{ "stop"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__stopCallback, 1 } },
{ "upgrade"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__upgradeCallback, 1 } }
};
@@ -4922,6 +4958,34 @@ JSC_DEFINE_HOST_FUNCTION(DebugHTTPServerPrototype__reloadCallback, (JSGlobalObje
return DebugHTTPServerPrototype__doReload(thisObject->wrapped(), lexicalGlobalObject, callFrame);
}
+JSC_DEFINE_HOST_FUNCTION(DebugHTTPServerPrototype__requestIPCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSDebugHTTPServer* thisObject = jsDynamicCast<JSDebugHTTPServer*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof DebugHTTPServer"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return DebugHTTPServerPrototype__doRequestIP(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
JSC_DEFINE_HOST_FUNCTION(DebugHTTPServerPrototype__stopCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
auto& vm = lexicalGlobalObject->vm();
@@ -11620,6 +11684,9 @@ JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__publishCallback);
extern "C" EncodedJSValue HTTPSServerPrototype__doReload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__reloadCallback);
+extern "C" EncodedJSValue HTTPSServerPrototype__doRequestIP(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__requestIPCallback);
+
extern "C" EncodedJSValue HTTPSServerPrototype__doStop(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__stopCallback);
@@ -11639,6 +11706,7 @@ static const HashTableValue JSHTTPSServerPrototypeTableValues[] = {
{ "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__protocolGetterWrap, 0 } },
{ "publish"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__publishCallback, 3 } },
{ "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__reloadCallback, 2 } },
+ { "requestIP"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__requestIPCallback, 1 } },
{ "stop"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__stopCallback, 1 } },
{ "upgrade"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__upgradeCallback, 1 } }
};
@@ -11863,6 +11931,34 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSServerPrototype__reloadCallback, (JSGlobalObject *
return HTTPSServerPrototype__doReload(thisObject->wrapped(), lexicalGlobalObject, callFrame);
}
+JSC_DEFINE_HOST_FUNCTION(HTTPSServerPrototype__requestIPCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSHTTPSServer* thisObject = jsDynamicCast<JSHTTPSServer*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof HTTPSServer"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return HTTPSServerPrototype__doRequestIP(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
JSC_DEFINE_HOST_FUNCTION(HTTPSServerPrototype__stopCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
auto& vm = lexicalGlobalObject->vm();
@@ -12102,6 +12198,9 @@ JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__publishCallback);
extern "C" EncodedJSValue HTTPServerPrototype__doReload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__reloadCallback);
+extern "C" EncodedJSValue HTTPServerPrototype__doRequestIP(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__requestIPCallback);
+
extern "C" EncodedJSValue HTTPServerPrototype__doStop(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__stopCallback);
@@ -12121,6 +12220,7 @@ static const HashTableValue JSHTTPServerPrototypeTableValues[] = {
{ "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__protocolGetterWrap, 0 } },
{ "publish"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__publishCallback, 3 } },
{ "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__reloadCallback, 2 } },
+ { "requestIP"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__requestIPCallback, 1 } },
{ "stop"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__stopCallback, 1 } },
{ "upgrade"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__upgradeCallback, 1 } }
};
@@ -12345,6 +12445,34 @@ JSC_DEFINE_HOST_FUNCTION(HTTPServerPrototype__reloadCallback, (JSGlobalObject *
return HTTPServerPrototype__doReload(thisObject->wrapped(), lexicalGlobalObject, callFrame);
}
+JSC_DEFINE_HOST_FUNCTION(HTTPServerPrototype__requestIPCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSHTTPServer* thisObject = jsDynamicCast<JSHTTPServer*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof HTTPServer"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return HTTPServerPrototype__doRequestIP(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
JSC_DEFINE_HOST_FUNCTION(HTTPServerPrototype__stopCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
auto& vm = lexicalGlobalObject->vm();
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index 7ffd75ccf..a7d2bb7e5 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -206,6 +206,7 @@ namespace JSCastingHelpers = JSC::JSCastingHelpers;
#include "JSDOMConvertStrings.h"
#include "JSDOMConvertUnion.h"
#include "AddEventListenerOptions.h"
+#include "JSSocketAddress.h"
#include "ErrorStackTrace.h"
#include "CallSite.h"
@@ -2884,6 +2885,11 @@ void GlobalObject::finishCreation(VM& vm)
init.set(structure);
});
+ m_JSSocketAddressStructure.initLater(
+ [](const Initializer<Structure>& init) {
+ init.set(JSSocketAddress::createStructure(init.vm, init.owner));
+ });
+
// Change prototype from null to object for synthetic modules.
m_moduleNamespaceObjectStructure.initLater(
[](const Initializer<Structure>& init) {
@@ -3858,6 +3864,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
thisObject->m_commonJSModuleObjectStructure.visit(visitor);
thisObject->m_memoryFootprintStructure.visit(visitor);
thisObject->m_commonJSFunctionArgumentsStructure.visit(visitor);
+ thisObject->m_JSSocketAddressStructure.visit(visitor);
thisObject->m_cachedGlobalObjectStructure.visit(visitor);
thisObject->m_cachedGlobalProxyStructure.visit(visitor);
diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h
index e27b3bffa..26111725b 100644
--- a/src/bun.js/bindings/ZigGlobalObject.h
+++ b/src/bun.js/bindings/ZigGlobalObject.h
@@ -245,6 +245,7 @@ public:
Structure* AsyncContextFrameStructure() { return m_asyncBoundFunctionStructure.getInitializedOnMainThread(this); }
Structure* commonJSFunctionArgumentsStructure() { return m_commonJSFunctionArgumentsStructure.getInitializedOnMainThread(this); }
+ Structure* JSSocketAddressStructure() { return m_JSSocketAddressStructure.getInitializedOnMainThread(this); }
JSWeakMap* vmModuleContextMap() { return m_vmModuleContextMap.getInitializedOnMainThread(this); }
@@ -494,6 +495,7 @@ public:
LazyProperty<JSGlobalObject, Structure> m_cachedGlobalProxyStructure;
LazyProperty<JSGlobalObject, Structure> m_commonJSModuleObjectStructure;
LazyProperty<JSGlobalObject, Structure> m_commonJSFunctionArgumentsStructure;
+ LazyProperty<JSGlobalObject, Structure> m_JSSocketAddressStructure;
LazyProperty<JSGlobalObject, Structure> m_memoryFootprintStructure;
LazyProperty<JSGlobalObject, JSObject> m_requireFunctionUnbound;
LazyProperty<JSGlobalObject, JSObject> m_requireResolveFunctionUnbound;
diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig
index 581d4a5f3..da93b2706 100644
--- a/src/bun.js/bindings/generated_classes.zig
+++ b/src/bun.js/bindings/generated_classes.zig
@@ -1327,6 +1327,8 @@ pub const JSDebugHTTPSServer = struct {
@compileLog("Expected DebugHTTPSServer.doPublish to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doPublish)));
if (@TypeOf(DebugHTTPSServer.doReload) != CallbackType)
@compileLog("Expected DebugHTTPSServer.doReload to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doReload)));
+ if (@TypeOf(DebugHTTPSServer.doRequestIP) != CallbackType)
+ @compileLog("Expected DebugHTTPSServer.doRequestIP to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doRequestIP)));
if (@TypeOf(DebugHTTPSServer.doStop) != CallbackType)
@compileLog("Expected DebugHTTPSServer.doStop to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doStop)));
if (@TypeOf(DebugHTTPSServer.doUpgrade) != CallbackType)
@@ -1335,6 +1337,7 @@ pub const JSDebugHTTPSServer = struct {
@export(DebugHTTPSServer.doFetch, .{ .name = "DebugHTTPSServerPrototype__doFetch" });
@export(DebugHTTPSServer.doPublish, .{ .name = "DebugHTTPSServerPrototype__doPublish" });
@export(DebugHTTPSServer.doReload, .{ .name = "DebugHTTPSServerPrototype__doReload" });
+ @export(DebugHTTPSServer.doRequestIP, .{ .name = "DebugHTTPSServerPrototype__doRequestIP" });
@export(DebugHTTPSServer.doStop, .{ .name = "DebugHTTPSServerPrototype__doStop" });
@export(DebugHTTPSServer.doUpgrade, .{ .name = "DebugHTTPSServerPrototype__doUpgrade" });
@export(DebugHTTPSServer.finalize, .{ .name = "DebugHTTPSServerClass__finalize" });
@@ -1470,6 +1473,8 @@ pub const JSDebugHTTPServer = struct {
@compileLog("Expected DebugHTTPServer.doPublish to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doPublish)));
if (@TypeOf(DebugHTTPServer.doReload) != CallbackType)
@compileLog("Expected DebugHTTPServer.doReload to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doReload)));
+ if (@TypeOf(DebugHTTPServer.doRequestIP) != CallbackType)
+ @compileLog("Expected DebugHTTPServer.doRequestIP to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doRequestIP)));
if (@TypeOf(DebugHTTPServer.doStop) != CallbackType)
@compileLog("Expected DebugHTTPServer.doStop to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doStop)));
if (@TypeOf(DebugHTTPServer.doUpgrade) != CallbackType)
@@ -1478,6 +1483,7 @@ pub const JSDebugHTTPServer = struct {
@export(DebugHTTPServer.doFetch, .{ .name = "DebugHTTPServerPrototype__doFetch" });
@export(DebugHTTPServer.doPublish, .{ .name = "DebugHTTPServerPrototype__doPublish" });
@export(DebugHTTPServer.doReload, .{ .name = "DebugHTTPServerPrototype__doReload" });
+ @export(DebugHTTPServer.doRequestIP, .{ .name = "DebugHTTPServerPrototype__doRequestIP" });
@export(DebugHTTPServer.doStop, .{ .name = "DebugHTTPServerPrototype__doStop" });
@export(DebugHTTPServer.doUpgrade, .{ .name = "DebugHTTPServerPrototype__doUpgrade" });
@export(DebugHTTPServer.finalize, .{ .name = "DebugHTTPServerClass__finalize" });
@@ -3277,6 +3283,8 @@ pub const JSHTTPSServer = struct {
@compileLog("Expected HTTPSServer.doPublish to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doPublish)));
if (@TypeOf(HTTPSServer.doReload) != CallbackType)
@compileLog("Expected HTTPSServer.doReload to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doReload)));
+ if (@TypeOf(HTTPSServer.doRequestIP) != CallbackType)
+ @compileLog("Expected HTTPSServer.doRequestIP to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doRequestIP)));
if (@TypeOf(HTTPSServer.doStop) != CallbackType)
@compileLog("Expected HTTPSServer.doStop to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doStop)));
if (@TypeOf(HTTPSServer.doUpgrade) != CallbackType)
@@ -3285,6 +3293,7 @@ pub const JSHTTPSServer = struct {
@export(HTTPSServer.doFetch, .{ .name = "HTTPSServerPrototype__doFetch" });
@export(HTTPSServer.doPublish, .{ .name = "HTTPSServerPrototype__doPublish" });
@export(HTTPSServer.doReload, .{ .name = "HTTPSServerPrototype__doReload" });
+ @export(HTTPSServer.doRequestIP, .{ .name = "HTTPSServerPrototype__doRequestIP" });
@export(HTTPSServer.doStop, .{ .name = "HTTPSServerPrototype__doStop" });
@export(HTTPSServer.doUpgrade, .{ .name = "HTTPSServerPrototype__doUpgrade" });
@export(HTTPSServer.finalize, .{ .name = "HTTPSServerClass__finalize" });
@@ -3420,6 +3429,8 @@ pub const JSHTTPServer = struct {
@compileLog("Expected HTTPServer.doPublish to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doPublish)));
if (@TypeOf(HTTPServer.doReload) != CallbackType)
@compileLog("Expected HTTPServer.doReload to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doReload)));
+ if (@TypeOf(HTTPServer.doRequestIP) != CallbackType)
+ @compileLog("Expected HTTPServer.doRequestIP to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doRequestIP)));
if (@TypeOf(HTTPServer.doStop) != CallbackType)
@compileLog("Expected HTTPServer.doStop to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doStop)));
if (@TypeOf(HTTPServer.doUpgrade) != CallbackType)
@@ -3428,6 +3439,7 @@ pub const JSHTTPServer = struct {
@export(HTTPServer.doFetch, .{ .name = "HTTPServerPrototype__doFetch" });
@export(HTTPServer.doPublish, .{ .name = "HTTPServerPrototype__doPublish" });
@export(HTTPServer.doReload, .{ .name = "HTTPServerPrototype__doReload" });
+ @export(HTTPServer.doRequestIP, .{ .name = "HTTPServerPrototype__doRequestIP" });
@export(HTTPServer.doStop, .{ .name = "HTTPServerPrototype__doStop" });
@export(HTTPServer.doUpgrade, .{ .name = "HTTPServerPrototype__doUpgrade" });
@export(HTTPServer.finalize, .{ .name = "HTTPServerClass__finalize" });
diff --git a/src/bun.js/webcore/request.zig b/src/bun.js/webcore/request.zig
index db073fccc..381ae2750 100644
--- a/src/bun.js/webcore/request.zig
+++ b/src/bun.js/webcore/request.zig
@@ -68,7 +68,7 @@ pub const Request = struct {
signal: ?*AbortSignal = null,
body: *BodyValueRef,
method: Method = Method.GET,
- uws_request: ?*uws.Request = null,
+ request_context: JSC.API.AnyRequestContext = JSC.API.AnyRequestContext.Null,
https: bool = false,
upgrader: ?*anyopaque = null,
@@ -89,7 +89,7 @@ pub const Request = struct {
pub fn getContentType(
this: *Request,
) ?ZigString.Slice {
- if (this.uws_request) |req| {
+ if (this.request_context.getRequest()) |req| {
if (req.header("content-type")) |value| {
return ZigString.Slice.fromUTF8NeverFree(value);
}
@@ -324,7 +324,7 @@ pub const Request = struct {
if (this.url.length() > 0)
return this.url.byteSlice().len;
- if (this.uws_request) |req| {
+ if (this.request_context.getRequest()) |req| {
const req_url = req.url();
if (req_url.len > 0 and req_url[0] == '/') {
if (req.header("host")) |host| {
@@ -351,7 +351,7 @@ pub const Request = struct {
pub fn ensureURL(this: *Request) !void {
if (!this.url.isEmpty()) return;
- if (this.uws_request) |req| {
+ if (this.request_context.getRequest()) |req| {
const req_url = req.url();
if (req_url.len > 0 and req_url[0] == '/') {
if (req.header("host")) |host| {
@@ -723,7 +723,7 @@ pub const Request = struct {
globalThis: *JSC.JSGlobalObject,
) callconv(.C) JSC.JSValue {
if (this.headers == null) {
- if (this.uws_request) |req| {
+ if (this.request_context.getRequest()) |req| {
this.headers = FetchHeaders.createFromUWS(globalThis, req);
} else {
this.headers = FetchHeaders.createEmpty();
@@ -742,7 +742,7 @@ pub const Request = struct {
pub fn cloneHeaders(this: *Request, globalThis: *JSGlobalObject) ?*FetchHeaders {
if (this.headers == null) {
- if (this.uws_request) |uws_req| {
+ if (this.request_context.getRequest()) |uws_req| {
this.headers = FetchHeaders.createFromUWS(globalThis, uws_req);
}
}