add headers to SyncResponse and XHR

This commit is contained in:
Muki Kiboigo authored and Karl Seguin committed 2026-09-29 07:49:05 +08:00
1 parent 5932638baf
commit b7c17c9cb4
2 files changed
+46 -11

No files matched your search

+32 -10
View File
@@ -405,6 +405,20 @@ pub fn send(self: *XMLHttpRequest, body_: ?BodyInit, exec_: *const Execution) !v
self._response_url = self._url;
self._response_len = resp.body.items.len;
for (resp.headers) |hdr| {
if (std.ascii.eqlIgnoreCase(hdr.name, "content-type")) {
self.applyContentType(hdr.value) catch |e| {
log.info(.http, "invalid content type", .{
.content_Type = hdr.value,
.err = e,
.url = self._url,
});
};
break;
}
}
try self.applyResponseHeaders(.{ .list = .{ .list = resp.headers } });
try self._response_data.appendSlice(self._arena.allocator(), resp.body.items);
var ls: js.Local.Scope = undefined;
@@ -635,6 +649,22 @@ fn getResponseXML(self: *XMLHttpRequest, exec: *const Execution) !?*Node.Documen
}
}
fn applyContentType(self: *XMLHttpRequest, content_type: []const u8) !void {
self._response_mime = try Mime.parse(content_type);
self._response_mime_raw = try self._arena.dupe(u8, std.mem.trim(u8, content_type, &std.ascii.whitespace));
}
fn applyResponseHeaders(self: *XMLHttpRequest, headers: http.HeaderIterator) !void {
var it = headers;
while (it.next()) |hdr| {
if (Headers.isForbiddenResponseHeaderName(hdr.name)) {
continue;
}
const joined = try std.fmt.allocPrint(self._arena.allocator(), "{s}: {s}", .{ hdr.name, hdr.value });
try self._response_headers.append(self._arena.allocator(), joined);
}
}
fn httpHeaderDoneCallback(transfer: *Transfer) !Transfer.HeaderResult {
const self: *XMLHttpRequest = @ptrCast(@alignCast(transfer.req.ctx));
@@ -647,7 +677,7 @@ fn httpHeaderDoneCallback(transfer: *Transfer) !Transfer.HeaderResult {
}
if (transfer.contentType()) |ct| {
self._response_mime = Mime.parse(ct) catch |e| {
self.applyContentType(ct) catch |e| {
log.info(.http, "invalid content type", .{
.content_Type = ct,
.err = e,
@@ -655,17 +685,9 @@ fn httpHeaderDoneCallback(transfer: *Transfer) !Transfer.HeaderResult {
});
return .abort;
};
self._response_mime_raw = try self._arena.dupe(u8, std.mem.trim(u8, ct, &std.ascii.whitespace));
}
var it = transfer.responseHeaderIterator();
while (it.next()) |hdr| {
if (Headers.isForbiddenResponseHeaderName(hdr.name)) {
continue;
}
const joined = try std.fmt.allocPrint(self._arena.allocator(), "{s}: {s}", .{ hdr.name, hdr.value });
try self._response_headers.append(self._arena.allocator(), joined);
}
try self.applyResponseHeaders(transfer.responseHeaderIterator());
self._response_status = transfer.responseStatus().?;
if (transfer.statusText()) |st| {
+14 -1
View File
@@ -1436,6 +1436,7 @@ const SyncContext = struct {
status: u16 = 0,
status_text: http.StatusText = .{},
body: std.ArrayList(u8),
headers: std.ArrayList(http.Header) = .empty,
// Acquired on the first byte we have to buffer, so a bodyless response
// never takes one. Ownership moves to the SyncResponse.
@@ -1447,8 +1448,18 @@ const SyncContext = struct {
self.status = transfer.responseStatus().?;
self.status_text = transfer.res.status_text;
const body_len = transfer.bodyLen();
const allocator = try self.bodyAllocator(body_len);
var it = transfer.responseHeaderIterator();
while (it.next()) |hdr| {
try self.headers.append(allocator, .{
.name = try allocator.dupe(u8, hdr.name),
.value = try allocator.dupe(u8, hdr.value),
});
}
if (body_len > 0) {
try self.body.ensureTotalCapacityPrecise(try self.bodyAllocator(body_len), body_len);
try self.body.ensureTotalCapacityPrecise(allocator, body_len);
}
return .proceed;
}
@@ -2115,6 +2126,7 @@ const SyncResponse = struct {
status: u16,
body: std.ArrayList(u8),
status_text: http.StatusText,
headers: []const http.Header,
// Owns `body`. Null when the response had nothing to buffer. Callers that
// keep `body` past this call take the arena instead of releasing it.
@@ -2676,6 +2688,7 @@ pub const Transfer = struct {
.status = sync_ctx.status,
.status_text = sync_ctx.status_text,
.body = sync_ctx.body,
.headers = sync_ctx.headers.items,
.arena = sync_ctx.arena,
},
.err => |e| return e,