authorgravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2023-10-06 21:38:05-05:00
committergravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2023-10-21 20:52:59-05:00
logc523b5421be86cdd0591a5672eeaea30fb142fe4
tree17b23ca55286378604d878930523a32cf0fe796b
parent16f89eab45c4356f8f1d824c342e76aee8ddff90
signature Commit is signed but in an unrecognized format.

std.http: make encoding fields non-null, store as enum variant


3 files changed, 52 insertions(+), 55 deletions(-)

lib/std/http.zig+3
...@@ -289,14 +289,17 @@ pub const Status = enum(u10) {...@@ -289,14 +289,17 @@ pub const Status = enum(u10) {
289289
290pub const TransferEncoding = enum {290pub const TransferEncoding = enum {
291 chunked,291 chunked,
292 none,
292 // compression is intentionally omitted here, as std.http.Client stores it as content-encoding293 // compression is intentionally omitted here, as std.http.Client stores it as content-encoding
293};294};
294295
295pub const ContentEncoding = enum {296pub const ContentEncoding = enum {
296 identity,297 identity,
297 compress,298 compress,
299 @"x-compress",
298 deflate,300 deflate,
299 gzip,301 gzip,
302 @"x-gzip",
300 zstd,303 zstd,
301};304};
302305
lib/std/http/Client.zig+24-27
...@@ -425,27 +425,23 @@ pub const Response = struct {...@@ -425,27 +425,23 @@ pub const Response = struct {
425 // Transfer-Encoding: deflate, chunked425 // Transfer-Encoding: deflate, chunked
426 var iter = mem.splitBackwardsScalar(u8, header_value, ',');426 var iter = mem.splitBackwardsScalar(u8, header_value, ',');
427427
428 if (iter.next()) |first| {428 const first = iter.first();
429 const trimmed = mem.trim(u8, first, " ");429 const trimmed_first = mem.trim(u8, first, " ");
430
431 if (std.meta.stringToEnum(http.TransferEncoding, trimmed)) |te| {
432 if (res.transfer_encoding != null) return error.HttpHeadersInvalid;
433 res.transfer_encoding = te;
434 } else if (std.meta.stringToEnum(http.ContentEncoding, trimmed)) |ce| {
435 if (res.transfer_compression != null) return error.HttpHeadersInvalid;
436 res.transfer_compression = ce;
437 } else {
438 return error.HttpTransferEncodingUnsupported;
439 }
440 }
441430
442 if (iter.next()) |second| {431 var next: ?[]const u8 = first;
443 if (res.transfer_compression != null) return error.HttpTransferEncodingUnsupported;432 if (std.meta.stringToEnum(http.TransferEncoding, trimmed_first)) |transfer| {
433 if (res.transfer_encoding != .none) return error.HttpHeadersInvalid; // we already have a transfer encoding
434 res.transfer_encoding = transfer;
444435
445 const trimmed = mem.trim(u8, second, " ");436 next = iter.next();
437 }
438
439 if (next) |second| {
440 const trimmed_second = mem.trim(u8, second, " ");
446441
447 if (std.meta.stringToEnum(http.ContentEncoding, trimmed)) |ce| {442 if (std.meta.stringToEnum(http.ContentEncoding, trimmed_second)) |transfer| {
448 res.transfer_compression = ce;443 if (res.transfer_compression != .identity) return error.HttpHeadersInvalid; // double compression is not supported
444 res.transfer_compression = transfer;
449 } else {445 } else {
450 return error.HttpTransferEncodingUnsupported;446 return error.HttpTransferEncodingUnsupported;
451 }447 }
...@@ -459,7 +455,7 @@ pub const Response = struct {...@@ -459,7 +455,7 @@ pub const Response = struct {
459455
460 res.content_length = content_length;456 res.content_length = content_length;
461 } else if (std.ascii.eqlIgnoreCase(header_name, "content-encoding")) {457 } else if (std.ascii.eqlIgnoreCase(header_name, "content-encoding")) {
462 if (res.transfer_compression != null) return error.HttpHeadersInvalid;458 if (res.transfer_compression != .identity) return error.HttpHeadersInvalid;
463459
464 const trimmed = mem.trim(u8, header_value, " ");460 const trimmed = mem.trim(u8, header_value, " ");
465461
...@@ -494,8 +490,8 @@ pub const Response = struct {...@@ -494,8 +490,8 @@ pub const Response = struct {
494 reason: []const u8,490 reason: []const u8,
495491
496 content_length: ?u64 = null,492 content_length: ?u64 = null,
497 transfer_encoding: ?http.TransferEncoding = null,493 transfer_encoding: http.TransferEncoding = .none,
498 transfer_compression: ?http.ContentEncoding = null,494 transfer_compression: http.ContentEncoding = .identity,
499495
500 headers: http.Headers,496 headers: http.Headers,
501 parser: proto.HeadersParser,497 parser: proto.HeadersParser,
...@@ -771,8 +767,9 @@ pub const Request = struct {...@@ -771,8 +767,9 @@ pub const Request = struct {
771 req.connection.?.closing = true;767 req.connection.?.closing = true;
772 }768 }
773769
774 if (req.response.transfer_encoding) |te| {770 if (req.response.transfer_encoding != .none) {
775 switch (te) {771 switch (req.response.transfer_encoding) {
772 .none => unreachable,
776 .chunked => {773 .chunked => {
777 req.response.parser.next_chunk_length = 0;774 req.response.parser.next_chunk_length = 0;
778 req.response.parser.state = .chunk_head_size;775 req.response.parser.state = .chunk_head_size;
...@@ -840,19 +837,19 @@ pub const Request = struct {...@@ -840,19 +837,19 @@ pub const Request = struct {
840 } else {837 } else {
841 req.response.skip = false;838 req.response.skip = false;
842 if (!req.response.parser.done) {839 if (!req.response.parser.done) {
843 if (req.response.transfer_compression) |tc| switch (tc) {840 switch (req.response.transfer_compression) {
844 .identity => req.response.compression = .none,841 .identity => req.response.compression = .none,
845 .compress => return error.CompressionNotSupported,842 .compress, .@"x-compress" => return error.CompressionNotSupported,
846 .deflate => req.response.compression = .{843 .deflate => req.response.compression = .{
847 .deflate = std.compress.zlib.decompressStream(req.client.allocator, req.transferReader()) catch return error.CompressionInitializationFailed,844 .deflate = std.compress.zlib.decompressStream(req.client.allocator, req.transferReader()) catch return error.CompressionInitializationFailed,
848 },845 },
849 .gzip => req.response.compression = .{846 .gzip, .@"x-gzip" => req.response.compression = .{
850 .gzip = std.compress.gzip.decompress(req.client.allocator, req.transferReader()) catch return error.CompressionInitializationFailed,847 .gzip = std.compress.gzip.decompress(req.client.allocator, req.transferReader()) catch return error.CompressionInitializationFailed,
851 },848 },
852 .zstd => req.response.compression = .{849 .zstd => req.response.compression = .{
853 .zstd = std.compress.zstd.decompressStream(req.client.allocator, req.transferReader()),850 .zstd = std.compress.zstd.decompressStream(req.client.allocator, req.transferReader()),
854 },851 },
855 };852 }
856 }853 }
857854
858 break;855 break;
lib/std/http/Server.zig+25-28
...@@ -228,27 +228,23 @@ pub const Request = struct {...@@ -228,27 +228,23 @@ pub const Request = struct {
228 // Transfer-Encoding: deflate, chunked228 // Transfer-Encoding: deflate, chunked
229 var iter = mem.splitBackwardsScalar(u8, header_value, ',');229 var iter = mem.splitBackwardsScalar(u8, header_value, ',');
230230
231 if (iter.next()) |first| {231 const first = iter.first();
232 const trimmed = mem.trim(u8, first, " ");232 const trimmed_first = mem.trim(u8, first, " ");
233
234 if (std.meta.stringToEnum(http.TransferEncoding, trimmed)) |te| {
235 if (req.transfer_encoding != null) return error.HttpHeadersInvalid;
236 req.transfer_encoding = te;
237 } else if (std.meta.stringToEnum(http.ContentEncoding, trimmed)) |ce| {
238 if (req.transfer_compression != null) return error.HttpHeadersInvalid;
239 req.transfer_compression = ce;
240 } else {
241 return error.HttpTransferEncodingUnsupported;
242 }
243 }
244233
245 if (iter.next()) |second| {234 var next: ?[]const u8 = first;
246 if (req.transfer_compression != null) return error.HttpTransferEncodingUnsupported;235 if (std.meta.stringToEnum(http.TransferEncoding, trimmed_first)) |transfer| {
236 if (req.transfer_encoding != .none) return error.HttpHeadersInvalid; // we already have a transfer encoding
237 req.transfer_encoding = transfer;
247238
248 const trimmed = mem.trim(u8, second, " ");239 next = iter.next();
240 }
241
242 if (next) |second| {
243 const trimmed_second = mem.trim(u8, second, " ");
249244
250 if (std.meta.stringToEnum(http.ContentEncoding, trimmed)) |ce| {245 if (std.meta.stringToEnum(http.ContentEncoding, trimmed_second)) |transfer| {
251 req.transfer_compression = ce;246 if (req.transfer_compression != .identity) return error.HttpHeadersInvalid; // double compression is not supported
247 req.transfer_compression = transfer;
252 } else {248 } else {
253 return error.HttpTransferEncodingUnsupported;249 return error.HttpTransferEncodingUnsupported;
254 }250 }
...@@ -256,7 +252,7 @@ pub const Request = struct {...@@ -256,7 +252,7 @@ pub const Request = struct {
256252
257 if (iter.next()) |_| return error.HttpTransferEncodingUnsupported;253 if (iter.next()) |_| return error.HttpTransferEncodingUnsupported;
258 } else if (std.ascii.eqlIgnoreCase(header_name, "content-encoding")) {254 } else if (std.ascii.eqlIgnoreCase(header_name, "content-encoding")) {
259 if (req.transfer_compression != null) return error.HttpHeadersInvalid;255 if (req.transfer_compression != .identity) return error.HttpHeadersInvalid;
260256
261 const trimmed = mem.trim(u8, header_value, " ");257 const trimmed = mem.trim(u8, header_value, " ");
262258
...@@ -278,8 +274,8 @@ pub const Request = struct {...@@ -278,8 +274,8 @@ pub const Request = struct {
278 version: http.Version,274 version: http.Version,
279275
280 content_length: ?u64 = null,276 content_length: ?u64 = null,
281 transfer_encoding: ?http.TransferEncoding = null,277 transfer_encoding: http.TransferEncoding = .none,
282 transfer_compression: ?http.ContentEncoding = null,278 transfer_compression: http.ContentEncoding = .identity,
283279
284 headers: http.Headers,280 headers: http.Headers,
285 parser: proto.HeadersParser,281 parser: proto.HeadersParser,
...@@ -511,8 +507,9 @@ pub const Response = struct {...@@ -511,8 +507,9 @@ pub const Response = struct {
511 res.request.headers = .{ .allocator = res.allocator, .owned = true };507 res.request.headers = .{ .allocator = res.allocator, .owned = true };
512 try res.request.parse(res.request.parser.header_bytes.items);508 try res.request.parse(res.request.parser.header_bytes.items);
513509
514 if (res.request.transfer_encoding) |te| {510 if (res.request.transfer_encoding != .none) {
515 switch (te) {511 switch (res.request.transfer_encoding) {
512 .none => unreachable,
516 .chunked => {513 .chunked => {
517 res.request.parser.next_chunk_length = 0;514 res.request.parser.next_chunk_length = 0;
518 res.request.parser.state = .chunk_head_size;515 res.request.parser.state = .chunk_head_size;
...@@ -527,19 +524,19 @@ pub const Response = struct {...@@ -527,19 +524,19 @@ pub const Response = struct {
527 }524 }
528525
529 if (!res.request.parser.done) {526 if (!res.request.parser.done) {
530 if (res.request.transfer_compression) |tc| switch (tc) {527 switch (res.request.transfer_compression) {
531 .identity => res.request.compression = .none,528 .identity => res.request.compression = .none,
532 .compress => return error.CompressionNotSupported,529 .compress, .@"x-compress" => return error.CompressionNotSupported,
533 .deflate => res.request.compression = .{530 .deflate => res.request.compression = .{
534 .deflate = std.compress.zlib.decompressStream(res.allocator, res.transferReader()) catch return error.CompressionInitializationFailed,531 .deflate = std.compress.zlib.decompressStream(res.allocator, res.transferReader()) catch return error.CompressionInitializationFailed,
535 },532 },
536 .gzip => res.request.compression = .{533 .gzip, .@"x-gzip" => res.request.compression = .{
537 .gzip = std.compress.gzip.decompress(res.allocator, res.transferReader()) catch return error.CompressionInitializationFailed,534 .gzip = std.compress.gzip.decompress(res.allocator, res.transferReader()) catch return error.CompressionInitializationFailed,
538 },535 },
539 .zstd => res.request.compression = .{536 .zstd => res.request.compression = .{
540 .zstd = std.compress.zstd.decompressStream(res.allocator, res.transferReader()),537 .zstd = std.compress.zstd.decompressStream(res.allocator, res.transferReader()),
541 },538 },
542 };539 }
543 }540 }
544 }541 }
545542
...@@ -754,7 +751,7 @@ test "HTTP server handles a chunked transfer coding request" {...@@ -754,7 +751,7 @@ test "HTTP server handles a chunked transfer coding request" {
754 defer _ = res.reset();751 defer _ = res.reset();
755 try res.wait();752 try res.wait();
756753
757 try expect(res.request.transfer_encoding.? == .chunked);754 try expect(res.request.transfer_encoding == .chunked);
758755
759 const server_body: []const u8 = "message from server!\n";756 const server_body: []const u8 = "message from server!\n";
760 res.transfer_encoding = .{ .content_length = server_body.len };757 res.transfer_encoding = .{ .content_length = server_body.len };