Skip to content

roobie/zfetch

Repository files navigation

zfetch

A minimal, secure HTTPS client for Zig.

Single static binary that fetches URLs over HTTPS with strict security defaults. Replaces curl in restricted environments where you need a small, auditable tool with no runtime dependencies.

Also usable as a Zig library for embedding HTTP(S) fetches in your own programs.

What is zfetch

  • Single static binary, no runtime dependencies
  • HTTP(S) only -- small attack surface by design
  • Strict security defaults: TLS verification on, redirect limits enforced, body size capped
  • Streaming I/O -- responses written directly to a sink, never buffered in memory
  • Deterministic exit codes for scripting
  • Embeddable Zig library with allocator-explicit API

Installation

Prerequisites

  • Zig 0.15.2+
  • CMake
  • Ninja (for building vendored BoringSSL)

Build from source

git clone https://github.com/nichochar/zfetch.git
cd zfetch
zig build -Doptimize=ReleaseSmall

The binary is at zig-out/bin/zfetch.

CLI Usage

# Simple GET request
zfetch https://example.com

# POST with JSON body
zfetch -d '{"key":"val"}' -H 'Content-Type: application/json' https://api.example.com

# PUT with body from stdin
zfetch -X PUT -d @- https://api.example.com/resource < data.json

# Write response to file
zfetch -o output.html https://example.com

# Fail on HTTP errors (exit 22 on 4xx/5xx)
zfetch --fail https://api.example.com/resource

Options

Flag Description
-X <METHOD> HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD)
-H <Header: Value> Add custom header (repeatable)
-d <data> Send request body (implies POST unless -X given)
-d @- Read request body from stdin
-o <file> Write response body to file instead of stdout
-s Silent mode (suppress status output on stderr)
-v, --verbose Verbose output (TLS diagnostics)
-k, --insecure Disable TLS certificate verification
--fail Exit 22 on HTTP 4xx/5xx errors
--connect-timeout <s> Connection timeout in seconds
--max-time <s> Maximum time for entire request in seconds
--help Show help and exit
--version Show version and exit

Library Usage

Add zfetch as a dependency in your build.zig.zon:

.dependencies = .{
    .zfetch = .{
        .url = "https://github.com/nichochar/zfetch/archive/<commit>.tar.gz",
        .hash = "...",
    },
},

Wire it into your build.zig:

const zfetch_dep = b.dependency("zfetch", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("zfetch", zfetch_dep.module("zfetch"));

Then use it in your code:

const std = @import("std");
const zfetch = @import("zfetch");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var client = zfetch.Client.init(allocator, .{});
    defer client.deinit();

    var response = client.fetch("https://example.com", std.fs.File.stdout()) catch |err| {
        std.debug.print("error: {s}\n", .{zfetch.errorMessage(err)});
        return;
    };
    defer response.deinit(allocator);
}

BoringSSL is vendored and links transparently through the zfetch module -- consumers do not need to configure TLS separately.

Build Profiles

Profile Use Case Binary Size
ReleaseSmall Containers, minimal environments, CI images 2.5 MB
ReleaseSafe Servers, development, debugging with safety checks 26.4 MB

Build with a specific profile:

zig build -Doptimize=ReleaseSmall    # Smallest binary
zig build -Doptimize=ReleaseSafe     # Safety checks enabled

License

Apache-2.0

About

Single static binary that fetches URLs over HTTPS with strict security defaults. Replaces curl in restricted environments where you need a small, auditable tool with no runtime dependencies.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors