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

Add support for builtin libcurl and some other fixes #4

Merged
merged 6 commits into from Dec 23, 2023

Conversation

Cloudef
Copy link
Contributor

@Cloudef Cloudef commented Dec 21, 2023

  • Fix crash on easy.do() which does not pass the proper type to curl
  • Fix compile on latest zig
  • Use standard optimize options in built.zig
  • Fix typo in errors.zig
  • Allow the use of certificates in std.crypto.Certificate.Bundle instead of default one
  • Include builtin libcurl compiled against mbedTls, the use of std.crypto.Certificate.Bundle is required, or CURLOPT_CAINFO should be used to point to cacert bundle.

@Cloudef
Copy link
Contributor Author

Cloudef commented Dec 21, 2023

Note that the zigcurl dependency points to my fork and should be updated once star-tek-mb/zigcurl#2 is merged.

build.zig.zon Outdated Show resolved Hide resolved
build.zig Show resolved Hide resolved
src/main.zig Outdated Show resolved Hide resolved
src/main.zig Outdated Show resolved Hide resolved
@Cloudef
Copy link
Contributor Author

Cloudef commented Dec 22, 2023

Side-note, it would be nice to have std.http.Client's fetch compatible api. I use this in my own project until std.crypto has TLSv1.2 support:

// Temporary crap until std.http.Client has TLSv1.2 support
// https://github.com/ziglang/zig/issues/14172#issuecomment-1384567705
const curl = @import("curl");
const Client = struct {
    client: curl.Easy,

    pub fn init(allocator: std.mem.Allocator) !@This() {
        return .{ .client = try curl.Easy.init(allocator) };
    }

    pub fn deinit(self: *@This()) void {
        self.client.deinit();
    }

    pub fn fetch(self: *@This(), allocator: std.mem.Allocator, options: std.http.Client.FetchOptions) !std.http.Client.FetchResult {
        var reader = switch (options.payload) {
            .file => |file| file.reader().any(),
            .string => |str| blk: {
                var stream = std.io.fixedBufferStream(str);
                break :blk stream.reader().any();
            },
            .none => blk: {
                const empty: []const u8 = &.{};
                var stream = std.io.fixedBufferStream(empty);
                break :blk stream.reader().any();
            },
        };

        const target = switch (options.location) {
            .url => |url| url,
            .uri => @panic("unsupported"),
        };

        var headers = curl.Easy.RequestHeader.init(allocator);
        for (options.headers.list.items[0..]) |header| try headers.add(header.name, header.value);
        var req = curl.Easy.Request(*@TypeOf(reader)).init(target, &reader, .{
            .method = std.meta.stringToEnum(curl.Easy.Method, @tagName(options.method)).?,
            .header = headers,
        });
        defer req.deinit();

        const res = try self.client.do(req);
        return .{
            .allocator = allocator,
            .options = options,
            .status = @enumFromInt(res.status_code),
            .body = res.body.items,
            .headers = .{ .allocator = allocator },
        };
    }
};

@jiacai2050
Copy link
Owner

it would be nice to have std.http.Client's fetch compatible api.

This is a nice point, we can do this in another PR.

The dependency points to a fork.
Should be updated to upstream once star-tek-mb/zigcurl#2
is merged!
@Cloudef
Copy link
Contributor Author

Cloudef commented Dec 23, 2023

The std.crypto.Certificate.Bundle usage is now under EasyOptions setting. I think this is the best way instead of trying to auto-detect what the library user might want. It makes sense to default to true here though as the included curl won't be very useful without disabling TLS verification otherwise.

zig-curl/src/easy.zig

Lines 233 to 263 in 96ba813

pub fn init(allocator: Allocator, options: EasyOptions) !Self {
const ca_bundle = blk: {
if (options.use_std_crypto_ca_bundle) {
var bundle = std.crypto.Certificate.Bundle{};
defer bundle.deinit(allocator);
try bundle.rescan(allocator);
var blob = std.ArrayListUnmanaged(u8){};
const base64 = std.base64.standard.Encoder;
var iter = bundle.map.iterator();
while (iter.next()) |entry| {
const der = try std.crypto.Certificate.der.Element.parse(bundle.bytes.items, entry.value_ptr.*);
const cert = bundle.bytes.items[entry.value_ptr.*..der.slice.end];
const begin_marker = "-----BEGIN CERTIFICATE-----";
const end_marker = "\n-----END CERTIFICATE-----\n";
const encoded_sz = base64.calcSize(cert.len);
try blob.ensureTotalCapacity(allocator, blob.items.len + encoded_sz);
var encoded = try allocator.alloc(u8, encoded_sz + begin_marker.len + end_marker.len);
defer allocator.free(encoded);
_ = base64.encode(encoded[0..], cert);
try blob.appendSlice(allocator, begin_marker);
for (encoded, 0..) |char, n| {
if (n % 64 == 0) try blob.append(allocator, '\n');
try blob.append(allocator, char);
}
try blob.appendSlice(allocator, end_marker);
}
break :blk try blob.toOwnedSlice(allocator);
} else {
break :blk null;
}
};

Copy link
Owner

@jiacai2050 jiacai2050 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jiacai2050
Copy link
Owner

I will do some polish based on your branch, please don't update any more.

@jiacai2050 jiacai2050 merged commit 659c139 into jiacai2050:main Dec 23, 2023
2 checks passed
@jiacai2050 jiacai2050 mentioned this pull request Dec 23, 2023
@Cloudef
Copy link
Contributor Author

Cloudef commented Jan 1, 2024

@jiacai2050 since there's no activity on the libcurl PR it might be better merge into this project. I also fixed ARM compilation Cloudef/zigcurl@e1266d8

@jiacai2050
Copy link
Owner

I do not like to copy all c files directly into this project, it's hard to update and we don't know the difference between ours and upstream.

Could we use git submodule to add those C packages?

@Cloudef
Copy link
Contributor Author

Cloudef commented Jan 5, 2024

I think it's possible. In the meantime star-tek-mb/zigcurl#2 the PR with fixes was merged in.

@jiacai2050
Copy link
Owner

@Cloudef Hi, just let you know, I already vendor those C libraries.

I choose not to use submodule since those libraries have really long commit history, and use a update.sh script to deal with the update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants