| author | |
| committer | |
| log | c523b5421be86cdd0591a5672eeaea30fb142fe4 |
| tree | 17b23ca55286378604d878930523a32cf0fe796b |
| parent | 16f89eab45c4356f8f1d824c342e76aee8ddff90 |
| signature | Commit is signed but in an unrecognized format. |
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) { |
| 289 | 289 | ||
| 290 | pub const TransferEncoding = enum { | 290 | pub const TransferEncoding = enum { |
| 291 | chunked, | 291 | chunked, |
| 292 | none, | ||
| 292 | // compression is intentionally omitted here, as std.http.Client stores it as content-encoding | 293 | // compression is intentionally omitted here, as std.http.Client stores it as content-encoding |
| 293 | }; | 294 | }; |
| 294 | 295 | ||
| 295 | pub const ContentEncoding = enum { | 296 | pub 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 | }; |
| 302 | 305 |
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, chunked | 425 | // Transfer-Encoding: deflate, chunked |
| 426 | var iter = mem.splitBackwardsScalar(u8, header_value, ','); | 426 | var iter = mem.splitBackwardsScalar(u8, header_value, ','); |
| 427 | 427 | ||
| 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 | } | ||
| 441 | 430 | ||
| 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; | ||
| 444 | 435 | ||
| 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, " "); | ||
| 446 | 441 | ||
| 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 { |
| 459 | 455 | ||
| 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; |
| 463 | 459 | ||
| 464 | const trimmed = mem.trim(u8, header_value, " "); | 460 | const trimmed = mem.trim(u8, header_value, " "); |
| 465 | 461 | ||
| ... | @@ -494,8 +490,8 @@ pub const Response = struct { | ... | @@ -494,8 +490,8 @@ pub const Response = struct { |
| 494 | reason: []const u8, | 490 | reason: []const u8, |
| 495 | 491 | ||
| 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, |
| 499 | 495 | ||
| 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 | } |
| 773 | 769 | ||
| 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 | } |
| 857 | 854 | ||
| 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, chunked | 228 | // Transfer-Encoding: deflate, chunked |
| 229 | var iter = mem.splitBackwardsScalar(u8, header_value, ','); | 229 | var iter = mem.splitBackwardsScalar(u8, header_value, ','); |
| 230 | 230 | ||
| 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 | } | ||
| 244 | 233 | ||
| 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; | ||
| 247 | 238 | ||
| 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, " "); | ||
| 249 | 244 | ||
| 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 { |
| 256 | 252 | ||
| 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; |
| 260 | 256 | ||
| 261 | const trimmed = mem.trim(u8, header_value, " "); | 257 | const trimmed = mem.trim(u8, header_value, " "); |
| 262 | 258 | ||
| ... | @@ -278,8 +274,8 @@ pub const Request = struct { | ... | @@ -278,8 +274,8 @@ pub const Request = struct { |
| 278 | version: http.Version, | 274 | version: http.Version, |
| 279 | 275 | ||
| 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, |
| 283 | 279 | ||
| 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); |
| 513 | 509 | ||
| 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 | } |
| 528 | 525 | ||
| 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 | } |
| 545 | 542 | ||
| ... | @@ -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(); |
| 756 | 753 | ||
| 757 | try expect(res.request.transfer_encoding.? == .chunked); | 754 | try expect(res.request.transfer_encoding == .chunked); |
| 758 | 755 | ||
| 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 }; |