@@ -31,7 +31,7 @@ fn set_bit(array: &mut [u8], ch: u8) {
31
31
}
32
32
33
33
thread_local ! {
34
- static DEFAULT_QUOTER : Quoter = Quoter :: new( b"@:" , b"/+" ) ;
34
+ static DEFAULT_QUOTER : Quoter = Quoter :: new( b"@:" , b"% /+" ) ;
35
35
}
36
36
37
37
#[ derive( Default , Clone , Debug ) ]
@@ -204,24 +204,59 @@ mod tests {
204
204
use super :: * ;
205
205
use crate :: { Path , ResourceDef } ;
206
206
207
+ const PROTECTED : & [ u8 ] = b"%/+" ;
208
+
209
+ fn match_url ( pattern : & ' static str , url : impl AsRef < str > ) -> Path < Url > {
210
+ let re = ResourceDef :: new ( pattern) ;
211
+ let uri = Uri :: try_from ( url. as_ref ( ) ) . unwrap ( ) ;
212
+ let mut path = Path :: new ( Url :: new ( uri) ) ;
213
+ assert ! ( re. match_path( & mut path) ) ;
214
+ path
215
+ }
216
+
217
+ fn percent_encode ( data : & [ u8 ] ) -> String {
218
+ data. into_iter ( ) . map ( |c| format ! ( "%{:02X}" , c) ) . collect ( )
219
+ }
220
+
207
221
#[ test]
208
222
fn test_parse_url ( ) {
209
- let re = ResourceDef :: new ( "/user/{id}/test" ) ;
223
+ let re = "/user/{id}/test" ;
210
224
211
- let url = Uri :: try_from ( "/user/2345/test" ) . unwrap ( ) ;
212
- let mut path = Path :: new ( Url :: new ( url) ) ;
213
- assert ! ( re. match_path( & mut path) ) ;
225
+ let path = match_url ( re, "/user/2345/test" ) ;
214
226
assert_eq ! ( path. get( "id" ) . unwrap( ) , "2345" ) ;
215
227
216
- let url = Uri :: try_from ( "/user/qwe %25/test" ) . unwrap ( ) ;
217
- let mut path = Path :: new ( Url :: new ( url ) ) ;
218
- assert ! ( re. match_path ( & mut path ) ) ;
219
- assert_eq ! ( path. get( "id" ) . unwrap( ) , "qwe%" ) ;
228
+ // " %25" should never be decoded into '%' to gurantee the output is a valid
229
+ // percent-encoded format
230
+ let path = match_url ( re, "/user/qwe%25/test" ) ;
231
+ assert_eq ! ( path. get( "id" ) . unwrap( ) , "qwe%25 " ) ;
220
232
221
- let url = Uri :: try_from ( "/user/qwe%25rty/test" ) . unwrap ( ) ;
222
- let mut path = Path :: new ( Url :: new ( url) ) ;
223
- assert ! ( re. match_path( & mut path) ) ;
224
- assert_eq ! ( path. get( "id" ) . unwrap( ) , "qwe%rty" ) ;
233
+ let path = match_url ( re, "/user/qwe%25rty/test" ) ;
234
+ assert_eq ! ( path. get( "id" ) . unwrap( ) , "qwe%25rty" ) ;
235
+ }
236
+
237
+ #[ test]
238
+ fn test_protected_chars ( ) {
239
+ let encoded = percent_encode ( PROTECTED ) ;
240
+ let path = match_url ( "/user/{id}/test" , format ! ( "/user/{}/test" , encoded) ) ;
241
+ assert_eq ! ( path. get( "id" ) . unwrap( ) , & encoded) ;
242
+ }
243
+
244
+ #[ test]
245
+ fn test_non_protecteed_ascii ( ) {
246
+ let nonprotected_ascii = ( '\u{0}' ..='\u{7F}' )
247
+ . filter ( |& c| c. is_ascii ( ) && !PROTECTED . contains ( & ( c as u8 ) ) )
248
+ . collect :: < String > ( ) ;
249
+ let encoded = percent_encode ( nonprotected_ascii. as_bytes ( ) ) ;
250
+ let path = match_url ( "/user/{id}/test" , format ! ( "/user/{}/test" , encoded) ) ;
251
+ assert_eq ! ( path. get( "id" ) . unwrap( ) , & nonprotected_ascii) ;
252
+ }
253
+
254
+ #[ test]
255
+ fn test_valid_utf8_multibyte ( ) {
256
+ let test = ( '\u{FF00}' ..='\u{FFFF}' ) . collect :: < String > ( ) ;
257
+ let encoded = percent_encode ( test. as_bytes ( ) ) ;
258
+ let path = match_url ( "/a/{id}/b" , format ! ( "/a/{}/b" , & encoded) ) ;
259
+ assert_eq ! ( path. get( "id" ) . unwrap( ) , & test) ;
225
260
}
226
261
227
262
#[ test]
0 commit comments