From bc13834df69d0341d8a06e9711e2a19dfc215fb0 Mon Sep 17 00:00:00 2001 From: jiacai2050 Date: Fri, 26 Jul 2024 22:35:17 +0800 Subject: [PATCH] add header example --- .github/workflows/CI.yml | 4 +-- .github/workflows/docs.yml | 7 ++-- .gitignore | 1 + Makefile | 1 + build.zig | 1 + examples/advanced.zig | 61 ------------------------------- examples/header.zig | 73 ++++++++++++++++++++++++++++++++++++++ src/Easy.zig | 11 +++--- src/root.zig | 1 + src/util.zig | 2 +- 10 files changed, 88 insertions(+), 74 deletions(-) create mode 100644 examples/header.zig diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 672feab..8c43377 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -64,10 +64,10 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - zig-version: [master, 0.12.0] + zig-version: [master, 0.13.0] steps: - uses: actions/checkout@v4 - - uses: goto-bus-stop/setup-zig@v2 + - uses: mlugg/setup-zig@v1 with: version: ${{ matrix.zig-version }} - uses: actions/setup-go@v5 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 27a0d7c..8e141b1 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,12 +25,9 @@ jobs: uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v3 - - uses: goto-bus-stop/setup-zig@v2 + - uses: mlugg/setup-zig@v1 with: - version: master - - uses: goto-bus-stop/setup-zig@v2 - with: - version: master + version: ${{ matrix.zig-version }} - name: Generate docs run: | make docs diff --git a/.gitignore b/.gitignore index 3f8a29b..5488c06 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ zig-linux* docs libroot* .DS_Store +*.o \ No newline at end of file diff --git a/Makefile b/Makefile index 255beae..c854027 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ run: zig build run-basic -freference-trace $(ARGS) zig build run-advanced -freference-trace $(ARGS) zig build run-multi -freference-trace $(ARGS) + zig build run-header -freference-trace $(ARGS) test: zig build test $(ARGS) diff --git a/build.zig b/build.zig index 9e04dcb..47f577b 100644 --- a/build.zig +++ b/build.zig @@ -30,6 +30,7 @@ pub fn build(b: *Build) void { try addExample(b, "basic", module, libcurl, target, optimize); try addExample(b, "advanced", module, libcurl, target, optimize); try addExample(b, "multi", module, libcurl, target, optimize); + try addExample(b, "header", module, libcurl, target, optimize); const main_tests = b.addTest(.{ .root_source_file = b.path("src/root.zig"), diff --git a/examples/advanced.zig b/examples/advanced.zig index db09fab..aebf266 100644 --- a/examples/advanced.zig +++ b/examples/advanced.zig @@ -112,53 +112,6 @@ fn postMutliPart(easy: Easy) !void { std.debug.print("resp:{s}\n", .{resp.body.?.items}); } -fn iterateHeaders(easy: Easy) !void { - // Reset old options, e.g. headers. - easy.reset(); - - const resp = try easy.get("https://httpbin.org/response-headers?X-Foo=1&X-Foo=2&X-Foo=3"); - defer resp.deinit(); - - std.debug.print("Iterating all headers...\n", .{}); - { - var iter = try resp.iterateHeaders(.{}); - while (try iter.next()) |header| { - std.debug.print(" {s}: {s}\n", .{ header.name, header.get() }); - } - } - - // Iterating X-Foo only - { - var iter = try resp.iterateHeaders(.{ .name = "X-Foo" }); - const expected_values = .{ "1", "2", "3" }; - inline for (expected_values) |expected| { - const header = try iter.next() orelse unreachable; - try std.testing.expectEqualStrings(header.get(), expected); - } - try std.testing.expect((try iter.next()) == null); - } -} - -fn iterateRedirectedHeaders(easy: Easy) !void { - // Reset old options, e.g. headers. - easy.reset(); - - try easy.setFollowLocation(true); - const resp = try easy.get("https://httpbin.org/redirect/1"); - defer resp.deinit(); - - const redirects = try resp.getRedirectCount(); - try std.testing.expectEqual(redirects, 1); - - for (0..redirects + 1) |i| { - std.debug.print("Request #{} headers:\n", .{i}); - var iter = try resp.iterateHeaders(.{ .request = i }); - while (try iter.next()) |header| { - std.debug.print(" {s}: {s}\n", .{ header.name, header.get() }); - } - } -} - pub fn main() !void { const allocator = std.heap.page_allocator; @@ -169,21 +122,7 @@ pub fn main() !void { }); defer easy.deinit(); - curl.printLibcurlVersion(); - println("PUT with custom header demo"); try putWithCustomHeader(allocator, easy); try postMutliPart(easy); - - println("Iterate headers demo"); - iterateHeaders(easy) catch |err| switch (err) { - error.NoCurlHeaderSupport => std.debug.print("No header support, skipping...\n", .{}), - else => return err, - }; - - println("Redirected headers demo"); - iterateRedirectedHeaders(easy) catch |err| switch (err) { - error.NoCurlHeaderSupport => std.debug.print("No header support, skipping...\n", .{}), - else => return err, - }; } diff --git a/examples/header.zig b/examples/header.zig new file mode 100644 index 0000000..90c4ae2 --- /dev/null +++ b/examples/header.zig @@ -0,0 +1,73 @@ +const std = @import("std"); +const curl = @import("curl"); +const Easy = curl.Easy; +const println = @import("util.zig").println; + +fn iterateHeaders(easy: Easy) !void { + // Reset old options, e.g. headers. + easy.reset(); + + const resp = try easy.get("https://httpbin.org/response-headers?X-Foo=1&X-Foo=2&X-Foo=3"); + defer resp.deinit(); + + std.debug.print("Iterating all headers...\n", .{}); + { + var iter = try resp.iterateHeaders(.{}); + while (try iter.next()) |header| { + std.debug.print(" {s}: {s}\n", .{ header.name, header.get() }); + } + } + + // Iterating X-Foo only + { + var iter = try resp.iterateHeaders(.{ .name = "X-Foo" }); + const expected_values = .{ "1", "2", "3" }; + inline for (expected_values) |expected| { + const header = try iter.next() orelse unreachable; + try std.testing.expectEqualStrings(header.get(), expected); + } + try std.testing.expect((try iter.next()) == null); + } +} + +fn iterateRedirectedHeaders(easy: Easy) !void { + // Reset old options, e.g. headers. + easy.reset(); + + try easy.setFollowLocation(true); + const resp = try easy.get("https://httpbin.org/redirect/1"); + defer resp.deinit(); + + const redirects = try resp.getRedirectCount(); + try std.testing.expectEqual(redirects, 1); + + for (0..redirects + 1) |i| { + std.debug.print("Request #{} headers:\n", .{i}); + var iter = try resp.iterateHeaders(.{ .request = i }); + while (try iter.next()) |header| { + std.debug.print(" {s}: {s}\n", .{ header.name, header.get() }); + } + } +} + +pub fn main() !void { + const allocator = std.heap.page_allocator; + + const ca_bundle = try curl.allocCABundle(allocator); + defer ca_bundle.deinit(); + const easy = try Easy.init(allocator, .{ + .ca_bundle = ca_bundle, + }); + defer easy.deinit(); + + if (comptime !curl.hasParseHeaderSupport()) { + std.debug.print("Libcurl version too old, don't support parse headers.\n", .{}); + return; + } + + println("Iterate headers demo"); + try iterateHeaders(easy); + + println("Redirected headers demo"); + try iterateRedirectedHeaders(easy); +} diff --git a/src/Easy.zig b/src/Easy.zig index 285b114..af96771 100644 --- a/src/Easy.zig +++ b/src/Easy.zig @@ -9,7 +9,7 @@ const Allocator = mem.Allocator; const checkCode = errors.checkCode; const Buffer = util.Buffer; -const has_parse_header_support = @import("util.zig").has_parse_header_support; +const hasParseHeaderSupport = @import("util.zig").hasParseHeaderSupport; const Self = @This(); @@ -71,7 +71,7 @@ pub const Response = struct { } fn polyfill_struct_curl_header() type { - if (has_parse_header_support()) { + if (hasParseHeaderSupport()) { return c.struct_curl_header; } else { // return a dummy struct to make it compile on old version. @@ -94,7 +94,7 @@ pub const Response = struct { /// Gets the header associated with the given name. pub fn getHeader(self: Response, name: [:0]const u8) errors.HeaderError!?Header { - if (comptime !has_parse_header_support()) { + if (comptime !hasParseHeaderSupport()) { return error.NoCurlHeaderSupport; } @@ -127,7 +127,7 @@ pub const Response = struct { c_header: ?*polyfill_struct_curl_header() = null, pub fn next(self: *HeaderIterator) !?Header { - if (comptime !has_parse_header_support()) { + if (comptime !hasParseHeaderSupport()) { return error.NoCurlHeaderSupport; } @@ -177,9 +177,10 @@ pub const Response = struct { }; pub fn iterateHeaders(self: Response, options: IterateHeadersOptions) errors.HeaderError!HeaderIterator { - if (comptime !has_parse_header_support()) { + if (comptime !hasParseHeaderSupport()) { return error.NoCurlHeaderSupport; } + return HeaderIterator{ .handle = self.handle, .name = options.name, diff --git a/src/root.zig b/src/root.zig index 566f39e..d8c6c14 100644 --- a/src/root.zig +++ b/src/root.zig @@ -6,6 +6,7 @@ pub const Easy = @import("Easy.zig"); pub const Multi = @import("Multi.zig"); pub const bufferWriteCallback = Easy.bufferWriteCallback; pub const printLibcurlVersion = util.printLibcurlVersion; +pub const hasParseHeaderSupport = util.hasParseHeaderSupport; pub const urlEncode = util.urlEncode; pub const allocCABundle = util.allocCABundle; pub const Buffer = util.Buffer; diff --git a/src/util.zig b/src/util.zig index 523ffaf..c617c37 100644 --- a/src/util.zig +++ b/src/util.zig @@ -53,7 +53,7 @@ pub fn printLibcurlVersion() void { } } -pub fn has_parse_header_support() bool { +pub fn hasParseHeaderSupport() bool { // `curl_header` is officially supported since 7.84.0. // https://everything.curl.dev/helpers/headerapi/index.html return c.CURL_AT_LEAST_VERSION(7, 84, 0);