Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: init multi #7

Merged
merged 10 commits into from
Mar 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .fdignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/libs/curl
/libs/mbedtls
/libs/zlib
6 changes: 1 addition & 5 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ jobs:
version: master
- name: Install deps
run: |
sudo apt update && sudo apt install -y valgrind libcurl4-openssl-dev
make prepare
sudo apt update && sudo apt install -y valgrind
- name: Run tests
run: |
make test
Expand Down Expand Up @@ -60,9 +59,6 @@ jobs:
- uses: goto-bus-stop/setup-zig@v1
with:
version: master
- name: Install deps
run: |
make prepare
- name: Run examples
run: |
make run
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ clean:
run:
zig build run-basic -freference-trace
zig build run-advanced -freference-trace
zig build run-multi -freference-trace

test:
zig build test
Expand Down
4 changes: 2 additions & 2 deletions README.org
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#+TITLE: zig-curl
#+DATE: 2023-09-16T23:16:15+0800
#+LASTMOD: 2024-01-26T22:07:12+0800
#+LASTMOD: 2024-03-02T20:57:50+0800
#+OPTIONS: toc:nil num:nil
#+STARTUP: content

Expand Down Expand Up @@ -66,7 +66,7 @@ exe.linkLibC();
#+end_src

* Roadmap
- [ ] Currently only easy API is supported, support [[https://curl.se/libcurl/c/libcurl-multi.html][multi API]].
- [x] Currently only easy API is supported, support [[https://curl.se/libcurl/c/libcurl-multi.html][multi API]].

* License
[[file:LICENSE][MIT]]
4 changes: 1 addition & 3 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@ pub fn build(b: *Build) void {
const optimize = b.standardOptimizeOption(.{});
const link_vendor = b.option(bool, "link_vendor", "Whether link to vendored libcurl (default: true)") orelse true;

const build_info = b.addOptions();
build_info.addOption(bool, "link_vendor", link_vendor);
const module = b.addModule(MODULE_NAME, .{
.root_source_file = .{ .path = "src/root.zig" },
});
module.addOptions("build_info", build_info);

var libcurl: ?*Step.Compile = null;
if (link_vendor) {
Expand All @@ -26,6 +23,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);

const main_tests = b.addTest(.{
.root_source_file = .{ .path = "src/root.zig" },
Expand Down
68 changes: 40 additions & 28 deletions examples/advanced.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ const Response = struct {
url: []const u8,
};

fn put_with_custom_header(allocator: Allocator, easy: Easy) !void {
fn putWithCustomHeader(allocator: Allocator, easy: Easy) !void {
const body =
\\ {"name": "John", "age": 15}
;

const headers = blk: {
var h = try easy.create_headers();
var h = try easy.createHeaders();
errdefer h.deinit();
try h.add("content-type", "application/json");
try h.add("user-agent", UA);
Expand All @@ -35,21 +35,25 @@ fn put_with_custom_header(allocator: Allocator, easy: Easy) !void {
};
defer headers.deinit();

try easy.set_url("https://httpbin.org/anything/zig-curl");
try easy.set_headers(headers);
try easy.set_method(.PUT);
try easy.set_verbose(true);
try easy.set_post_fields(body);

const resp = try easy.perform();
try easy.setUrl("https://httpbin.org/anything/zig-curl");
try easy.setHeaders(headers);
try easy.setMethod(.PUT);
try easy.setVerbose(true);
try easy.setPostFields(body);
var buf = curl.Buffer.init(allocator);
try easy.setWritedata(&buf);
try easy.setWritefunction(curl.bufferWriteCallback);

var resp = try easy.perform();
resp.body = buf;
defer resp.deinit();

std.debug.print("Status code: {d}\nBody: {s}\n", .{
resp.status_code,
resp.body.items,
resp.body.?.items,
});

const parsed = try std.json.parseFromSlice(Response, allocator, resp.body.items, .{
const parsed = try std.json.parseFromSlice(Response, allocator, resp.body.?.items, .{
.ignore_unknown_fields = true,
});
defer parsed.deinit();
Expand All @@ -71,47 +75,55 @@ fn put_with_custom_header(allocator: Allocator, easy: Easy) !void {
);

// Get response header `date`.
const date_header = try resp.get_header("date");
const date_header = try resp.getHeader("date");
if (date_header) |h| {
std.debug.print("date header: {s}\n", .{h.get()});
} else {
std.debug.print("date header not found\n", .{});
}
}

fn post_mutli_part(easy: Easy) !void {
fn postMutliPart(easy: Easy) !void {
// Reset old options, e.g. headers.
easy.reset();

const multi_part = try easy.create_multi_part();
try multi_part.add_part("foo", .{ .data = "hello foo" });
try multi_part.add_part("bar", .{ .data = "hello bar" });
try multi_part.add_part("build.zig", .{ .file = "build.zig" });
try multi_part.add_part("readme", .{ .file = "README.org" });
const multi_part = try easy.createMultiPart();
try multi_part.addPart("foo", .{ .data = "hello foo" });
try multi_part.addPart("bar", .{ .data = "hello bar" });
try multi_part.addPart("build.zig", .{ .file = "build.zig" });
try multi_part.addPart("readme", .{ .file = "README.org" });
defer multi_part.deinit();

try easy.set_url("https://httpbin.org/anything/mp");
try easy.set_method(.PUT);
try easy.set_multi_part(multi_part);
try easy.set_verbose(true);
try easy.setUrl("https://httpbin.org/anything/mp");
try easy.setMethod(.PUT);
try easy.setMultiPart(multi_part);
try easy.setVerbose(true);
var buf = curl.Buffer.init(easy.allocator);
try easy.setWritedata(&buf);
try easy.setWritefunction(curl.bufferWriteCallback);

const resp = try easy.perform();
var resp = try easy.perform();
resp.body = buf;
defer resp.deinit();

std.debug.print("resp:{s}\n", .{resp.body.items});
std.debug.print("resp:{s}\n", .{resp.body.?.items});
}

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer if (gpa.deinit() != .ok) @panic("leak");
const allocator = gpa.allocator();

const easy = try Easy.init(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();

curl.print_libcurl_version();
curl.printLibcurlVersion();

println("PUT with custom header demo");
try put_with_custom_header(allocator, easy);
try post_mutli_part(easy);
try putWithCustomHeader(allocator, easy);
try postMutliPart(easy);
}
15 changes: 10 additions & 5 deletions examples/basic.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ fn get(allocator: Allocator, easy: Easy) !void {
const resp = try easy.get("https://httpbin.org/anything");
defer resp.deinit();

const body = resp.body.?.items;
std.debug.print("Status code: {d}\nBody: {s}\n", .{
resp.status_code,
resp.body.items,
body,
});

const Response = struct {
Expand All @@ -20,7 +21,7 @@ fn get(allocator: Allocator, easy: Easy) !void {
},
method: []const u8,
};
const parsed = try std.json.parseFromSlice(Response, allocator, resp.body.items, .{
const parsed = try std.json.parseFromSlice(Response, allocator, body, .{
.ignore_unknown_fields = true,
});
defer parsed.deinit();
Expand All @@ -40,7 +41,7 @@ fn post(allocator: Allocator, easy: Easy) !void {

std.debug.print("Status code: {d}\nBody: {s}\n", .{
resp.status_code,
resp.body.items,
resp.body.?.items,
});

const Response = struct {
Expand All @@ -53,7 +54,7 @@ fn post(allocator: Allocator, easy: Easy) !void {
},
method: []const u8,
};
const parsed = try std.json.parseFromSlice(Response, allocator, resp.body.items, .{ .ignore_unknown_fields = true });
const parsed = try std.json.parseFromSlice(Response, allocator, resp.body.?.items, .{ .ignore_unknown_fields = true });
defer parsed.deinit();

try std.testing.expectEqualDeep(parsed.value, Response{
Expand All @@ -68,7 +69,11 @@ pub fn main() !void {
defer if (gpa.deinit() != .ok) @panic("leak");
const allocator = gpa.allocator();

const easy = try Easy.init(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();

println("GET demo");
Expand Down
54 changes: 54 additions & 0 deletions examples/multi.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const std = @import("std");
const println = @import("util.zig").println;
const mem = std.mem;
const Allocator = mem.Allocator;
const curl = @import("curl");
const Easy = curl.Easy;
const Multi = curl.Multi;
const c = curl.libcurl;

pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();

const ca_bundle = try curl.allocCABundle(allocator);
defer ca_bundle.deinit();
const easy = try Easy.init(allocator, .{
.ca_bundle = ca_bundle,
});
try easy.setUrl("http://httpbin.org/headers");
defer easy.deinit();

const easy2 = try Easy.init(allocator, .{
.ca_bundle = ca_bundle,
});
try easy2.setUrl("http://httpbin.org/ip");
defer easy2.deinit();

const multi = try Multi.init();
// defer multi.deinit();

try multi.addHandle(easy);
try multi.addHandle(easy2);

var running = true;

while (running) {
const transfer = try multi.perform();
running = transfer != 0;
std.debug.print("num of transfer {any}\n", .{transfer});

const num_fds = try multi.poll(null, 3000);
std.debug.print("ret = {any}\n", .{num_fds});
}

running = true;
while (running) {
const info = try multi.readInfo();
running = info.msgs_in_queue != 0;
try multi.removeHandle(info.msg.easy_handle.?);
c.curl_easy_cleanup(info.msg.easy_handle.?);
std.debug.print("info {any}\n", .{info});
}
}
Loading
Loading