Skip to content

Commit

Permalink
Add fetch CLI test app
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner committed Oct 12, 2021
1 parent f646250 commit 756bfc9
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 5 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,5 @@ packages/bun-cli/postinstall.js
packages/bun-*/bin/*

packages/bun-cli/bin/*
bun-test-scratch
bun-test-scratch
misctools/fetch
3 changes: 3 additions & 0 deletions misctools/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.tgz
tgz
readlink-getfd
169 changes: 169 additions & 0 deletions misctools/fetch.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
const std = @import("std");
usingnamespace @import("../src/global.zig");
const clap = @import("../src/deps/zig-clap/clap.zig");

const HTTPClient = @import("../src/http_client.zig");
const URL = @import("../src/query_string_map.zig").URL;
const Headers = @import("../src/javascript/jsc/webcore/response.zig").Headers;
const Method = @import("../src/http/method.zig").Method;
const ColonListType = @import("../src/cli/colon_list_type.zig").ColonListType;
const HeadersTuple = ColonListType(string, noop_resolver);
const path_handler = @import("../src/resolver/resolve_path.zig");

fn noop_resolver(in: string) !string {
return in;
}

const VERSION = "0.0.0";

const params = [_]clap.Param(clap.Help){
clap.parseParam("-v, --verbose Show headers & status code") catch unreachable,
clap.parseParam("-H, --header <STR>... Add a header") catch unreachable,
clap.parseParam("-r, --max-redirects <STR> Maximum number of redirects to follow (default: 128)") catch unreachable,
clap.parseParam("-b, --body <STR> HTTP request body as a string") catch unreachable,
clap.parseParam("-f, --file <STR> File path to load as body") catch unreachable,
clap.parseParam("--no-gzip Disable gzip") catch unreachable,
clap.parseParam("--no-deflate Disable deflate") catch unreachable,
clap.parseParam("--no-compression Disable gzip & deflate") catch unreachable,
clap.parseParam("--version Print the version and exit") catch unreachable,
clap.parseParam("<POS>... ") catch unreachable,
};

const MethodNames = std.ComptimeStringMap(Method, .{
.{ "GET", Method.GET },
.{ "get", Method.GET },

.{ "POST", Method.POST },
.{ "post", Method.POST },

.{ "PUT", Method.PUT },
.{ "put", Method.PUT },

.{ "PATCH", Method.PATCH },
.{ "patch", Method.PATCH },

.{ "OPTIONS", Method.OPTIONS },
.{ "options", Method.OPTIONS },

.{ "HEAD", Method.HEAD },
.{ "head", Method.HEAD },
});

var file_path_buf: [std.fs.MAX_PATH_BYTES + 1]u8 = undefined;
var cwd_buf: [std.fs.MAX_PATH_BYTES + 1]u8 = undefined;

pub const Arguments = struct {
url: URL,
method: Method,
verbose: bool = false,
headers: Headers.Entries,
headers_buf: string,
body: string = "",

pub fn parse(allocator: *std.mem.Allocator) !Arguments {
var diag = clap.Diagnostic{};

var args = clap.parse(clap.Help, &params, .{
.diagnostic = &diag,
.allocator = allocator,
}) catch |err| {
// Report useful error and exit
diag.report(Output.errorWriter(), err) catch {};
return err;
};

var positionals = args.positionals();
var raw_args: std.ArrayListUnmanaged(string) = undefined;

if (positionals.len > 0) {
raw_args = .{ .capacity = positionals.len, .items = @intToPtr([*][]const u8, @ptrToInt(positionals.ptr))[0..positionals.len] };
} else {
raw_args = .{};
}

if (args.flag("--version")) {
try Output.writer().writeAll(VERSION);
std.os.exit(0);
}

var method = Method.GET;
var url: URL = .{};
var body_string: string = args.option("--body") orelse "";

if (args.option("--file")) |file_path| {
if (file_path.len > 0) {
var cwd = try std.process.getCwd(&cwd_buf);
var parts = [_]string{std.mem.span(file_path)};
var absolute_path = path_handler.joinAbsStringBuf(cwd, &file_path_buf, &parts, .auto);
file_path_buf[absolute_path.len] = 0;
file_path_buf[absolute_path.len + 1] = 0;
var absolute_path_len = absolute_path.len;
var absolute_path_ = file_path_buf[0..absolute_path_len :0];

var body_file = std.fs.openFileAbsoluteZ(absolute_path_, .{ .read = true }) catch |err| {
Output.printErrorln("<r><red>{s}<r> opening file {s}", .{ @errorName(err), absolute_path });
Output.flush();
std.os.exit(1);
};

var file_contents = body_file.readToEndAlloc(allocator, try body_file.getEndPos()) catch |err| {
Output.printErrorln("<r><red>{s}<r> reading file {s}", .{ @errorName(err), absolute_path });
Output.flush();
std.os.exit(1);
};
body_string = file_contents;
}
}

{
var raw_arg_i: usize = 0;
while (raw_arg_i < raw_args.items.len) : (raw_arg_i += 1) {
const arg = raw_args.items[raw_arg_i];
if (MethodNames.get(std.mem.span(arg))) |method_| {
method = method_;
_ = raw_args.swapRemove(raw_arg_i);
}
}

if (raw_args.items.len == 0) {
Output.prettyErrorln("<r><red>error<r><d>:<r> <b>Missing URL<r>\n\nExample:\n<r><b>fetch GET https://example.com<r>\n\n<b>fetch example.com/foo<r>\n\n", .{});
Output.flush();
std.os.exit(1);
}

const url_position = raw_args.items.len - 1;
url = URL.parse(raw_args.swapRemove(url_position));
if (!url.isAbsolute()) {
Output.prettyErrorln("<r><red>error<r><d>:<r> <b>Invalid URL<r>\n\nExample:\n<r><b>fetch GET https://example.com<r>\n\n<b>fetch example.com/foo<r>\n\n", .{});
Output.flush();
std.os.exit(1);
}
}

return Arguments{
.url = url,
.method = method,
.verbose = args.flag("--verbose"),
.headers = .{},
.headers_buf = "",
.body = body_string,
};
}
};

pub fn main() anyerror!void {
var stdout_ = std.io.getStdOut();
var stderr_ = std.io.getStdErr();
var output_source = Output.Source.init(stdout_, stderr_);
Output.Source.set(&output_source);
defer Output.flush();

var args = try Arguments.parse(default_allocator);
var client = HTTPClient.init(default_allocator, args.method, args.url, args.headers, args.headers_buf);
client.verbose = args.verbose;
var body_out_str = try MutableString.init(default_allocator, 1024);
var response = try client.send(args.body, &body_out_str);

Output.disableBuffering();
try Output.writer().writeAll(body_out_str.list.items);
}
8 changes: 4 additions & 4 deletions misctools/tgz.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const RecognizedExtensions = std.ComptimeStringMap(void, .{
.{ ".gz", void{} },
});

var buf: [512 * 1024 * 1024]u8 = undefined;
var buf: [32 * 1024 * 1024]u8 = undefined;

// zig build-exe -Drelease-fast --main-pkg-path ../ ./tgz.zig ../src/deps/zlib/libz.a ../src/deps/libarchive.a -lc -liconv
// zig build-exe -Drelease-fast --main-pkg-path ../ ./tgz.zig ../src/deps/zlib/libz.a ../src/deps/libarchive.a -lc -liconv
Expand Down Expand Up @@ -62,14 +62,14 @@ pub fn main() anyerror!void {
}

// if (std.mem.eql(u8, std.fs.path.extension(tarball_path), ".gz") or std.mem.eql(u8, std.fs.path.extension(tarball_path), ".tgz")) {
// tarball_buf_list = std.ArrayListUnmanaged(u8){ .capacity = gzip_buf.len, .items = std.mem.span(&gzip_buf) };
// tarball_buf_list = std.ArrayListUnmanaged(u8){ .capacity = file_buf.len, .items = file_buf };
// var gunzip = try Zlib.ZlibReaderArrayList.init(file_buf, &tarball_buf_list, std.heap.c_allocator);
// try gunzip.readAll();
// gunzip.deinit();
// Output.prettyErrorln("Decompressed {d} -> {d}\n", .{ file_buf.len, tarball_buf_list.items.len });
// } else {
tarball_buf_list = std.ArrayListUnmanaged(u8){ .capacity = file_buf.len, .items = file_buf };
// tarball_buf_list = std.ArrayListUnmanaged(u8){ .capacity = file_buf.len, .items = file_buf };
// }

try Archive.extractToDisk(tarball_buf_list.items, folder, 1, false);
try Archive.extractToDisk(file_buf, folder, 1, false);
}

0 comments on commit 756bfc9

Please sign in to comment.