From ff9f9bae1db3c98a963b014c2d61507cdf9a1d50 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Thu, 4 Dec 2025 16:10:56 +0800 Subject: [PATCH] fetch with body --- src/browser/webapi/net/Fetch.zig | 3 ++- src/browser/webapi/net/Request.zig | 34 ++++++++++++++++++++---------- src/http/Http.zig | 2 ++ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/browser/webapi/net/Fetch.zig b/src/browser/webapi/net/Fetch.zig index 50d44270..88c961d7 100644 --- a/src/browser/webapi/net/Fetch.zig +++ b/src/browser/webapi/net/Fetch.zig @@ -69,7 +69,8 @@ pub fn init(input: Input, options: ?InitOpts, page: *Page) !js.Promise { try http_client.request(.{ .ctx = fetch, .url = request._url, - .method = .GET, + .method = request._method, + .body = request._body, .headers = headers, .resource_type = .fetch, .cookie_jar = &page._session.cookie_jar, diff --git a/src/browser/webapi/net/Request.zig b/src/browser/webapi/net/Request.zig index 8dea853f..d053b434 100644 --- a/src/browser/webapi/net/Request.zig +++ b/src/browser/webapi/net/Request.zig @@ -19,6 +19,7 @@ const std = @import("std"); const js = @import("../../js/js.zig"); +const Http = @import("../../../http/Http.zig"); const URL = @import("../URL.zig"); const Page = @import("../../Page.zig"); @@ -28,8 +29,9 @@ const Allocator = std.mem.Allocator; const Request = @This(); _url: [:0]const u8, -_method: std.http.Method, +_method: Http.Method, _headers: ?*Headers, +_body: ?[]const u8, _arena: Allocator, pub const Input = union(enum) { @@ -40,6 +42,7 @@ pub const Input = union(enum) { pub const InitOpts = struct { method: ?[]const u8 = null, headers: ?Headers.InitOpts = null, + body: ?[]const u8 = null, }; pub fn init(input: Input, opts_: ?InitOpts, page: *Page) !*Request { @@ -65,30 +68,39 @@ pub fn init(input: Input, opts_: ?InitOpts, page: *Page) !*Request { .request => |r| r._headers, }; + const body = if (opts.body) |b| + try arena.dupe(u8, b) + else switch (input) { + .url => null, + .request => |r| r._body, + }; + return page._factory.create(Request{ ._url = url, ._arena = arena, ._method = method, ._headers = headers, + ._body = body, }); } -fn parseMethod(method: []const u8, page: *Page) !std.http.Method { +fn parseMethod(method: []const u8, page: *Page) !Http.Method { if (method.len > "options".len) { return error.InvalidMethod; } const lower = std.ascii.lowerString(&page.buf, method); - if (std.mem.eql(u8, lower, "get")) return .GET; - if (std.mem.eql(u8, lower, "post")) return .POST; - if (std.mem.eql(u8, lower, "delete")) return .DELETE; - if (std.mem.eql(u8, lower, "put")) return .PUT; - if (std.mem.eql(u8, lower, "patch")) return .PATCH; - if (std.mem.eql(u8, lower, "head")) return .HEAD; - if (std.mem.eql(u8, lower, "options")) return .OPTIONS; - - return error.InvalidMethod; + const method_lookup = std.StaticStringMap(Http.Method).initComptime(.{ + .{ "get", .GET }, + .{ "post", .POST }, + .{ "delete", .DELETE }, + .{ "put", .PUT }, + .{ "patch", .PATCH }, + .{ "head", .HEAD }, + .{ "options", .OPTIONS }, + }); + return method_lookup.get(lower) orelse return error.InvalidMethod; } pub fn getUrl(self: *const Request) []const u8 { diff --git a/src/http/Http.zig b/src/http/Http.zig index e5be87ee..1a558029 100644 --- a/src/http/Http.zig +++ b/src/http/Http.zig @@ -222,6 +222,7 @@ pub const Connection = struct { .DELETE => "DELETE", .HEAD => "HEAD", .OPTIONS => "OPTIONS", + .PATCH => "PATCH", }; try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_CUSTOMREQUEST, m.ptr)); } @@ -360,6 +361,7 @@ pub const Method = enum(u8) { DELETE = 3, HEAD = 4, OPTIONS = 5, + PATCH = 6, }; // TODO: on BSD / Linux, we could just read the PEM file directly.