authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-06 19:56:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-07 10:04:52-07:00
log163a8278264218720180d22d26ccc24b835a0b15
tree6072de97180877aef4038ff9144bdc3ee6495413
parent4567241d8d238c47c0e0844af15764ccc851c8fc

std.http: remove custom method support

let's see if anybody notices it missing

4 files changed, 24 insertions(+), 47 deletions(-)

lib/std/http.zig+20-42
...@@ -20,51 +20,32 @@ pub const Version = enum {...@@ -20,51 +20,32 @@ pub const Version = enum {
20/// https://datatracker.ietf.org/doc/html/rfc7231#section-4 Initial definition20/// https://datatracker.ietf.org/doc/html/rfc7231#section-4 Initial definition
21///21///
22/// https://datatracker.ietf.org/doc/html/rfc5789#section-2 PATCH22/// https://datatracker.ietf.org/doc/html/rfc5789#section-2 PATCH
23pub const Method = enum(u64) {23pub const Method = enum {
24 GET = parse("GET"),24 GET,
25 HEAD = parse("HEAD"),25 HEAD,
26 POST = parse("POST"),26 POST,
27 PUT = parse("PUT"),27 PUT,
28 DELETE = parse("DELETE"),28 DELETE,
29 CONNECT = parse("CONNECT"),29 CONNECT,
30 OPTIONS = parse("OPTIONS"),30 OPTIONS,
31 TRACE = parse("TRACE"),31 TRACE,
32 PATCH = parse("PATCH"),32 PATCH,
33
34 _,
35
36 /// Converts `s` into a type that may be used as a `Method` field.
37 /// Asserts that `s` is 24 or fewer bytes.
38 pub fn parse(s: []const u8) u64 {
39 var x: u64 = 0;
40 const len = @min(s.len, @sizeOf(@TypeOf(x)));
41 @memcpy(std.mem.asBytes(&x)[0..len], s[0..len]);
42 return x;
43 }
44
45 pub fn format(self: Method, w: *Writer) Writer.Error!void {
46 const bytes: []const u8 = @ptrCast(&@intFromEnum(self));
47 const str = std.mem.sliceTo(bytes, 0);
48 try w.writeAll(str);
49 }
5033
51 /// Returns true if a request of this method is allowed to have a body34 /// Returns true if a request of this method is allowed to have a body
52 /// Actual behavior from servers may vary and should still be checked35 /// Actual behavior from servers may vary and should still be checked
53 pub fn requestHasBody(self: Method) bool {36 pub fn requestHasBody(m: Method) bool {
54 return switch (self) {37 return switch (m) {
55 .POST, .PUT, .PATCH => true,38 .POST, .PUT, .PATCH => true,
56 .GET, .HEAD, .DELETE, .CONNECT, .OPTIONS, .TRACE => false,39 .GET, .HEAD, .DELETE, .CONNECT, .OPTIONS, .TRACE => false,
57 else => true,
58 };40 };
59 }41 }
6042
61 /// Returns true if a response to this method is allowed to have a body43 /// Returns true if a response to this method is allowed to have a body
62 /// Actual behavior from clients may vary and should still be checked44 /// Actual behavior from clients may vary and should still be checked
63 pub fn responseHasBody(self: Method) bool {45 pub fn responseHasBody(m: Method) bool {
64 return switch (self) {46 return switch (m) {
65 .GET, .POST, .DELETE, .CONNECT, .OPTIONS, .PATCH => true,47 .GET, .POST, .DELETE, .CONNECT, .OPTIONS, .PATCH => true,
66 .HEAD, .PUT, .TRACE => false,48 .HEAD, .PUT, .TRACE => false,
67 else => true,
68 };49 };
69 }50 }
7051
...@@ -73,11 +54,10 @@ pub const Method = enum(u64) {...@@ -73,11 +54,10 @@ pub const Method = enum(u64) {
73 /// https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP54 /// https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP
74 ///55 ///
75 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.156 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.1
76 pub fn safe(self: Method) bool {57 pub fn safe(m: Method) bool {
77 return switch (self) {58 return switch (m) {
78 .GET, .HEAD, .OPTIONS, .TRACE => true,59 .GET, .HEAD, .OPTIONS, .TRACE => true,
79 .POST, .PUT, .DELETE, .CONNECT, .PATCH => false,60 .POST, .PUT, .DELETE, .CONNECT, .PATCH => false,
80 else => false,
81 };61 };
82 }62 }
8363
...@@ -88,11 +68,10 @@ pub const Method = enum(u64) {...@@ -88,11 +68,10 @@ pub const Method = enum(u64) {
88 /// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent68 /// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
89 ///69 ///
90 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.270 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.2
91 pub fn idempotent(self: Method) bool {71 pub fn idempotent(m: Method) bool {
92 return switch (self) {72 return switch (m) {
93 .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE => true,73 .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE => true,
94 .CONNECT, .POST, .PATCH => false,74 .CONNECT, .POST, .PATCH => false,
95 else => false,
96 };75 };
97 }76 }
9877
...@@ -102,11 +81,10 @@ pub const Method = enum(u64) {...@@ -102,11 +81,10 @@ pub const Method = enum(u64) {
102 /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable81 /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable
103 ///82 ///
104 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.383 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.3
105 pub fn cacheable(self: Method) bool {84 pub fn cacheable(m: Method) bool {
106 return switch (self) {85 return switch (m) {
107 .GET, .HEAD => true,86 .GET, .HEAD => true,
108 .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .TRACE, .PATCH => false,87 .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .TRACE, .PATCH => false,
109 else => false,
110 };88 };
111 }89 }
112};90};
lib/std/http/Client.zig+1-1
...@@ -928,7 +928,7 @@ pub const Request = struct {...@@ -928,7 +928,7 @@ pub const Request = struct {
928 const connection = r.connection.?;928 const connection = r.connection.?;
929 const w = connection.writer();929 const w = connection.writer();
930930
931 try r.method.format(w);931 try w.writeAll(@tagName(r.method));
932 try w.writeByte(' ');932 try w.writeByte(' ');
933933
934 if (r.method == .CONNECT) {934 if (r.method == .CONNECT) {
lib/std/http/Server.zig+2-3
...@@ -97,10 +97,9 @@ pub const Request = struct {...@@ -97,10 +97,9 @@ pub const Request = struct {
9797
98 const method_end = mem.indexOfScalar(u8, first_line, ' ') orelse98 const method_end = mem.indexOfScalar(u8, first_line, ' ') orelse
99 return error.HttpHeadersInvalid;99 return error.HttpHeadersInvalid;
100 if (method_end > 24) return error.HttpHeadersInvalid;
101100
102 const method_str = first_line[0..method_end];101 const method = std.meta.stringToEnum(http.Method, first_line[0..method_end]) orelse
103 const method: http.Method = @enumFromInt(http.Method.parse(method_str));102 return error.UnknownHttpMethod;
104103
105 const version_start = mem.lastIndexOfScalar(u8, first_line, ' ') orelse104 const version_start = mem.lastIndexOfScalar(u8, first_line, ' ') orelse
106 return error.HttpHeadersInvalid;105 return error.HttpHeadersInvalid;
lib/std/http/test.zig+1-1
...@@ -413,7 +413,7 @@ test "general client/server API coverage" {...@@ -413,7 +413,7 @@ test "general client/server API coverage" {
413 const log = std.log.scoped(.server);413 const log = std.log.scoped(.server);
414 const gpa = std.testing.allocator;414 const gpa = std.testing.allocator;
415415
416 log.info("{f} {t} {s}", .{ request.head.method, request.head.version, request.head.target });416 log.info("{t} {t} {s}", .{ request.head.method, request.head.version, request.head.target });
417 const target = try gpa.dupe(u8, request.head.target);417 const target = try gpa.dupe(u8, request.head.target);
418 defer gpa.free(target);418 defer gpa.free(target);
419419