@@ -62,7 +62,10 @@ pub const URL = struct {
6262 return .{
6363 .rawuri = raw ,
6464 .uri = uri ,
65- .search_params = try URLSearchParams .constructor (alloc , uri .query ),
65+ .search_params = try URLSearchParams .constructor (
66+ alloc ,
67+ uriComponentNullStr (uri .query ),
68+ ),
6669 };
6770 }
6871
@@ -102,7 +105,7 @@ pub const URL = struct {
102105 var q = std .ArrayList (u8 ).init (alloc );
103106 defer q .deinit ();
104107 try self .search_params .values .encode (q .writer ());
105- self .uri .query = q .items ;
108+ self .uri .query = .{ . raw = q .items } ;
106109
107110 return try self .format (alloc );
108111 }
@@ -116,9 +119,9 @@ pub const URL = struct {
116119 .scheme = true ,
117120 .authentication = true ,
118121 .authority = true ,
119- .path = self .uri .path .len > 0 ,
120- .query = self .uri .query != null and self . uri . query .? .len > 0 ,
121- .fragment = self .uri .fragment != null and self . uri . fragment .? .len > 0 ,
122+ .path = uriComponentNullStr ( self .uri .path ) .len > 0 ,
123+ .query = uriComponentNullStr ( self .uri .query ) .len > 0 ,
124+ .fragment = uriComponentNullStr ( self .uri .fragment ) .len > 0 ,
122125 }, buf .writer ());
123126 return try buf .toOwnedSlice ();
124127 }
@@ -131,11 +134,11 @@ pub const URL = struct {
131134 }
132135
133136 pub fn get_username (self : * URL ) []const u8 {
134- return self .uri .user orelse "" ;
137+ return uriComponentNullStr ( self .uri .user ) ;
135138 }
136139
137140 pub fn get_password (self : * URL ) []const u8 {
138- return self .uri .password orelse "" ;
141+ return uriComponentNullStr ( self .uri .password ) ;
139142 }
140143
141144 // the caller must free the returned string.
@@ -157,7 +160,7 @@ pub const URL = struct {
157160 }
158161
159162 pub fn get_hostname (self : * URL ) []const u8 {
160- return self .uri .host orelse "" ;
163+ return uriComponentNullStr ( self .uri .host ) ;
161164 }
162165
163166 // the caller must free the returned string.
@@ -174,8 +177,8 @@ pub const URL = struct {
174177 }
175178
176179 pub fn get_pathname (self : * URL ) []const u8 {
177- if (self .uri .path .len == 0 ) return "/" ;
178- return self .uri .path ;
180+ if (uriComponentStr ( self .uri .path ) .len == 0 ) return "/" ;
181+ return uriComponentStr ( self .uri .path ) ;
179182 }
180183
181184 // the caller must free the returned string.
@@ -198,7 +201,7 @@ pub const URL = struct {
198201 pub fn get_hash (self : * URL , alloc : std.mem.Allocator ) ! []const u8 {
199202 if (self .uri .fragment == null ) return try alloc .dupe (u8 , "" );
200203
201- return try std .mem .concat (alloc , u8 , &[_ ][]const u8 { "#" , self .uri .fragment .? });
204+ return try std .mem .concat (alloc , u8 , &[_ ][]const u8 { "#" , uriComponentNullStr ( self .uri .fragment ) });
202205 }
203206
204207 pub fn get_searchParams (self : * URL ) * URLSearchParams {
@@ -210,6 +213,21 @@ pub const URL = struct {
210213 }
211214};
212215
216+ // uriComponentNullStr converts an optional std.Uri.Component to string value.
217+ // The string value can be undecoded.
218+ fn uriComponentNullStr (c : ? std.Uri.Component ) []const u8 {
219+ if (c == null ) return "" ;
220+
221+ return uriComponentStr (c .? );
222+ }
223+
224+ fn uriComponentStr (c : std.Uri.Component ) []const u8 {
225+ return switch (c ) {
226+ .raw = > | v | v ,
227+ .percent_encoded = > | v | v ,
228+ };
229+ }
230+
213231// https://url.spec.whatwg.org/#interface-urlsearchparams
214232// TODO array like
215233pub const URLSearchParams = struct {
0 commit comments