diff options
| author | Nameless <truemedian@gmail.com> | 2023-04-14 12:38:13 -0500 |
|---|---|---|
| committer | Nameless <truemedian@gmail.com> | 2023-04-17 19:14:48 -0500 |
| commit | 96533b1289f210b415e12d4cf5bbac466279c2e5 (patch) | |
| tree | 1f566443a986b4a8b0d05edfb585023e9616b70b /lib/std/Uri.zig | |
| parent | 2c492064fbc882fa31256209d201ade1bb20cb92 (diff) | |
| download | zig-96533b1289f210b415e12d4cf5bbac466279c2e5.tar.gz zig-96533b1289f210b415e12d4cf5bbac466279c2e5.zip | |
std.http: very basic http client proxy
Diffstat (limited to 'lib/std/Uri.zig')
| -rw-r--r-- | lib/std/Uri.zig | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig index eb6311a19b..b010ce8662 100644 --- a/lib/std/Uri.zig +++ b/lib/std/Uri.zig @@ -27,6 +27,18 @@ pub fn escapeQuery(allocator: std.mem.Allocator, input: []const u8) error{OutOfM return escapeStringWithFn(allocator, input, isQueryChar); } +pub fn writeEscapedString(writer: anytype, input: []const u8) !void { + return writeEscapedStringWithFn(writer, input, isUnreserved); +} + +pub fn writeEscapedPath(writer: anytype, input: []const u8) !void { + return writeEscapedStringWithFn(writer, input, isPathChar); +} + +pub fn writeEscapedQuery(writer: anytype, input: []const u8) !void { + return writeEscapedStringWithFn(writer, input, isQueryChar); +} + pub fn escapeStringWithFn(allocator: std.mem.Allocator, input: []const u8, comptime keepUnescaped: fn (c: u8) bool) std.mem.Allocator.Error![]const u8 { var outsize: usize = 0; for (input) |c| { @@ -52,6 +64,16 @@ pub fn escapeStringWithFn(allocator: std.mem.Allocator, input: []const u8, compt return output; } +pub fn writeEscapedStringWithFn(writer: anytype, input: []const u8, comptime keepUnescaped: fn (c: u8) bool) @TypeOf(writer).Error!void { + for (input) |c| { + if (keepUnescaped(c)) { + try writer.writeByte(c); + } else { + try writer.print("%{X:0>2}", .{c}); + } + } +} + /// Parses a URI string and unescapes all %XX where XX is a valid hex number. Otherwise, verbatim copies /// them to the output. pub fn unescapeString(allocator: std.mem.Allocator, input: []const u8) error{OutOfMemory}![]const u8 { @@ -184,6 +206,60 @@ pub fn parseWithoutScheme(text: []const u8) ParseError!Uri { return uri; } +pub fn format( + uri: Uri, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) @TypeOf(writer).Error!void { + _ = options; + + const needs_absolute = comptime std.mem.indexOf(u8, fmt, "+") != null; + const needs_path = comptime std.mem.indexOf(u8, fmt, "/") != null or fmt.len == 0; + + if (needs_absolute) { + try writer.writeAll(uri.scheme); + try writer.writeAll(":"); + if (uri.host) |host| { + try writer.writeAll("//"); + + if (uri.user) |user| { + try writer.writeAll(user); + if (uri.password) |password| { + try writer.writeAll(":"); + try writer.writeAll(password); + } + try writer.writeAll("@"); + } + + try writer.writeAll(host); + + if (uri.port) |port| { + try writer.writeAll(":"); + try std.fmt.formatInt(port, 10, .lower, .{}, writer); + } + } + } + + if (needs_path) { + if (uri.path.len == 0) { + try writer.writeAll("/"); + } else { + try Uri.writeEscapedPath(writer, uri.path); + } + + if (uri.query) |q| { + try writer.writeAll("?"); + try Uri.writeEscapedQuery(writer, q); + } + + if (uri.fragment) |f| { + try writer.writeAll("#"); + try Uri.writeEscapedQuery(writer, f); + } + } +} + /// Parses the URI or returns an error. /// The return value will contain unescaped strings pointing into the /// original `text`. Each component that is provided, will be non-`null`. |
