mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Fix #1354
This commit is contained in:
@@ -4079,6 +4079,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
|
||||
.vm = JSC.VirtualMachine.vm,
|
||||
.allocator = Arena.getThreadlocalDefault(),
|
||||
};
|
||||
|
||||
if (RequestContext.pool == null) {
|
||||
RequestContext.pool = server.allocator.create(RequestContext.RequestContextStackAllocator) catch @panic("Out of memory!");
|
||||
RequestContext.pool.?.* = .{
|
||||
@@ -4256,11 +4257,12 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
|
||||
var ctx = this.request_pool_allocator.create(RequestContext) catch @panic("ran out of memory");
|
||||
ctx.create(this, req, resp);
|
||||
var request_object = this.allocator.create(JSC.WebCore.Request) catch unreachable;
|
||||
|
||||
request_object.* = .{
|
||||
.url = "",
|
||||
.method = ctx.method,
|
||||
.uws_request = req,
|
||||
.base_url_string_for_joining = this.base_url_string_for_joining,
|
||||
.https = ssl_enabled,
|
||||
.body = .{
|
||||
.Empty = .{},
|
||||
},
|
||||
@@ -4339,8 +4341,8 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
|
||||
.url = "",
|
||||
.method = ctx.method,
|
||||
.uws_request = req,
|
||||
.base_url_string_for_joining = this.base_url_string_for_joining,
|
||||
.upgrader = ctx,
|
||||
.https = ssl_enabled,
|
||||
.body = .{
|
||||
.Empty = .{},
|
||||
},
|
||||
|
||||
@@ -5166,17 +5166,17 @@ pub const Body = struct {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Request
|
||||
pub const Request = struct {
|
||||
url: []const u8 = "",
|
||||
url_was_allocated: bool = false,
|
||||
|
||||
headers: ?*FetchHeaders = null,
|
||||
body: Body.Value = Body.Value{ .Empty = .{} },
|
||||
method: Method = Method.GET,
|
||||
uws_request: ?*uws.Request = null,
|
||||
https: bool = false,
|
||||
upgrader: ?*anyopaque = null,
|
||||
|
||||
// We must report a consistent value for this
|
||||
reported_estimated_size: ?u63 = null,
|
||||
base_url_string_for_joining: []const u8 = "",
|
||||
|
||||
url_was_allocated: bool = false,
|
||||
|
||||
pub usingnamespace JSC.Codegen.JSRequest;
|
||||
|
||||
@@ -5368,29 +5368,54 @@ pub const Request = struct {
|
||||
return ZigString.init(this.url).withEncoding().toValueGC(globalObject);
|
||||
}
|
||||
|
||||
pub fn sizeOfURL(this: *Request) usize {
|
||||
pub fn sizeOfURL(this: *const Request) usize {
|
||||
if (this.url.len > 0)
|
||||
return this.url.len;
|
||||
|
||||
if (this.uws_request) |req| {
|
||||
return this.base_url_string_for_joining.len + req.url().len;
|
||||
const fmt = ZigURL.HostFormatter{
|
||||
.is_https = this.https,
|
||||
.host = req.header("host") orelse "",
|
||||
};
|
||||
|
||||
return this.getProtocol().len + req.url().len + std.fmt.count("{any}", .{fmt});
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pub fn getProtocol(this: *const Request) []const u8 {
|
||||
if (this.https)
|
||||
return "https://";
|
||||
|
||||
return "http://";
|
||||
}
|
||||
|
||||
pub fn ensureURL(this: *Request) !void {
|
||||
if (this.url.len > 0) return;
|
||||
|
||||
if (this.uws_request) |req| {
|
||||
if (this.base_url_string_for_joining.len > 0) {
|
||||
this.url = try strings.append(bun.default_allocator, this.base_url_string_for_joining, req.url());
|
||||
const req_url = req.url();
|
||||
if (req.header("host")) |host| {
|
||||
const fmt = ZigURL.HostFormatter{
|
||||
.is_https = this.https,
|
||||
.host = host,
|
||||
};
|
||||
const url = try std.fmt.allocPrint(bun.default_allocator, "{s}{any}{s}", .{
|
||||
this.getProtocol(),
|
||||
fmt,
|
||||
req_url,
|
||||
});
|
||||
if (comptime Environment.allow_assert) {
|
||||
std.debug.assert(this.sizeOfURL() == url.len);
|
||||
}
|
||||
this.url = url;
|
||||
this.url_was_allocated = true;
|
||||
|
||||
// don't keep this around when we don't need it
|
||||
this.base_url_string_for_joining = "";
|
||||
} else {
|
||||
this.url = try bun.default_allocator.dupe(u8, req.url());
|
||||
if (comptime Environment.allow_assert) {
|
||||
std.debug.assert(this.sizeOfURL() == req_url.len);
|
||||
}
|
||||
this.url = try bun.default_allocator.dupe(u8, req_url);
|
||||
this.url_was_allocated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,6 +915,8 @@ pub const Request = opaque {
|
||||
return ptr[0..req.uws_req_get_method(&ptr)];
|
||||
}
|
||||
pub fn header(req: *Request, name: []const u8) ?[]const u8 {
|
||||
std.debug.assert(std.ascii.isLower(name[0]));
|
||||
|
||||
var ptr: [*]const u8 = undefined;
|
||||
const len = req.uws_req_get_header(name.ptr, name.len, &ptr);
|
||||
if (len == 0) return null;
|
||||
|
||||
@@ -1148,7 +1148,7 @@ pub fn buildRequest(this: *HTTPClient, body_len: usize) picohttp.Request {
|
||||
if (!override_host_header) {
|
||||
request_headers_buf[header_count] = picohttp.Header{
|
||||
.name = host_header_name,
|
||||
.value = this.url.hostname,
|
||||
.value = this.url.host,
|
||||
};
|
||||
header_count += 1;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ pub const URL = struct {
|
||||
|
||||
pub const HostFormatter = struct {
|
||||
host: string,
|
||||
port: string,
|
||||
port: string = "80",
|
||||
is_https: bool = false,
|
||||
|
||||
pub fn format(formatter: HostFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
|
||||
@@ -41,13 +41,35 @@ it("request.url should log successfully", async () => {
|
||||
return new Response(file(fixture));
|
||||
},
|
||||
});
|
||||
expected = `http://${server.hostname}:${server.port}/helloooo`;
|
||||
expected = `http://localhost:${server.port}/helloooo`;
|
||||
const response = await fetch(expected);
|
||||
expect(response.url).toBe(expected);
|
||||
expect(await response.text()).toBe(textToExpect);
|
||||
server.stop();
|
||||
});
|
||||
|
||||
it("request.url should be based on the Host header", async () => {
|
||||
const fixture = resolve(import.meta.dir, "./fetch.js.txt");
|
||||
const textToExpect = readFileSync(fixture, "utf-8");
|
||||
var expected;
|
||||
const server = serve({
|
||||
port: port++,
|
||||
fetch(req) {
|
||||
expect(req.url).toBe("http://example.com/helloooo");
|
||||
return new Response(file(fixture));
|
||||
},
|
||||
});
|
||||
expected = `http://${server.hostname}:${server.port}/helloooo`;
|
||||
const response = await fetch(expected, {
|
||||
headers: {
|
||||
Host: "example.com",
|
||||
},
|
||||
});
|
||||
expect(response.url).toBe(expected);
|
||||
expect(await response.text()).toBe(textToExpect);
|
||||
server.stop();
|
||||
});
|
||||
|
||||
describe("streaming", () => {
|
||||
describe("error handler", () => {
|
||||
it("throw on pull reports an error and close the connection", async () => {
|
||||
|
||||
Reference in New Issue
Block a user