@@ -43,7 +43,7 @@ type UriKey {
43
43
Fragment
44
44
}
45
45
46
- /// Parses a complient URI string into the `Uri` Type.
46
+ /// Parses a compliant URI string into the `Uri` Type.
47
47
/// If the string is not a valid URI string then an error is returned.
48
48
///
49
49
/// The opposite operation is `uri.to_string`
@@ -117,7 +117,10 @@ pub fn query_to_string(query: List(tuple(String, String))) -> String {
117
117
|> result.unwrap("")
118
118
}
119
119
120
- fn do_remove_dot_segments(input, accumulator) {
120
+ fn do_remove_dot_segments(
121
+ input: List(String),
122
+ accumulator: List(String),
123
+ ) -> List(String) {
121
124
case input {
122
125
[] -> list.reverse(accumulator)
123
126
[segment, ..rest] -> {
@@ -133,7 +136,7 @@ fn do_remove_dot_segments(input, accumulator) {
133
136
}
134
137
}
135
138
136
- fn remove_dot_segments(input) {
139
+ fn remove_dot_segments(input: List(String)) -> List(String ) {
137
140
do_remove_dot_segments(input, [])
138
141
}
139
142
@@ -142,7 +145,7 @@ fn remove_dot_segments(input) {
142
145
/// Removes empty segments and resolves dot-segments as specified in
143
146
/// [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC.
144
147
///
145
- pub fn path_segments(path) {
148
+ pub fn path_segments(path: String) -> List(String ) {
146
149
remove_dot_segments(string.split(path, "/"))
147
150
}
148
151
@@ -154,10 +157,14 @@ external fn erl_to_string(Map(UriKey, Dynamic)) -> Dynamic =
154
157
/// The opposite operation is `uri.parse`.
155
158
///
156
159
pub fn to_string(uri: Uri) -> String {
157
- let field = fn(key: UriKey, value: Option(anything)) {
158
- value
159
- |> option.to_result(Nil)
160
- |> result.map(fn(value) { tuple(key, dynamic.from(value)) })
160
+ let field = fn(
161
+ key: UriKey,
162
+ value: Option(anything),
163
+ ) -> Result(tuple(UriKey, Dynamic), Nil) {
164
+ case value {
165
+ Some(v) -> Ok(tuple(key, dynamic.from(v)))
166
+ None -> Error(Nil)
167
+ }
161
168
}
162
169
163
170
[
@@ -194,16 +201,12 @@ pub fn origin(uri: Uri) -> Result(String, Nil) {
194
201
}
195
202
}
196
203
197
- fn drop_last(elements) {
198
- let tuple(keep, _last) = list.split(elements, list.length(elements) - 1)
199
- keep
204
+ fn drop_last(elements: List(a)) -> List(a) {
205
+ list.take(from: elements, up_to: list.length(elements) - 1)
200
206
}
201
207
202
- fn join_segments(segments) {
203
- case segments {
204
- [] -> ""
205
- _ -> string.append("/", string.join(segments, "/"))
206
- }
208
+ fn join_segments(segments: List(String)) -> String {
209
+ string.join(["", ..segments], "/")
207
210
}
208
211
209
212
/// Resolve a uri with respect to the given base uri
@@ -213,27 +216,12 @@ fn join_segments(segments) {
213
216
pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) {
214
217
case base {
215
218
Uri(scheme: Some(_), host: Some(_), ..) -> case relative {
216
- Uri(scheme: Some(_), ..) -> {
217
- let path = string.split(relative.path, "/")
218
- |> remove_dot_segments()
219
- |> join_segments()
220
- let resolved = Uri(
221
- relative.scheme,
222
- None,
223
- relative.host,
224
- relative.port,
225
- path,
226
- relative.query,
227
- relative.fragment,
228
- )
229
- Ok(resolved)
230
- }
231
- Uri(scheme: None, host: Some(_), ..) -> {
219
+ Uri(host: Some(_), ..) -> {
232
220
let path = string.split(relative.path, "/")
233
221
|> remove_dot_segments()
234
222
|> join_segments()
235
223
let resolved = Uri(
236
- base.scheme,
224
+ option.or(relative.scheme, base.scheme) ,
237
225
None,
238
226
relative.host,
239
227
relative.port,
@@ -243,57 +231,33 @@ pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) {
243
231
)
244
232
Ok(resolved)
245
233
}
246
- Uri(scheme: None, host: None, path: "", ..) -> {
234
+ Uri(scheme: None, host: None, ..) -> {
235
+ let tuple(new_path, new_query) = case relative.path {
236
+ "" -> tuple(base.path, option.or(relative.query, base.query))
237
+ _ -> {
238
+ let path_segments = case string.starts_with(relative.path, "/") {
239
+ True -> string.split(relative.path, "/")
240
+ False -> string.split(base.path, "/")
241
+ |> drop_last()
242
+ |> list.append(string.split(relative.path, "/") )
243
+ }
244
+ let path = path_segments
245
+ |> remove_dot_segments ( )
246
+ |> join_segments ( )
247
+ tuple ( path , relative . query )
248
+ }
249
+ }
247
250
let resolved = Uri (
248
251
base . scheme ,
249
252
None ,
250
253
base . host ,
251
254
base . port ,
252
- base.path ,
253
- option.or(relative.query, base.query) ,
255
+ new_path ,
256
+ new_query ,
254
257
relative . fragment ,
255
258
)
256
259
Ok ( resolved )
257
260
}
258
- Uri(
259
- scheme: None,
260
- host: None,
261
- path: path,
262
- ..,
263
- ) -> case string.starts_with(path, "/") {
264
- True -> {
265
- let path = string.split(relative.path, "/")
266
- |> remove_dot_segments()
267
- |> join_segments()
268
- let resolved = Uri(
269
- base.scheme,
270
- None,
271
- base.host,
272
- base.port,
273
- path,
274
- relative.query,
275
- relative.fragment,
276
- )
277
- Ok(resolved)
278
- }
279
- False -> {
280
- let path = string.split(base.path, "/")
281
- |> drop_last()
282
- |> list.append(string.split(relative.path, "/") )
283
- |> remove_dot_segments ( )
284
- |> join_segments ( )
285
- let resolved = Uri (
286
- base . scheme ,
287
- None ,
288
- base . host ,
289
- base . port ,
290
- path ,
291
- relative . query ,
292
- relative . fragment ,
293
- )
294
- Ok ( resolved )
295
- }
296
- }
297
261
}
298
262
_ -> Error ( Nil )
299
263
}
0 commit comments