aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-02-12 23:03:06 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-02-23 02:37:11 -0700
commit4d401e6159be774537bfcf8b57db7db1b44979e1 (patch)
tree9dbfdee96b9c2cb779000c4689e4fe421cf35346 /test
parentf46447e6a1cda2b3b2e0ee90a68b2cca112f8742 (diff)
downloadzig-4d401e6159be774537bfcf8b57db7db1b44979e1.tar.gz
zig-4d401e6159be774537bfcf8b57db7db1b44979e1.zip
std.http: remove Headers API
I originally removed these in 402f967ed5339fa3d828b7fe1d57cdb5bf38dbf2. I allowed them to be added back in #15299 because they were smuggled in alongside a bug fix, however, I wasn't kidding when I said that I wanted to take the design of std.http in a different direction than using this data structure. Instead, some headers are provided via explicit field names populated while parsing the HTTP request/response, and some are provided via new fields that support passing extra, arbitrary headers. This resulted in simplification of logic in many places, as well as elimination of the possibility of failure in many places. There is less deinitialization code happening now. Furthermore, it made it no longer necessary to clone the headers data structure in order to handle redirects. http_proxy and https_proxy fields are now pointers since it is common for them to be unpopulated. loadDefaultProxies is changed into initDefaultProxies to communicate that it does not actually load anything from disk or from the network. The function now is leaky; the API user must pass an already instantiated arena allocator. Removes the need to deinitialize proxies. Before, proxies stored arbitrary sets of headers. Now they only store the authorization value. Removed the duplicated code between https_proxy and http_proxy. Finally, parsing failures of the environment variables result in errors being emitted rather than silently ignoring the proxy. error.CompressionNotSupported is renamed to error.CompressionUnsupported, matching the naming convention from all the other errors in the same set. Removed documentation comments that were redundant with field and type names. Disabling zstd decompression in the server for now; see #18937. I found some apparently dead code in src/Package/Fetch/git.zig. I want to check with Ian about this. I discovered that test/standalone/http.zig is dead code, it is only being compiled but not being run. Furthermore it hangs at the end if you run it manually. The previous commits in this branch were written under the assumption that this test was being run with `zig build test-standalone`.
Diffstat (limited to 'test')
-rw-r--r--test/standalone/http.zig188
1 files changed, 79 insertions, 109 deletions
diff --git a/test/standalone/http.zig b/test/standalone/http.zig
index a50721e4d0..c11bf9a0a7 100644
--- a/test/standalone/http.zig
+++ b/test/standalone/http.zig
@@ -26,8 +26,8 @@ fn handleRequest(res: *Server.Response) !void {
log.info("{} {s} {s}", .{ res.request.method, @tagName(res.request.version), res.request.target });
- if (res.request.headers.contains("expect")) {
- if (mem.eql(u8, res.request.headers.getFirstValue("expect").?, "100-continue")) {
+ if (res.request.expect) |expect| {
+ if (mem.eql(u8, expect, "100-continue")) {
res.status = .@"continue";
try res.send();
res.status = .ok;
@@ -41,8 +41,8 @@ fn handleRequest(res: *Server.Response) !void {
const body = try res.reader().readAllAlloc(salloc, 8192);
defer salloc.free(body);
- if (res.request.headers.contains("connection")) {
- try res.headers.append("connection", "keep-alive");
+ if (res.request.keep_alive) {
+ res.keep_alive = true;
}
if (mem.startsWith(u8, res.request.target, "/get")) {
@@ -52,7 +52,9 @@ fn handleRequest(res: *Server.Response) !void {
res.transfer_encoding = .{ .content_length = 14 };
}
- try res.headers.append("content-type", "text/plain");
+ res.extra_headers = &.{
+ .{ .name = "content-type", .value = "text/plain" },
+ };
try res.send();
if (res.request.method != .HEAD) {
@@ -82,14 +84,14 @@ fn handleRequest(res: *Server.Response) !void {
try res.finish();
} else if (mem.startsWith(u8, res.request.target, "/echo-content")) {
try testing.expectEqualStrings("Hello, World!\n", body);
- try testing.expectEqualStrings("text/plain", res.request.headers.getFirstValue("content-type").?);
-
- if (res.request.headers.contains("transfer-encoding")) {
- try testing.expectEqualStrings("chunked", res.request.headers.getFirstValue("transfer-encoding").?);
- res.transfer_encoding = .chunked;
- } else {
- res.transfer_encoding = .{ .content_length = 14 };
- try testing.expectEqualStrings("14", res.request.headers.getFirstValue("content-length").?);
+ try testing.expectEqualStrings("text/plain", res.request.content_type.?);
+
+ switch (res.request.transfer_encoding) {
+ .chunked => res.transfer_encoding = .chunked,
+ .none => {
+ res.transfer_encoding = .{ .content_length = 14 };
+ try testing.expectEqual(14, res.request.content_length.?);
+ },
}
try res.send();
@@ -108,7 +110,9 @@ fn handleRequest(res: *Server.Response) !void {
res.transfer_encoding = .chunked;
res.status = .found;
- try res.headers.append("location", "../../get");
+ res.extra_headers = &.{
+ .{ .name = "location", .value = "../../get" },
+ };
try res.send();
try res.writeAll("Hello, ");
@@ -118,7 +122,9 @@ fn handleRequest(res: *Server.Response) !void {
res.transfer_encoding = .chunked;
res.status = .found;
- try res.headers.append("location", "/redirect/1");
+ res.extra_headers = &.{
+ .{ .name = "location", .value = "/redirect/1" },
+ };
try res.send();
try res.writeAll("Hello, ");
@@ -131,7 +137,9 @@ fn handleRequest(res: *Server.Response) !void {
defer salloc.free(location);
res.status = .found;
- try res.headers.append("location", location);
+ res.extra_headers = &.{
+ .{ .name = "location", .value = location },
+ };
try res.send();
try res.writeAll("Hello, ");
@@ -141,7 +149,9 @@ fn handleRequest(res: *Server.Response) !void {
res.transfer_encoding = .chunked;
res.status = .found;
- try res.headers.append("location", "/redirect/3");
+ res.extra_headers = &.{
+ .{ .name = "location", .value = "/redirect/3" },
+ };
try res.send();
try res.writeAll("Hello, ");
@@ -153,7 +163,9 @@ fn handleRequest(res: *Server.Response) !void {
defer salloc.free(location);
res.status = .found;
- try res.headers.append("location", location);
+ res.extra_headers = &.{
+ .{ .name = "location", .value = location },
+ };
try res.send();
try res.finish();
} else {
@@ -234,19 +246,20 @@ pub fn main() !void {
errdefer client.deinit();
// defer client.deinit(); handled below
- try client.loadDefaultProxies();
+ var arena_instance = std.heap.ArenaAllocator.init(calloc);
+ defer arena_instance.deinit();
+ const arena = arena_instance.allocator();
- { // read content-length response
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
+ try client.initDefaultProxies(arena);
+ { // read content-length response
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/get", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -258,23 +271,20 @@ pub fn main() !void {
defer calloc.free(body);
try testing.expectEqualStrings("Hello, World!\n", body);
- try testing.expectEqualStrings("text/plain", req.response.headers.getFirstValue("content-type").?);
+ try testing.expectEqualStrings("text/plain", req.response.content_type.?);
}
// connection has been kept alive
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // read large content-length response
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/large", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -292,16 +302,13 @@ pub fn main() !void {
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // send head request and not read chunked
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/get", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.HEAD, uri, h, .{
+ var req = try client.open(.HEAD, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -313,24 +320,21 @@ pub fn main() !void {
defer calloc.free(body);
try testing.expectEqualStrings("", body);
- try testing.expectEqualStrings("text/plain", req.response.headers.getFirstValue("content-type").?);
- try testing.expectEqualStrings("14", req.response.headers.getFirstValue("content-length").?);
+ try testing.expectEqualStrings("text/plain", req.response.content_type.?);
+ try testing.expectEqual(14, req.response.content_length.?);
}
// connection has been kept alive
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // read chunked response
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/get?chunked", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -342,23 +346,20 @@ pub fn main() !void {
defer calloc.free(body);
try testing.expectEqualStrings("Hello, World!\n", body);
- try testing.expectEqualStrings("text/plain", req.response.headers.getFirstValue("content-type").?);
+ try testing.expectEqualStrings("text/plain", req.response.content_type.?);
}
// connection has been kept alive
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // send head request and not read chunked
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/get?chunked", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.HEAD, uri, h, .{
+ var req = try client.open(.HEAD, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -370,24 +371,21 @@ pub fn main() !void {
defer calloc.free(body);
try testing.expectEqualStrings("", body);
- try testing.expectEqualStrings("text/plain", req.response.headers.getFirstValue("content-type").?);
- try testing.expectEqualStrings("chunked", req.response.headers.getFirstValue("transfer-encoding").?);
+ try testing.expectEqualStrings("text/plain", req.response.content_type.?);
+ try testing.expect(req.response.transfer_encoding == .chunked);
}
// connection has been kept alive
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // check trailing headers
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/trailer", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -399,26 +397,25 @@ pub fn main() !void {
defer calloc.free(body);
try testing.expectEqualStrings("Hello, World!\n", body);
- try testing.expectEqualStrings("aaaa", req.response.headers.getFirstValue("x-checksum").?);
+ @panic("TODO implement inspecting custom headers in responses");
+ //try testing.expectEqualStrings("aaaa", req.response.headers.getFirstValue("x-checksum").?);
}
// connection has been kept alive
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // send content-length request
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
- try h.append("content-type", "text/plain");
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/echo-content", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.POST, uri, h, .{
+ var req = try client.open(.POST, uri, .{
.server_header_buffer = &server_header_buffer,
+ .extra_headers = &.{
+ .{ .name = "content-type", .value = "text/plain" },
+ },
});
defer req.deinit();
@@ -441,19 +438,15 @@ pub fn main() !void {
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // read content-length response with connection close
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
- try h.append("connection", "close");
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/get", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
+ .keep_alive = false,
});
defer req.deinit();
@@ -464,26 +457,24 @@ pub fn main() !void {
defer calloc.free(body);
try testing.expectEqualStrings("Hello, World!\n", body);
- try testing.expectEqualStrings("text/plain", req.response.headers.getFirstValue("content-type").?);
+ try testing.expectEqualStrings("text/plain", req.response.content_type.?);
}
// connection has been closed
try testing.expect(client.connection_pool.free_len == 0);
{ // send chunked request
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
- try h.append("content-type", "text/plain");
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/echo-content", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.POST, uri, h, .{
+ var req = try client.open(.POST, uri, .{
.server_header_buffer = &server_header_buffer,
+ .extra_headers = &.{
+ .{ .name = "content-type", .value = "text/plain" },
+ },
});
defer req.deinit();
@@ -506,16 +497,13 @@ pub fn main() !void {
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // relative redirect
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/redirect/1", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -533,16 +521,13 @@ pub fn main() !void {
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // redirect from root
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/redirect/2", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -560,16 +545,13 @@ pub fn main() !void {
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // absolute redirect
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/redirect/3", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -587,16 +569,13 @@ pub fn main() !void {
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // too many redirects
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/redirect/4", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -612,16 +591,13 @@ pub fn main() !void {
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // check client without segfault by connection error after redirection
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/redirect/invalid", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.GET, uri, h, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
@@ -639,10 +615,6 @@ pub fn main() !void {
try testing.expect(client.http_proxy != null or client.connection_pool.free_len == 1);
{ // Client.fetch()
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
- try h.append("content-type", "text/plain");
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/echo-content#fetch", .{port});
defer calloc.free(location);
@@ -651,8 +623,10 @@ pub fn main() !void {
var res = try client.fetch(calloc, .{
.location = .{ .url = location },
.method = .POST,
- .headers = h,
.payload = .{ .string = "Hello, World!\n" },
+ .extra_headers = &.{
+ .{ .name = "content-type", .value = "text/plain" },
+ },
});
defer res.deinit();
@@ -660,20 +634,18 @@ pub fn main() !void {
}
{ // expect: 100-continue
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
- try h.append("expect", "100-continue");
- try h.append("content-type", "text/plain");
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/echo-content#expect-100", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.POST, uri, h, .{
+ var req = try client.open(.POST, uri, .{
.server_header_buffer = &server_header_buffer,
+ .extra_headers = &.{
+ .{ .name = "expect", .value = "100-continue" },
+ .{ .name = "content-type", .value = "text/plain" },
+ },
});
defer req.deinit();
@@ -694,20 +666,18 @@ pub fn main() !void {
}
{ // expect: garbage
- var h = http.Headers{ .allocator = calloc };
- defer h.deinit();
-
- try h.append("content-type", "text/plain");
- try h.append("expect", "garbage");
-
const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/echo-content#expect-garbage", .{port});
defer calloc.free(location);
const uri = try std.Uri.parse(location);
log.info("{s}", .{location});
var server_header_buffer: [1024]u8 = undefined;
- var req = try client.open(.POST, uri, h, .{
+ var req = try client.open(.POST, uri, .{
.server_header_buffer = &server_header_buffer,
+ .extra_headers = &.{
+ .{ .name = "content-type", .value = "text/plain" },
+ .{ .name = "expect", .value = "garbage" },
+ },
});
defer req.deinit();
@@ -734,7 +704,7 @@ pub fn main() !void {
for (0..total_connections) |i| {
const headers_buf = try calloc.alloc(u8, 1024);
try header_bufs.append(headers_buf);
- var req = try client.open(.GET, uri, .{ .allocator = calloc }, .{
+ var req = try client.open(.GET, uri, .{
.server_header_buffer = headers_buf,
});
req.response.parser.state = .complete;