Set Response.type to basic on same-origin requests

This commit is contained in:
Karl Seguin
2025-09-23 11:35:51 +08:00
parent db166b4633
commit 6bad2b16e4
3 changed files with 32 additions and 4 deletions

View File

@@ -43,8 +43,8 @@ pub const Interfaces = .{
}; };
pub const FetchContext = struct { pub const FetchContext = struct {
page: *Page,
arena: std.mem.Allocator, arena: std.mem.Allocator,
js_ctx: *Env.JsContext,
promise_resolver: Env.PersistentPromiseResolver, promise_resolver: Env.PersistentPromiseResolver,
method: Http.Method, method: Http.Method,
@@ -63,9 +63,12 @@ pub const FetchContext = struct {
pub fn toResponse(self: *const FetchContext) !Response { pub fn toResponse(self: *const FetchContext) !Response {
var headers: Headers = .{}; var headers: Headers = .{};
// seems to be the highest priority
const same_origin = try isSameOriginAsPage(self.url, self.page);
// If the mode is "no-cors", we need to return this opaque/stripped Response. // If the mode is "no-cors", we need to return this opaque/stripped Response.
// https://developer.mozilla.org/en-US/docs/Web/API/Response/type // https://developer.mozilla.org/en-US/docs/Web/API/Response/type
if (self.mode == .@"no-cors") { if (!same_origin and self.mode == .@"no-cors") {
return Response{ return Response{
.status = 0, .status = 0,
.headers = headers, .headers = headers,
@@ -85,7 +88,7 @@ pub const FetchContext = struct {
} }
const resp_type: Response.ResponseType = blk: { const resp_type: Response.ResponseType = blk: {
if (std.mem.startsWith(u8, self.url, "data:")) { if (same_origin or std.mem.startsWith(u8, self.url, "data:")) {
break :blk .basic; break :blk .basic;
} }
@@ -132,8 +135,8 @@ pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !Env.Promi
const fetch_ctx = try arena.create(FetchContext); const fetch_ctx = try arena.create(FetchContext);
fetch_ctx.* = .{ fetch_ctx.* = .{
.page = page,
.arena = arena, .arena = arena,
.js_ctx = page.main_context,
.promise_resolver = resolver, .promise_resolver = resolver,
.method = req.method, .method = req.method,
.url = req.url, .url = req.url,
@@ -234,6 +237,11 @@ pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !Env.Promi
return resolver.promise(); return resolver.promise();
} }
fn isSameOriginAsPage(url: []const u8, page: *const Page) !bool {
const origin = try page.origin(page.call_arena);
return std.mem.startsWith(u8, url, origin);
}
const testing = @import("../../testing.zig"); const testing = @import("../../testing.zig");
test "fetch: fetch" { test "fetch: fetch" {
try testing.htmlRunner("fetch/fetch.html"); try testing.htmlRunner("fetch/fetch.html");

View File

@@ -3,6 +3,24 @@
const promise1 = new Promise((resolve) => { const promise1 = new Promise((resolve) => {
fetch('http://127.0.0.1:9582/xhr/json') fetch('http://127.0.0.1:9582/xhr/json')
.then((res) => { .then((res) => {
testing.expectEqual('cors', res.type);
return res.json()
})
.then((json) => {
resolve(json);
});
});
testing.async(promise1, (json) => {
testing.expectEqual({over: '9000!!!'}, json);
});
</script>
<script id=same-origin type=module>
const promise1 = new Promise((resolve) => {
fetch('http://localhost:9582/xhr/json')
.then((res) => {
testing.expectEqual('basic', res.type);
return res.json() return res.json()
}) })
.then((json) => { .then((json) => {

View File

@@ -95,7 +95,9 @@
async function async(promise, cb) { async function async(promise, cb) {
const script_id = document.currentScript.id; const script_id = document.currentScript.id;
const stack = new Error().stack; const stack = new Error().stack;
this._captured = {script_id: script_id, stack: stack};
const value = await promise; const value = await promise;
// reset it, because await promise could change it.
this._captured = {script_id: script_id, stack: stack}; this._captured = {script_id: script_id, stack: stack};
cb(value); cb(value);
this._captured = null; this._captured = null;