@@ -58,7 +58,7 @@ defmodule URI do
58
58
new URIs.
59
59
"""
60
60
@ spec default_port ( binary , pos_integer ) :: :ok
61
- def default_port ( scheme , port ) when is_binary ( scheme ) and port > 0 do
61
+ def default_port ( scheme , port ) when is_binary ( scheme ) and is_integer ( port ) and port > 0 do
62
62
:elixir_config . put ( { :uri , scheme } , port )
63
63
end
64
64
@@ -88,7 +88,22 @@ defmodule URI do
88
88
89
89
"""
90
90
@ spec encode_query ( term ) :: binary
91
- def encode_query ( l ) , do: Enum . map_join ( l , "&" , & pair / 1 )
91
+ def encode_query ( enumerable ) do
92
+ Enum . map_join ( enumerable , "&" , & encode_kv_pair / 1 )
93
+ end
94
+
95
+ defp encode_kv_pair ( { key , _ } ) when is_list ( key ) do
96
+ raise ArgumentError , "encode_query/1 keys cannot be lists, got: #{ inspect key } "
97
+ end
98
+
99
+ defp encode_kv_pair ( { _ , value } ) when is_list ( value ) do
100
+ raise ArgumentError , "encode_query/1 values cannot be lists, got: #{ inspect value } "
101
+ end
102
+
103
+ defp encode_kv_pair ( { key , value } ) do
104
+ encode_www_form ( Kernel . to_string ( key ) ) <>
105
+ "=" <> encode_www_form ( Kernel . to_string ( value ) )
106
+ end
92
107
93
108
@ doc """
94
109
Decodes a query string into a map.
@@ -110,33 +125,37 @@ defmodule URI do
110
125
111
126
"""
112
127
@ spec decode_query ( binary , map ) :: map
113
- def decode_query ( q , map \\ % { } )
128
+ def decode_query ( query , map \\ % { } )
114
129
115
- def decode_query ( q , % { __struct__: _ } = dict ) when is_binary ( q ) do
130
+ def decode_query ( query , % { __struct__: _ } = dict ) when is_binary ( query ) do
116
131
IO . warn "URI.decode_query/2 is deprecated, please use URI.decode_query/1"
117
- decode_query_dict ( q , dict )
132
+ decode_query_into_dict ( query , dict )
118
133
end
119
134
120
- def decode_query ( q , map ) when is_binary ( q ) and is_map ( map ) do
121
- decode_query_map ( q , map )
135
+ def decode_query ( query , map ) when is_binary ( query ) and is_map ( map ) do
136
+ decode_query_into_map ( query , map )
122
137
end
123
138
124
- def decode_query ( q , dict ) when is_binary ( q ) do
139
+ def decode_query ( query , dict ) when is_binary ( query ) do
125
140
IO . warn "URI.decode_query/2 is deprecated, please use URI.decode_query/1"
126
- decode_query_dict ( q , dict )
141
+ decode_query_into_dict ( query , dict )
127
142
end
128
143
129
- defp decode_query_map ( q , map ) do
130
- case do_decode_query ( q ) do
131
- nil -> map
132
- { { k , v } , q } -> decode_query_map ( q , Map . put ( map , k , v ) )
144
+ defp decode_query_into_map ( query , map ) do
145
+ case decode_next_query_pair ( query ) do
146
+ nil ->
147
+ map
148
+ { { key , value } , rest } ->
149
+ decode_query_into_map ( rest , Map . put ( map , key , value ) )
133
150
end
134
151
end
135
152
136
- defp decode_query_dict ( q , dict ) do
137
- case do_decode_query ( q ) do
138
- nil -> dict
139
- { { k , v } , q } -> decode_query_dict ( q , Dict . put ( dict , k , v ) )
153
+ defp decode_query_into_dict ( query , dict ) do
154
+ case decode_next_query_pair ( query ) do
155
+ nil ->
156
+ dict
157
+ { { key , value } , rest } ->
158
+ decode_query_into_dict ( rest , Dict . put ( dict , key , value ) )
140
159
end
141
160
end
142
161
@@ -153,43 +172,28 @@ defmodule URI do
153
172
154
173
"""
155
174
@ spec query_decoder ( binary ) :: Enumerable . t
156
- def query_decoder ( q ) when is_binary ( q ) do
157
- Stream . unfold ( q , & do_decode_query / 1 )
175
+ def query_decoder ( query ) when is_binary ( query ) do
176
+ Stream . unfold ( query , & decode_next_query_pair / 1 )
158
177
end
159
178
160
- defp do_decode_query ( "" ) do
179
+ defp decode_next_query_pair ( "" ) do
161
180
nil
162
181
end
163
182
164
- defp do_decode_query ( q ) do
165
- { first , next } =
166
- case :binary . split ( q , "&" ) do
167
- [ first , rest ] -> { first , rest }
168
- [ first ] -> { first , "" }
183
+ defp decode_next_query_pair ( query ) do
184
+ { undecoded_next_pair , rest } =
185
+ case :binary . split ( query , "&" ) do
186
+ [ next_pair , rest ] -> { next_pair , rest }
187
+ [ next_pair ] -> { next_pair , "" }
169
188
end
170
189
171
- current =
172
- case :binary . split ( first , "=" ) do
173
- [ key , value ] ->
174
- { decode_www_form ( key ) , decode_www_form ( value ) }
175
- [ key ] ->
176
- { decode_www_form ( key ) , nil }
190
+ next_pair =
191
+ case :binary . split ( undecoded_next_pair , "=" ) do
192
+ [ key , value ] -> { decode_www_form ( key ) , decode_www_form ( value ) }
193
+ [ key ] -> { decode_www_form ( key ) , nil }
177
194
end
178
195
179
- { current , next }
180
- end
181
-
182
- defp pair ( { k , _ } ) when is_list ( k ) do
183
- raise ArgumentError , "encode_query/1 keys cannot be lists, got: #{ inspect k } "
184
- end
185
-
186
- defp pair ( { _ , v } ) when is_list ( v ) do
187
- raise ArgumentError , "encode_query/1 values cannot be lists, got: #{ inspect v } "
188
- end
189
-
190
- defp pair ( { k , v } ) do
191
- encode_www_form ( Kernel . to_string ( k ) ) <>
192
- "=" <> encode_www_form ( Kernel . to_string ( v ) )
196
+ { next_pair , rest }
193
197
end
194
198
195
199
@ doc """
@@ -204,9 +208,9 @@ defmodule URI do
204
208
true
205
209
206
210
"""
207
- @ spec char_reserved? ( term ) :: boolean
208
- def char_reserved? ( c ) do
209
- c in ':/?#[]@!$&\' ()*+,;='
211
+ @ spec char_reserved? ( char ) :: boolean
212
+ def char_reserved? ( char ) when char in 0 .. 0x10ffff do
213
+ char in ':/?#[]@!$&\' ()*+,;='
210
214
end
211
215
212
216
@ doc """
@@ -221,12 +225,12 @@ defmodule URI do
221
225
true
222
226
223
227
"""
224
- @ spec char_unreserved? ( term ) :: boolean
225
- def char_unreserved? ( c ) do
226
- c in ?0 .. ?9 or
227
- c in ?a .. ?z or
228
- c in ?A .. ?Z or
229
- c in '~_-.'
228
+ @ spec char_unreserved? ( char ) :: boolean
229
+ def char_unreserved? ( char ) when char in 0 .. 0x10ffff do
230
+ char in ?0 .. ?9 or
231
+ char in ?a .. ?z or
232
+ char in ?A .. ?Z or
233
+ char in '~_-.'
230
234
end
231
235
232
236
@ doc """
@@ -241,9 +245,9 @@ defmodule URI do
241
245
false
242
246
243
247
"""
244
- @ spec char_unescaped? ( term ) :: boolean
245
- def char_unescaped? ( c ) do
246
- char_reserved? ( c ) or char_unreserved? ( c )
248
+ @ spec char_unescaped? ( char ) :: boolean
249
+ def char_unescaped? ( char ) when char in 0 .. 0x10ffff do
250
+ char_reserved? ( char ) or char_unreserved? ( char )
247
251
end
248
252
249
253
@ doc """
@@ -264,8 +268,9 @@ defmodule URI do
264
268
265
269
"""
266
270
@ spec encode ( binary , ( byte -> boolean ) ) :: binary
267
- def encode ( str , predicate \\ & char_unescaped? / 1 ) when is_binary ( str ) do
268
- for << c <- str >> , into: "" , do: percent ( c , predicate )
271
+ def encode ( string , predicate \\ & char_unescaped? / 1 )
272
+ when is_binary ( string ) and is_function ( predicate , 1 ) do
273
+ for << char <- string >> , into: "" , do: percent ( char , predicate )
269
274
end
270
275
271
276
@ doc """
@@ -278,20 +283,20 @@ defmodule URI do
278
283
279
284
"""
280
285
@ spec encode_www_form ( binary ) :: binary
281
- def encode_www_form ( str ) when is_binary ( str ) do
282
- for << c <- str >> , into: "" do
283
- case percent ( c , & char_unreserved? / 1 ) do
286
+ def encode_www_form ( string ) when is_binary ( string ) do
287
+ for << char <- string >> , into: "" do
288
+ case percent ( char , & char_unreserved? / 1 ) do
284
289
"%20" -> "+"
285
- pct -> pct
290
+ percent -> percent
286
291
end
287
292
end
288
293
end
289
294
290
- defp percent ( c , predicate ) do
291
- if predicate . ( c ) do
292
- << c >>
295
+ defp percent ( char , predicate ) do
296
+ if predicate . ( char ) do
297
+ << char >>
293
298
else
294
- "%" <> hex ( bsr ( c , 4 ) ) <> hex ( band ( c , 15 ) )
299
+ "%" <> hex ( bsr ( char , 4 ) ) <> hex ( band ( char , 15 ) )
295
300
end
296
301
end
297
302
@@ -325,11 +330,11 @@ defmodule URI do
325
330
326
331
"""
327
332
@ spec decode_www_form ( binary ) :: binary
328
- def decode_www_form ( str ) do
329
- unpercent ( str , "" , true )
333
+ def decode_www_form ( string ) do
334
+ unpercent ( string , "" , true )
330
335
catch
331
336
:malformed_uri ->
332
- raise ArgumentError , "malformed URI #{ inspect str } "
337
+ raise ArgumentError , "malformed URI #{ inspect string } "
333
338
end
334
339
335
340
defp unpercent ( << ?+ , tail :: binary >> , acc , spaces = true ) do
@@ -392,15 +397,15 @@ defmodule URI do
392
397
393
398
def parse ( % URI { } = uri ) , do: uri
394
399
395
- def parse ( s ) when is_binary ( s ) do
400
+ def parse ( string ) when is_binary ( string ) do
396
401
# From http://tools.ietf.org/html/rfc3986#appendix-B
397
402
regex = ~r/ ^(([a-z][a-z0-9\+ \- \. ]*):)?(\/ \/ ([^\/ ?#]*))?([^?#]*)(\? ([^#]*))?(#(.*))?/ i
398
- parts = nillify ( Regex . run ( regex , s ) )
403
+ parts = nillify ( Regex . run ( regex , string ) )
399
404
400
405
destructure [ _ , _ , scheme , _ , authority , path , _ , query , _ , fragment ] , parts
401
406
{ userinfo , host , port } = split_authority ( authority )
402
407
403
- scheme = normalize_scheme ( scheme )
408
+ scheme = scheme && String . downcase ( scheme )
404
409
port = port || ( scheme && default_port ( scheme ) )
405
410
406
411
% URI {
@@ -411,9 +416,8 @@ defmodule URI do
411
416
end
412
417
413
418
# Split an authority into its userinfo, host and port parts.
414
- defp split_authority ( s ) do
415
- s = s || ""
416
- components = Regex . run ~r/ (^(.*)@)?(\[ [a-zA-Z0-9:.]*\] |[^:]*)(:(\d *))?/ , s
419
+ defp split_authority ( string ) do
420
+ components = Regex . run ( ~r/ (^(.*)@)?(\[ [a-zA-Z0-9:.]*\] |[^:]*)(:(\d *))?/ , string || "" )
417
421
418
422
destructure [ _ , _ , userinfo , host , _ , port ] , nillify ( components )
419
423
host = if host , do: host |> String . trim_leading ( "[" ) |> String . trim_trailing ( "]" )
@@ -422,14 +426,11 @@ defmodule URI do
422
426
{ userinfo , host , port }
423
427
end
424
428
425
- defp normalize_scheme ( nil ) , do: nil
426
- defp normalize_scheme ( scheme ) , do: String . downcase ( scheme )
427
-
428
429
# Regex.run returns empty strings sometimes. We want
429
430
# to replace those with nil for consistency.
430
- defp nillify ( l ) do
431
- for s <- l do
432
- if byte_size ( s ) > 0 , do: s
431
+ defp nillify ( list ) do
432
+ for string <- list do
433
+ if byte_size ( string ) > 0 , do: string
433
434
end
434
435
end
435
436
0 commit comments