Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/browser/fetch/fetch.zig
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ pub const Interfaces = .{
};

pub const FetchContext = struct {
page: *Page,
arena: std.mem.Allocator,
js_ctx: *Env.JsContext,
promise_resolver: Env.PersistentPromiseResolver,

method: Http.Method,
Expand All @@ -63,9 +63,12 @@ pub const FetchContext = struct {
pub fn toResponse(self: *const FetchContext) !Response {
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.
// 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{
.status = 0,
.headers = headers,
Expand All @@ -85,7 +88,7 @@ pub const FetchContext = struct {
}

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;
}

Expand Down Expand Up @@ -132,8 +135,8 @@ pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !Env.Promi

const fetch_ctx = try arena.create(FetchContext);
fetch_ctx.* = .{
.page = page,
.arena = arena,
.js_ctx = page.main_context,
.promise_resolver = resolver,
.method = req.method,
.url = req.url,
Expand Down Expand Up @@ -234,6 +237,11 @@ pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !Env.Promi
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");
test "fetch: fetch" {
try testing.htmlRunner("fetch/fetch.html");
Expand Down
18 changes: 18 additions & 0 deletions src/tests/fetch/fetch.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,24 @@
const promise1 = new Promise((resolve) => {
fetch('http://127.0.0.1:9582/xhr/json')
.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()
})
.then((json) => {
Expand Down
2 changes: 2 additions & 0 deletions src/tests/testing.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@
async function async(promise, cb) {
const script_id = document.currentScript.id;
const stack = new Error().stack;
this._captured = {script_id: script_id, stack: stack};
const value = await promise;
// reset it, because await promise could change it.
this._captured = {script_id: script_id, stack: stack};
cb(value);
this._captured = null;
Expand Down