diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index d8d8fd20407d..a0755b050c7b 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -2423,6 +2423,11 @@ declare module "bun" { * When bun is not started with the `--hot` flag, this ID is currently unused. */ readonly id: string; + + /** + * A URL object representing the address the server is listening on. + */ + readonly url: URL; } /** diff --git a/src/bun.js/api/server.classes.ts b/src/bun.js/api/server.classes.ts index 80449ed27a1b..c01cbc352a7a 100644 --- a/src/bun.js/api/server.classes.ts +++ b/src/bun.js/api/server.classes.ts @@ -51,6 +51,9 @@ function generate(name) { development: { getter: "getDevelopment", }, + url: { + getter: "getURL", + }, }, klass: {}, finalize: true, diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 3fe411f39a7a..ab7b244238a3 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -5897,6 +5897,16 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp }, } } + + pub fn getURL( + this: *ThisServer, + globalThis: *JSC.JSGlobalObject, + ) callconv(.C) JSC.JSValue { + var href_ = bun.String.init(this.config.base_url.href); + var href = href_.toJS(globalThis).toBunString(globalThis); + const url = JSC.URL.fromString(href) orelse return JSValue.jsUndefined(); + return JSC.URL.toJS(url, globalThis); + } }; } diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index 31b331111fbb..2326a5fe682c 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -338,6 +338,12 @@ extern "C" WTF::URL* URL__fromJS(EncodedJSValue encodedValue, JSC::JSGlobalObjec return new WTF::URL(WTFMove(url)); } +extern "C" EncodedJSValue URL__toJS(WTF::URL* wtfUrl, JSC::JSGlobalObject* globalObject) +{ + auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm()); + return JSC::JSValue::encode(jsString(globalObject->vm(), wtfUrl->string())); +} + extern "C" BunString URL__getHrefFromJS(EncodedJSValue encodedValue, JSC::JSGlobalObject* globalObject) { auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm()); diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index 45d60d379724..c8373f1e12a1 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -4206,6 +4206,9 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__stopCallback); extern "C" EncodedJSValue DebugHTTPSServerPrototype__doUpgrade(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__upgradeCallback); +extern "C" JSC::EncodedJSValue DebugHTTPSServerPrototype__getURL(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(DebugHTTPSServerPrototype__urlGetterWrap); + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDebugHTTPSServerPrototype, JSDebugHTTPSServerPrototype::Base); static const HashTableValue JSDebugHTTPSServerPrototypeTableValues[] = { @@ -4221,7 +4224,8 @@ static const HashTableValue JSDebugHTTPSServerPrototypeTableValues[] = { { "reload"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__reloadCallback, 2 } }, { "requestIP"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__requestIPCallback, 1 } }, { "stop"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__stopCallback, 1 } }, - { "upgrade"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__upgradeCallback, 1 } } + { "upgrade"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__upgradeCallback, 1 } }, + { "url"_s, static_cast(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__urlGetterWrap, 0 } } }; const ClassInfo JSDebugHTTPSServerPrototype::s_info = { "DebugHTTPSServer"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDebugHTTPSServerPrototype) }; @@ -4528,6 +4532,18 @@ JSC_DEFINE_HOST_FUNCTION(DebugHTTPSServerPrototype__upgradeCallback, (JSGlobalOb return DebugHTTPSServerPrototype__doUpgrade(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_CUSTOM_GETTER(DebugHTTPSServerPrototype__urlGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSDebugHTTPSServer* thisObject = jsCast(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + JSC::EncodedJSValue result = DebugHTTPSServerPrototype__getURL(thisObject->wrapped(), globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, result); +} + void JSDebugHTTPSServerPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) { Base::finishCreation(vm); @@ -4720,6 +4736,9 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__stopCallback); extern "C" EncodedJSValue DebugHTTPServerPrototype__doUpgrade(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__upgradeCallback); +extern "C" JSC::EncodedJSValue DebugHTTPServerPrototype__getURL(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(DebugHTTPServerPrototype__urlGetterWrap); + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDebugHTTPServerPrototype, JSDebugHTTPServerPrototype::Base); static const HashTableValue JSDebugHTTPServerPrototypeTableValues[] = { @@ -4735,7 +4754,8 @@ static const HashTableValue JSDebugHTTPServerPrototypeTableValues[] = { { "reload"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__reloadCallback, 2 } }, { "requestIP"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__requestIPCallback, 1 } }, { "stop"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__stopCallback, 1 } }, - { "upgrade"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__upgradeCallback, 1 } } + { "upgrade"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__upgradeCallback, 1 } }, + { "url"_s, static_cast(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__urlGetterWrap, 0 } } }; const ClassInfo JSDebugHTTPServerPrototype::s_info = { "DebugHTTPServer"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDebugHTTPServerPrototype) }; @@ -5042,6 +5062,18 @@ JSC_DEFINE_HOST_FUNCTION(DebugHTTPServerPrototype__upgradeCallback, (JSGlobalObj return DebugHTTPServerPrototype__doUpgrade(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_CUSTOM_GETTER(DebugHTTPServerPrototype__urlGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSDebugHTTPServer* thisObject = jsCast(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + JSC::EncodedJSValue result = DebugHTTPServerPrototype__getURL(thisObject->wrapped(), globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, result); +} + void JSDebugHTTPServerPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) { Base::finishCreation(vm); @@ -11693,6 +11725,9 @@ JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__stopCallback); extern "C" EncodedJSValue HTTPSServerPrototype__doUpgrade(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__upgradeCallback); +extern "C" JSC::EncodedJSValue HTTPSServerPrototype__getURL(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(HTTPSServerPrototype__urlGetterWrap); + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPSServerPrototype, JSHTTPSServerPrototype::Base); static const HashTableValue JSHTTPSServerPrototypeTableValues[] = { @@ -11708,7 +11743,8 @@ static const HashTableValue JSHTTPSServerPrototypeTableValues[] = { { "reload"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__reloadCallback, 2 } }, { "requestIP"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__requestIPCallback, 1 } }, { "stop"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__stopCallback, 1 } }, - { "upgrade"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__upgradeCallback, 1 } } + { "upgrade"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__upgradeCallback, 1 } }, + { "url"_s, static_cast(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__urlGetterWrap, 0 } } }; const ClassInfo JSHTTPSServerPrototype::s_info = { "HTTPSServer"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSHTTPSServerPrototype) }; @@ -12015,6 +12051,18 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSServerPrototype__upgradeCallback, (JSGlobalObject return HTTPSServerPrototype__doUpgrade(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_CUSTOM_GETTER(HTTPSServerPrototype__urlGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSHTTPSServer* thisObject = jsCast(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + JSC::EncodedJSValue result = HTTPSServerPrototype__getURL(thisObject->wrapped(), globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, result); +} + void JSHTTPSServerPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) { Base::finishCreation(vm); @@ -12207,6 +12255,9 @@ JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__stopCallback); extern "C" EncodedJSValue HTTPServerPrototype__doUpgrade(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__upgradeCallback); +extern "C" JSC::EncodedJSValue HTTPServerPrototype__getURL(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(HTTPServerPrototype__urlGetterWrap); + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPServerPrototype, JSHTTPServerPrototype::Base); static const HashTableValue JSHTTPServerPrototypeTableValues[] = { @@ -12222,7 +12273,8 @@ static const HashTableValue JSHTTPServerPrototypeTableValues[] = { { "reload"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__reloadCallback, 2 } }, { "requestIP"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__requestIPCallback, 1 } }, { "stop"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__stopCallback, 1 } }, - { "upgrade"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__upgradeCallback, 1 } } + { "upgrade"_s, static_cast(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__upgradeCallback, 1 } }, + { "url"_s, static_cast(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__urlGetterWrap, 0 } } }; const ClassInfo JSHTTPServerPrototype::s_info = { "HTTPServer"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSHTTPServerPrototype) }; @@ -12529,6 +12581,18 @@ JSC_DEFINE_HOST_FUNCTION(HTTPServerPrototype__upgradeCallback, (JSGlobalObject * return HTTPServerPrototype__doUpgrade(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_CUSTOM_GETTER(HTTPServerPrototype__urlGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSHTTPServer* thisObject = jsCast(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + JSC::EncodedJSValue result = HTTPServerPrototype__getURL(thisObject->wrapped(), globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, result); +} + void JSHTTPServerPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) { Base::finishCreation(vm); diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index f274f72d7ea4..59c78a9a4e4b 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -5481,6 +5481,7 @@ pub fn untrackFunction( pub const URL = opaque { extern fn URL__fromJS(JSValue, *JSC.JSGlobalObject) ?*URL; + extern fn URL__toJS(globalObject: *JSC.JSGlobalObject, in: *URL) JSC.JSValue; extern fn URL__fromString(*bun.String) ?*URL; extern fn URL__protocol(*URL) String; extern fn URL__href(*URL) String; @@ -5535,6 +5536,11 @@ pub const URL = opaque { return URL__fromJS(value, globalObject); } + pub fn toJS(url: *URL, globalObject: *JSC.JSGlobalObject) JSValue { + JSC.markBinding(@src()); + return URL__toJS(globalObject, url); + } + pub fn fromUTF8(input: []const u8) ?*URL { return fromString(String.fromUTF8(input)); } diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index da93b270691f..dd63ce9e9a9d 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -1333,6 +1333,9 @@ pub const JSDebugHTTPSServer = struct { @compileLog("Expected DebugHTTPSServer.doStop to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doStop))); if (@TypeOf(DebugHTTPSServer.doUpgrade) != CallbackType) @compileLog("Expected DebugHTTPSServer.doUpgrade to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doUpgrade))); + if (@TypeOf(DebugHTTPSServer.getURL) != GetterType) + @compileLog("Expected DebugHTTPSServer.getURL to be a getter"); + if (!JSC.is_bindgen) { @export(DebugHTTPSServer.doFetch, .{ .name = "DebugHTTPSServerPrototype__doFetch" }); @export(DebugHTTPSServer.doPublish, .{ .name = "DebugHTTPSServerPrototype__doPublish" }); @@ -1348,6 +1351,7 @@ pub const JSDebugHTTPSServer = struct { @export(DebugHTTPSServer.getPendingWebSockets, .{ .name = "DebugHTTPSServerPrototype__getPendingWebSockets" }); @export(DebugHTTPSServer.getPort, .{ .name = "DebugHTTPSServerPrototype__getPort" }); @export(DebugHTTPSServer.getProtocol, .{ .name = "DebugHTTPSServerPrototype__getProtocol" }); + @export(DebugHTTPSServer.getURL, .{ .name = "DebugHTTPSServerPrototype__getURL" }); } } }; @@ -1479,6 +1483,9 @@ pub const JSDebugHTTPServer = struct { @compileLog("Expected DebugHTTPServer.doStop to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doStop))); if (@TypeOf(DebugHTTPServer.doUpgrade) != CallbackType) @compileLog("Expected DebugHTTPServer.doUpgrade to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doUpgrade))); + if (@TypeOf(DebugHTTPServer.getURL) != GetterType) + @compileLog("Expected DebugHTTPServer.getURL to be a getter"); + if (!JSC.is_bindgen) { @export(DebugHTTPServer.doFetch, .{ .name = "DebugHTTPServerPrototype__doFetch" }); @export(DebugHTTPServer.doPublish, .{ .name = "DebugHTTPServerPrototype__doPublish" }); @@ -1494,6 +1501,7 @@ pub const JSDebugHTTPServer = struct { @export(DebugHTTPServer.getPendingWebSockets, .{ .name = "DebugHTTPServerPrototype__getPendingWebSockets" }); @export(DebugHTTPServer.getPort, .{ .name = "DebugHTTPServerPrototype__getPort" }); @export(DebugHTTPServer.getProtocol, .{ .name = "DebugHTTPServerPrototype__getProtocol" }); + @export(DebugHTTPServer.getURL, .{ .name = "DebugHTTPServerPrototype__getURL" }); } } }; @@ -3289,6 +3297,9 @@ pub const JSHTTPSServer = struct { @compileLog("Expected HTTPSServer.doStop to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doStop))); if (@TypeOf(HTTPSServer.doUpgrade) != CallbackType) @compileLog("Expected HTTPSServer.doUpgrade to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doUpgrade))); + if (@TypeOf(HTTPSServer.getURL) != GetterType) + @compileLog("Expected HTTPSServer.getURL to be a getter"); + if (!JSC.is_bindgen) { @export(HTTPSServer.doFetch, .{ .name = "HTTPSServerPrototype__doFetch" }); @export(HTTPSServer.doPublish, .{ .name = "HTTPSServerPrototype__doPublish" }); @@ -3304,6 +3315,7 @@ pub const JSHTTPSServer = struct { @export(HTTPSServer.getPendingWebSockets, .{ .name = "HTTPSServerPrototype__getPendingWebSockets" }); @export(HTTPSServer.getPort, .{ .name = "HTTPSServerPrototype__getPort" }); @export(HTTPSServer.getProtocol, .{ .name = "HTTPSServerPrototype__getProtocol" }); + @export(HTTPSServer.getURL, .{ .name = "HTTPSServerPrototype__getURL" }); } } }; @@ -3435,6 +3447,9 @@ pub const JSHTTPServer = struct { @compileLog("Expected HTTPServer.doStop to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doStop))); if (@TypeOf(HTTPServer.doUpgrade) != CallbackType) @compileLog("Expected HTTPServer.doUpgrade to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doUpgrade))); + if (@TypeOf(HTTPServer.getURL) != GetterType) + @compileLog("Expected HTTPServer.getURL to be a getter"); + if (!JSC.is_bindgen) { @export(HTTPServer.doFetch, .{ .name = "HTTPServerPrototype__doFetch" }); @export(HTTPServer.doPublish, .{ .name = "HTTPServerPrototype__doPublish" }); @@ -3450,6 +3465,7 @@ pub const JSHTTPServer = struct { @export(HTTPServer.getPendingWebSockets, .{ .name = "HTTPServerPrototype__getPendingWebSockets" }); @export(HTTPServer.getPort, .{ .name = "HTTPServerPrototype__getPort" }); @export(HTTPServer.getProtocol, .{ .name = "HTTPServerPrototype__getProtocol" }); + @export(HTTPServer.getURL, .{ .name = "HTTPServerPrototype__getURL" }); } } }; diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index cef5d0804d20..cc08950175b8 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -234,6 +234,7 @@ extern "C" void Bun__WTFStringImpl__deref(WTF::StringImpl* impl); extern "C" void Bun__WTFStringImpl__ref(WTF::StringImpl* impl); extern "C" bool BunString__fromJS(JSC::JSGlobalObject*, JSC::EncodedJSValue, BunString*); extern "C" JSC::EncodedJSValue BunString__toJS(JSC::JSGlobalObject*, BunString*); +extern "C" JSC::EncodedJSValue URL__toJS(WTF::URL*, JSC::JSGlobalObject*); extern "C" void BunString__toWTFString(BunString*); namespace Bun { diff --git a/test/js/bun/http/bun-server.test.ts b/test/js/bun/http/bun-server.test.ts index e82e2cab00cf..bc217b26dfaa 100644 --- a/test/js/bun/http/bun-server.test.ts +++ b/test/js/bun/http/bun-server.test.ts @@ -379,4 +379,58 @@ describe("Server", () => { await proc.exited; expect(proc.exitCode).toBe(0); }); + + + test("server should have URL fields set", async () => { + const server = Bun.serve({ + fetch(req) { + return new Response("Hello World!"); + }, + }); + try { + expect(server.url.hash).toBe(""); + expect(server.url.host).toBe(`0.0.0.0:${server.port}`); + expect(server.url.hostname).toBe("0.0.0.0"); + expect(server.url.href).toBe(`http://0.0.0.0:${server.port}/`); + expect(server.url.origin).toBe(`http://0.0.0.0:${server.port}`); + expect(server.url.password).toBe(""); + expect(server.url.pathname).toBe("/"); + expect(server.url.port).toBe(`${server.port}`); + expect(server.url.protocol).toBe("http"); + expect(server.url.search).toBe(""); + expect(server.url.username).toBe(""); + expect(server.url.searchParams).toEqual({}); + expect(server.url.toJSON()).toBe(`http://0.0.0.0:${server.port}/`); + } finally { + server.stop(true); + } + }); + + test("server should have URL fields set with IPv6", async () => { + const server = Bun.serve({ + hostname: "[::1]", + fetch() { + return new Response("Hello"); + }, + port: 0, + }); + try { + expect(server.url.hash).toBe(""); + expect(server.url.host).toStartWith("[::1]"); + expect(server.url.hostname).toBe("[::1]"); + expect(server.url.href).toStartWith("http://[::1]:"); + expect(server.url.href).toEndWith("/"); + expect(server.url.origin).toStartWith("http://[::1]:"); + expect(server.url.password).toBe(""); + expect(server.url.pathname).toBe("/"); + expect(server.url.port).toBeDefined(); + expect(server.url.protocol).toBe("http"); + expect(server.url.search).toBe(""); + expect(server.url.username).toBe(""); + expect(server.url.searchParams).toEqual({}); + expect(server.url.toJSON()).toStartWith("http://[::1]:"); + } finally { + server.stop(true); + } + }); });