0
# URL Building and Parsing
1
2
URL construction, parsing, and manipulation with immutable URLs and builder patterns.
3
4
## Capabilities
5
6
### URL Class
7
8
Immutable URL representation with full parsing and component access.
9
10
```kotlin { .api }
11
/**
12
* Immutable URL representation
13
*/
14
class Url {
15
val protocol: URLProtocol
16
val host: String
17
val port: Int
18
val specifiedPort: Int
19
val encodedPath: String
20
val encodedPathAndQuery: String
21
val encodedQuery: String
22
val parameters: Parameters
23
val fragment: String?
24
val encodedFragment: String?
25
val user: String?
26
val encodedUser: String?
27
val password: String?
28
val encodedPassword: String?
29
val pathSegments: List<String>
30
val rawSegments: List<String>
31
val segments: List<String>
32
val trailingQuery: Boolean
33
34
companion object {
35
/**
36
* Create URL from string
37
* @param urlString URL string to parse
38
* @return Url instance
39
*/
40
operator fun invoke(urlString: String): Url
41
42
fun serializer(): KSerializer<Url>
43
}
44
}
45
46
/**
47
* Parse URL from string
48
* @param urlString URL string to parse
49
* @return Url instance
50
*/
51
fun parseUrl(urlString: String): Url
52
```
53
54
### URLBuilder Class
55
56
Mutable builder for constructing URLs with fluent API.
57
58
```kotlin { .api }
59
/**
60
* Mutable URL builder
61
*/
62
class URLBuilder(
63
protocol: URLProtocol = URLProtocol.HTTP,
64
host: String = "localhost",
65
port: Int = DEFAULT_PORT,
66
user: String? = null,
67
password: String? = null,
68
pathSegments: List<String> = emptyList(),
69
parameters: Parameters = Parameters.Empty,
70
fragment: String? = null,
71
trailingQuery: Boolean = false
72
) {
73
var protocol: URLProtocol
74
var host: String
75
var port: Int
76
var user: String?
77
var encodedUser: String?
78
var password: String?
79
var encodedPassword: String?
80
val pathSegments: MutableList<String>
81
val encodedPathSegments: MutableList<String>
82
val parameters: ParametersBuilder
83
val encodedParameters: ParametersBuilder
84
var fragment: String?
85
var encodedFragment: String?
86
var trailingQuery: Boolean
87
88
val protocolOrNull: URLProtocol?
89
val authority: String
90
val encodedPath: String
91
92
/**
93
* Build immutable URL
94
* @return Url instance
95
*/
96
fun build(): Url
97
98
/**
99
* Build URL as string
100
* @return URL string representation
101
*/
102
fun buildString(): String
103
104
/**
105
* Initialize from URL string
106
* @param url URL string to parse
107
* @return This URLBuilder for chaining
108
*/
109
fun takeFrom(url: String): URLBuilder
110
111
/**
112
* Initialize from another URLBuilder
113
* @param builder URLBuilder to copy from
114
* @return This URLBuilder for chaining
115
*/
116
fun takeFrom(builder: URLBuilder): URLBuilder
117
118
/**
119
* Initialize from Url instance
120
* @param url Url to copy from
121
* @return This URLBuilder for chaining
122
*/
123
fun takeFrom(url: Url): URLBuilder
124
125
/**
126
* Clone this builder
127
* @return New URLBuilder with same configuration
128
*/
129
fun clone(): URLBuilder
130
}
131
132
const val DEFAULT_PORT: Int
133
```
134
135
### URL Construction Functions
136
137
Utility functions for creating URLs and URLBuilders.
138
139
```kotlin { .api }
140
/**
141
* Create URLBuilder from string
142
* @param urlString URL string to parse
143
* @return URLBuilder instance
144
*/
145
fun URLBuilder(urlString: String): URLBuilder
146
147
/**
148
* Create URLBuilder from Url
149
* @param url Url to copy from
150
* @return URLBuilder instance
151
*/
152
fun URLBuilder(url: Url): URLBuilder
153
154
/**
155
* Create URLBuilder from another URLBuilder
156
* @param builder URLBuilder to copy from
157
* @return URLBuilder instance
158
*/
159
fun URLBuilder(builder: URLBuilder): URLBuilder
160
161
/**
162
* Create Url from URLBuilder
163
* @param builder URLBuilder to build from
164
* @return Url instance
165
*/
166
fun Url(builder: URLBuilder): Url
167
168
/**
169
* Build URL using builder function
170
* @param block Function to configure URLBuilder
171
* @return Url instance
172
*/
173
fun buildUrl(block: URLBuilder.() -> Unit): Url
174
```
175
176
### Path Manipulation
177
178
Functions for working with URL paths.
179
180
```kotlin { .api }
181
/**
182
* Append path segments to URL builder
183
* @param segments Path segments to append
184
* @param encodeSlash Whether to encode slash characters
185
* @return URLBuilder for chaining
186
*/
187
fun URLBuilder.appendPathSegments(segments: List<String>, encodeSlash: Boolean = true): URLBuilder
188
fun URLBuilder.appendPathSegments(vararg segments: String, encodeSlash: Boolean = true): URLBuilder
189
190
/**
191
* Append encoded path segments to URL builder
192
* @param segments Pre-encoded path segments
193
* @return URLBuilder for chaining
194
*/
195
fun URLBuilder.appendEncodedPathSegments(segments: List<String>): URLBuilder
196
fun URLBuilder.appendEncodedPathSegments(vararg segments: String): URLBuilder
197
198
/**
199
* Set path segments replacing existing ones
200
* @param segments Path segments to set
201
* @return URLBuilder for chaining
202
*/
203
fun URLBuilder.pathComponents(segments: List<String>): URLBuilder
204
fun URLBuilder.pathComponents(vararg segments: String): URLBuilder
205
206
/**
207
* Set path segments from string array
208
* @param segments Path segments
209
*/
210
fun URLBuilder.path(vararg segments: String)
211
212
/**
213
* Set encoded path directly
214
* @param encodedPath Encoded path string
215
*/
216
fun URLBuilder.setEncodedPath(encodedPath: String)
217
```
218
219
### URL Utilities
220
221
Utility functions for URL manipulation and information.
222
223
```kotlin { .api }
224
/**
225
* Get full path including query string
226
* @return Full path with query
227
*/
228
fun Url.getFullPath(): String
229
230
/**
231
* Get host with port if non-default
232
* @return Host with port
233
*/
234
fun Url.getHostWithPort(): String
235
236
/**
237
* Get host with port if explicitly specified
238
* @return Host with port if specified
239
*/
240
fun Url.getHostWithPortIfSpecified(): String
241
242
/**
243
* Check if URL has absolute path
244
* @return true if path is absolute
245
*/
246
fun Url.isAbsolutePath(): Boolean
247
fun URLBuilder.isAbsolutePath(): Boolean
248
249
/**
250
* Check if URL has relative path
251
* @return true if path is relative
252
*/
253
fun Url.isRelativePath(): Boolean
254
fun URLBuilder.isRelativePath(): Boolean
255
256
/**
257
* Get authority part (user:password@host:port)
258
* @return Authority string
259
*/
260
fun Url.getAuthority(): String
261
262
/**
263
* Get protocol with authority (https://example.com)
264
* @return Protocol with authority
265
*/
266
fun Url.getProtocolWithAuthority(): String
267
268
/**
269
* Append URL path with parameters to Appendable
270
* @param path Path to append
271
* @param parameters Parameters to append
272
* @param includeQuery Whether to include query separator
273
*/
274
fun appendUrlFullPath(
275
out: Appendable,
276
path: String,
277
parameters: ParametersBuilder,
278
includeQuery: Boolean
279
)
280
```
281
282
### URLProtocol
283
284
URL protocol/scheme representation with common protocols pre-defined.
285
286
```kotlin { .api }
287
/**
288
* URL protocol/scheme
289
* @param name Protocol name (e.g., "https")
290
* @param defaultPort Default port for protocol
291
*/
292
data class URLProtocol(val name: String, val defaultPort: Int) {
293
companion object {
294
val HTTP: URLProtocol
295
val HTTPS: URLProtocol
296
val WS: URLProtocol
297
val WSS: URLProtocol
298
val SOCKS: URLProtocol
299
300
val byName: Map<String, URLProtocol>
301
302
/**
303
* Get existing protocol or create new one
304
* @param name Protocol name
305
* @return URLProtocol instance
306
*/
307
fun createOrDefault(name: String): URLProtocol
308
}
309
}
310
311
/**
312
* Check if protocol is secure (HTTPS, WSS)
313
* @return true if secure protocol
314
*/
315
fun URLProtocol.isSecure(): Boolean
316
317
/**
318
* Check if protocol is WebSocket (WS, WSS)
319
* @return true if WebSocket protocol
320
*/
321
fun URLProtocol.isWebsocket(): Boolean
322
```
323
324
### URL Encoding/Decoding
325
326
Functions for URL component encoding and decoding.
327
328
```kotlin { .api }
329
/**
330
* Encode URL path component
331
* @param path Path to encode
332
* @param encodeSlash Whether to encode slash characters
333
* @param encodePercent Whether to encode percent characters
334
* @return Encoded path
335
*/
336
fun encodeURLPath(path: String, encodeSlash: Boolean = false, encodePercent: Boolean = true): String
337
338
/**
339
* Encode URL path part
340
* @param part Path part to encode
341
* @return Encoded path part
342
*/
343
fun encodeURLPathPart(part: String): String
344
345
/**
346
* Encode URL parameter
347
* @param value Parameter value to encode
348
* @param spaceToPlus Whether to encode spaces as plus signs
349
* @return Encoded parameter value
350
*/
351
fun encodeURLParameter(value: String, spaceToPlus: Boolean = false): String
352
353
/**
354
* Encode URL query component
355
* @param component Query component to encode
356
* @param spaceToPlus Whether to encode spaces as plus signs
357
* @param encodeFull Whether to encode all special characters
358
* @param charset Character encoding to use
359
* @return Encoded query component
360
*/
361
fun encodeURLQueryComponent(
362
component: String,
363
spaceToPlus: Boolean = true,
364
encodeFull: Boolean = false,
365
charset: Charset = Charsets.UTF_8
366
): String
367
368
/**
369
* Decode URL part
370
* @param encoded Encoded URL part
371
* @param start Start index
372
* @param end End index
373
* @param charset Character encoding to use
374
* @return Decoded string
375
*/
376
fun decodeURLPart(
377
encoded: String,
378
start: Int = 0,
379
end: Int = encoded.length,
380
charset: Charset = Charsets.UTF_8
381
): String
382
383
/**
384
* Decode URL query component
385
* @param encoded Encoded query component
386
* @param start Start index
387
* @param end End index
388
* @param plusToSpace Whether to decode plus signs as spaces
389
* @param charset Character encoding to use
390
* @return Decoded string
391
*/
392
fun decodeURLQueryComponent(
393
encoded: String,
394
start: Int = 0,
395
end: Int = encoded.length,
396
plusToSpace: Boolean = true,
397
charset: Charset = Charsets.UTF_8
398
): String
399
400
/**
401
* OAuth-specific URL encoding
402
* @param value Value to encode
403
* @return OAuth-encoded value
404
*/
405
fun encodeOAuth(value: String): String
406
```
407
408
### Exception Types
409
410
Exceptions thrown during URL processing.
411
412
```kotlin { .api }
413
/**
414
* Exception thrown when URL decoding fails
415
*/
416
class URLDecodeException(message: String) : Exception(message)
417
418
/**
419
* Exception thrown when URL parsing fails
420
*/
421
class URLParserException(message: String, cause: Throwable? = null) : IllegalStateException(message, cause)
422
```
423
424
**Usage Examples:**
425
426
```kotlin
427
import io.ktor.http.*
428
429
// Create URLs
430
val url1 = Url("https://api.example.com/users?page=1")
431
val url2 = parseUrl("https://example.com/path")
432
433
// Build URLs
434
val builtUrl = buildUrl {
435
protocol = URLProtocol.HTTPS
436
host = "api.example.com"
437
port = 8080
438
path("v1", "users", "123")
439
parameters.append("format", "json")
440
parameters.append("include", "profile")
441
fragment = "section1"
442
}
443
444
// Use URLBuilder
445
val builder = URLBuilder("https://example.com")
446
builder.appendPathSegments("api", "v1", "users")
447
builder.parameters.append("q", "search term")
448
val finalUrl = builder.build()
449
450
// Access URL components
451
val protocol = url1.protocol // URLProtocol.HTTPS
452
val host = url1.host // "api.example.com"
453
val path = url1.encodedPath // "/users"
454
val params = url1.parameters // Parameters with "page" -> "1"
455
val query = url1.encodedQuery // "page=1"
456
457
// URL utilities
458
val fullPath = url1.getFullPath() // "/users?page=1"
459
val hostWithPort = url1.getHostWithPort() // "api.example.com" or "api.example.com:8080"
460
val isAbsolute = url1.isAbsolutePath() // true
461
462
// Encoding/decoding
463
val encoded = encodeURLPath("/api/v1/users")
464
val encodedParam = encodeURLParameter("hello world")
465
val decoded = decodeURLQueryComponent("hello%20world")
466
467
// Protocol utilities
468
val isSecure = URLProtocol.HTTPS.isSecure() // true
469
val isWebSocket = URLProtocol.WS.isWebsocket() // true
470
471
// Clone and modify
472
val newBuilder = URLBuilder(url1)
473
newBuilder.host = "different.example.com"
474
val modifiedUrl = newBuilder.build()
475
```