diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-04-18 19:56:24 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-18 19:56:24 -0700 |
| commit | 0eebc258809beac9779af48216b01c5c20cbbfea (patch) | |
| tree | a912eef3d99d3e2371484fd60f6b32a7e11d509b /lib/std/Uri.zig | |
| parent | 77fdd76c16196441dce0f38ccea2eae01436c4be (diff) | |
| parent | a23c8662b41cf6954d8294ea316fb28a88481a7e (diff) | |
| download | zig-0eebc258809beac9779af48216b01c5c20cbbfea.tar.gz zig-0eebc258809beac9779af48216b01c5c20cbbfea.zip | |
Merge pull request #15299 from truemedian/std-http
std.http: curated error sets and custom Headers
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`. |
