aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-10-12 16:26:57 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-10-12 16:26:57 -0700
commit756bfc9077e37d0feb053879103473f9ed80274e (patch)
treecaff95da03b080fd35f6eb04fb427bc8aab949b7
parentf646250a91355abebd559fa6735efbe9dbc0314f (diff)
downloadbun-756bfc9077e37d0feb053879103473f9ed80274e.tar.gz
bun-756bfc9077e37d0feb053879103473f9ed80274e.tar.zst
bun-756bfc9077e37d0feb053879103473f9ed80274e.zip
Add fetch CLI test app
-rw-r--r--.gitignore3
-rw-r--r--misctools/.gitignore3
-rw-r--r--misctools/fetch.zig169
-rw-r--r--misctools/tgz.zig8
4 files changed, 178 insertions, 5 deletions
diff --git a/.gitignore b/.gitignore
index d4eca5e8c..bc2458e82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,4 +67,5 @@ packages/bun-cli/postinstall.js
packages/bun-*/bin/*
packages/bun-cli/bin/*
-bun-test-scratch \ No newline at end of file
+bun-test-scratch
+misctools/fetch \ No newline at end of file
diff --git a/misctools/.gitignore b/misctools/.gitignore
new file mode 100644
index 000000000..41cdc1338
--- /dev/null
+++ b/misctools/.gitignore
@@ -0,0 +1,3 @@
+*.tgz
+tgz
+readlink-getfd
diff --git a/misctools/fetch.zig b/misctools/fetch.zig
new file mode 100644
index 000000000..ad704151a
--- /dev/null
+++ b/misctools/fetch.zig
@@ -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);
+}
diff --git a/misctools/tgz.zig b/misctools/tgz.zig
index 87497594a..d30606244 100644
--- a/misctools/tgz.zig
+++ b/misctools/tgz.zig
@@ -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
@@ -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);
}