Skip to content

Commit

Permalink
add header example
Browse files Browse the repository at this point in the history
  • Loading branch information
jiacai2050 committed Jul 26, 2024
1 parent 5728019 commit b43f97b
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 70 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ zig-linux*
docs
libroot*
.DS_Store
*.o
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
61 changes: 0 additions & 61 deletions examples/advanced.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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,
};
}
73 changes: 73 additions & 0 deletions examples/header.zig
Original file line number Diff line number Diff line change
@@ -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();

comptime if (!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);
}
17 changes: 9 additions & 8 deletions src/Easy.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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.
Expand All @@ -94,9 +94,9 @@ 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()) {
comptime if (!hasParseHeaderSupport()) {
return error.NoCurlHeaderSupport;
}
};

var header: ?*c.struct_curl_header = null;
return Response.getHeaderInner(self.handle, name, &header);
Expand Down Expand Up @@ -127,9 +127,9 @@ pub const Response = struct {
c_header: ?*polyfill_struct_curl_header() = null,

pub fn next(self: *HeaderIterator) !?Header {
if (comptime !has_parse_header_support()) {
comptime if (!hasParseHeaderSupport()) {
return error.NoCurlHeaderSupport;
}
};

const request: c_int = if (self.request) |v| @intCast(v) else -1;

Expand Down Expand Up @@ -177,9 +177,10 @@ pub const Response = struct {
};

pub fn iterateHeaders(self: Response, options: IterateHeadersOptions) errors.HeaderError!HeaderIterator {
if (comptime !has_parse_header_support()) {
comptime if (!hasParseHeaderSupport()) {
return error.NoCurlHeaderSupport;
}
};

return HeaderIterator{
.handle = self.handle,
.name = options.name,
Expand Down
1 change: 1 addition & 0 deletions src/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/util.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit b43f97b

Please sign in to comment.