aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Uri.zig
diff options
context:
space:
mode:
authorNameless <truemedian@gmail.com>2023-10-02 19:57:43 -0500
committerNameless <truemedian@gmail.com>2023-10-21 20:52:58 -0500
commit1afeada2d95e50efe651bd6227719ca4003dad96 (patch)
tree0799938787b302420653064771942bb589546b36 /lib/std/Uri.zig
parent7d50634e0ad4355e339bc243a2e2842693e133f9 (diff)
downloadzig-1afeada2d95e50efe651bd6227719ca4003dad96.tar.gz
zig-1afeada2d95e50efe651bd6227719ca4003dad96.zip
std.http.Client: enhance proxy support
adds connectTunnel to form a HTTP CONNECT tunnel to the desired host. Primarily implemented for proxies, but like connectUnix may be called by any user. adds loadDefaultProxies to load proxy information from common environment variables (http_proxy, HTTP_PROXY, https_proxy, HTTPS_PROXY, all_proxy, ALL_PROXY). - no_proxy and NO_PROXY are currently unsupported. splits proxy into http_proxy and https_proxy, adds headers field for arbitrary headers to each proxy.
Diffstat (limited to 'lib/std/Uri.zig')
-rw-r--r--lib/std/Uri.zig112
1 files changed, 79 insertions, 33 deletions
diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig
index 6952839e71..0a98c5b641 100644
--- a/lib/std/Uri.zig
+++ b/lib/std/Uri.zig
@@ -208,24 +208,45 @@ pub fn parseWithoutScheme(text: []const u8) ParseError!Uri {
return uri;
}
-pub fn format(
+pub const WriteToStreamOptions = struct {
+ /// When true, include the scheme part of the URI.
+ scheme: bool = false,
+
+ /// When true, include the user and password part of the URI. Ignored if `authority` is false.
+ authentication: bool = false,
+
+ /// When true, include the authority part of the URI.
+ authority: bool = false,
+
+ /// When true, include the path part of the URI.
+ path: bool = false,
+
+ /// When true, include the query part of the URI. Ignored when `path` is false.
+ query: bool = false,
+
+ /// When true, include the fragment part of the URI. Ignored when `path` is false.
+ fragment: bool = false,
+
+ /// When true, do not escape any part of the URI.
+ raw: bool = false,
+};
+
+pub fn writeToStream(
uri: Uri,
- comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
+ options: WriteToStreamOptions,
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;
- const raw_uri = comptime std.mem.indexOf(u8, fmt, "r") != null;
- const needs_fragment = comptime std.mem.indexOf(u8, fmt, "#") != null;
-
- if (needs_absolute) {
+ if (options.scheme) {
try writer.writeAll(uri.scheme);
try writer.writeAll(":");
- if (uri.host) |host| {
+
+ if (options.authority and uri.host != null) {
try writer.writeAll("//");
+ }
+ }
+
+ if (options.authority) {
+ if (options.authentication and uri.host != null) {
if (uri.user) |user| {
try writer.writeAll(user);
if (uri.password) |password| {
@@ -234,7 +255,9 @@ pub fn format(
}
try writer.writeAll("@");
}
+ }
+ if (uri.host) |host| {
try writer.writeAll(host);
if (uri.port) |port| {
@@ -244,39 +267,62 @@ pub fn format(
}
}
- if (needs_path) {
+ if (options.path) {
if (uri.path.len == 0) {
try writer.writeAll("/");
+ } else if (options.raw) {
+ try writer.writeAll(uri.path);
} else {
- if (raw_uri) {
- try writer.writeAll(uri.path);
- } else {
- try Uri.writeEscapedPath(writer, uri.path);
- }
+ try writeEscapedPath(writer, uri.path);
}
- if (uri.query) |q| {
+ if (options.query) if (uri.query) |q| {
try writer.writeAll("?");
- if (raw_uri) {
+ if (options.raw) {
try writer.writeAll(q);
} else {
- try Uri.writeEscapedQuery(writer, q);
+ try writeEscapedQuery(writer, q);
}
- }
+ };
- if (needs_fragment) {
- if (uri.fragment) |f| {
- try writer.writeAll("#");
- if (raw_uri) {
- try writer.writeAll(f);
- } else {
- try Uri.writeEscapedQuery(writer, f);
- }
+ if (options.fragment) if (uri.fragment) |f| {
+ try writer.writeAll("#");
+ if (options.raw) {
+ try writer.writeAll(f);
+ } else {
+ try writeEscapedQuery(writer, f);
}
- }
+ };
}
}
+pub fn format(
+ uri: Uri,
+ comptime fmt: []const u8,
+ options: std.fmt.FormatOptions,
+ writer: anytype,
+) @TypeOf(writer).Error!void {
+ _ = options;
+
+ const scheme = comptime std.mem.indexOf(u8, fmt, ":") != null or fmt.len == 0;
+ const authentication = comptime std.mem.indexOf(u8, fmt, "@") != null or fmt.len == 0;
+ const authority = comptime std.mem.indexOf(u8, fmt, "+") != null or fmt.len == 0;
+ const path = comptime std.mem.indexOf(u8, fmt, "/") != null or fmt.len == 0;
+ const query = comptime std.mem.indexOf(u8, fmt, "?") != null or fmt.len == 0;
+ const fragment = comptime std.mem.indexOf(u8, fmt, "#") != null or fmt.len == 0;
+ const raw = comptime std.mem.indexOf(u8, fmt, "r") != null or fmt.len == 0;
+
+ return writeToStream(uri, .{
+ .scheme = scheme,
+ .authentication = authentication,
+ .authority = authority,
+ .path = path,
+ .query = query,
+ .fragment = fragment,
+ .raw = raw,
+ }, writer);
+}
+
/// 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`.
@@ -709,7 +755,7 @@ test "URI query escaping" {
const parsed = try Uri.parse(address);
// format the URI to escape it
- const formatted_uri = try std.fmt.allocPrint(std.testing.allocator, "{}", .{parsed});
+ const formatted_uri = try std.fmt.allocPrint(std.testing.allocator, "{/?}", .{parsed});
defer std.testing.allocator.free(formatted_uri);
try std.testing.expectEqualStrings("/?response-content-type=application%2Foctet-stream", formatted_uri);
}
@@ -727,6 +773,6 @@ test "format" {
};
var buf = std.ArrayList(u8).init(std.testing.allocator);
defer buf.deinit();
- try uri.format("+/", .{}, buf.writer());
+ try uri.format(":/?#", .{}, buf.writer());
try std.testing.expectEqualSlices(u8, "file:/foo/bar/baz", buf.items);
}