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
29 changes: 18 additions & 11 deletions src/bun.js/webcore/response.zig
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ pub const Fetch = struct {

pub const fetch_error_no_args = "fetch() expects a string but received no arguments.";
pub const fetch_error_blank_url = "fetch() URL must not be a blank string.";
pub const fetch_error_unexpected_body = "fetch() request with GET/HEAD/OPTIONS method cannot have body.";
const JSTypeErrorEnum = std.enums.EnumArray(JSType, string);
pub const fetch_type_error_names: JSTypeErrorEnum = brk: {
var errors = JSTypeErrorEnum.initUndefined();
Expand Down Expand Up @@ -799,8 +800,8 @@ pub const Fetch = struct {
var globalThis = ctx.ptr();

if (arguments.len == 0) {
const fetch_error = fetch_error_no_args;
return JSPromise.rejectedPromiseValue(globalThis, ZigString.init(fetch_error).toErrorInstance(globalThis)).asRef();
const err = JSC.toTypeError(.ERR_MISSING_ARGS, fetch_error_no_args, .{}, ctx);
return JSPromise.rejectedPromiseValue(globalThis, err).asRef();
}

var headers: ?Headers = null;
Expand Down Expand Up @@ -1002,8 +1003,8 @@ pub const Fetch = struct {
var url_zig = proxy_str.getZigString(globalThis);

if (url_zig.len == 0) {
const fetch_error = fetch_error_blank_url;
return JSPromise.rejectedPromiseValue(globalThis, ZigString.init(fetch_error).toErrorInstance(globalThis)).asRef();
const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, fetch_error_blank_url, .{}, ctx);
return JSPromise.rejectedPromiseValue(globalThis, err).asRef();
}

if (proxy_arg.isNull()) {
Expand Down Expand Up @@ -1056,8 +1057,8 @@ pub const Fetch = struct {
};

if (url_slice.len == 0) {
const fetch_error = fetch_error_blank_url;
return JSPromise.rejectedPromiseValue(globalThis, ZigString.init(fetch_error).toErrorInstance(globalThis)).asRef();
const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, fetch_error_blank_url, .{}, ctx);
return JSPromise.rejectedPromiseValue(globalThis, err).asRef();
}

url = ZigURL.parse(url_slice.slice());
Expand All @@ -1071,8 +1072,8 @@ pub const Fetch = struct {
};

if (url_slice.len == 0) {
const fetch_error = fetch_error_blank_url;
return JSPromise.rejectedPromiseValue(globalThis, ZigString.init(fetch_error).toErrorInstance(globalThis)).asRef();
const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, fetch_error_blank_url, .{}, ctx);
return JSPromise.rejectedPromiseValue(globalThis, err).asRef();
}

url = ZigURL.parse(url_slice.slice());
Expand All @@ -1087,21 +1088,27 @@ pub const Fetch = struct {
};

if (url_slice.len == 0) {
const fetch_error = fetch_error_blank_url;
return JSPromise.rejectedPromiseValue(globalThis, ZigString.init(fetch_error).toErrorInstance(globalThis)).asRef();
const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, fetch_error_blank_url, .{}, ctx);
return JSPromise.rejectedPromiseValue(globalThis, err).asRef();
}

url = ZigURL.parse(url_slice.slice());
url_proxy_buffer = url.href;
}
} else {
const fetch_error = fetch_type_error_strings.get(js.JSValueGetType(ctx, arguments[0]));
exception.* = ZigString.init(fetch_error).toErrorInstance(globalThis).asObjectRef();
const err = JSC.toTypeError(.ERR_INVALID_ARG_TYPE, "{s}", .{fetch_error}, ctx);
exception.* = err.asObjectRef();
return null;
}

var deferred_promise = JSC.C.JSObjectMakeDeferredPromise(globalThis, null, null, null);

if (!method.hasRequestBody() and body.size() > 0) {
const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, fetch_error_unexpected_body, .{}, ctx);
return JSPromise.rejectedPromiseValue(globalThis, err).asRef();
}

// var resolve = FetchTasklet.FetchResolver.Class.make(ctx: js.JSContextRef, ptr: *ZigType)
_ = FetchTasklet.queue(
default_allocator,
Expand Down
27 changes: 26 additions & 1 deletion test/bun.js/fetch.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,31 @@ describe("fetch", () => {
expect(response.redirected).toBe(true);
server.stop();
});

it("provide body", async () => {
const server = Bun.serve({
port: 4084,
fetch(req) {
return new Response(req.body);
},
});

// POST with body
const url = `http://${server.hostname}:${server.port}`;
const response = await fetch(url, { method: "POST", body: "buntastic" });
expect(response.status).toBe(200);
expect(await response.text()).toBe("buntastic");

// GET cannot have body
try {
await fetch(url, { body: "buntastic" });
expect(false).toBe(true);
} catch (exception) {
expect(exception instanceof TypeError).toBe(true);
}

server.stop();
});
});

it("simultaneous HTTPS fetch", async () => {
Expand Down Expand Up @@ -630,7 +655,7 @@ describe("Response", () => {
await body.json();
expect(false).toBe(true);
} catch (exception) {
expect(exception instanceof SyntaxError);
expect(exception instanceof SyntaxError).toBe(true);
}
});

Expand Down