or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication.mdcontent-multipart.mdcontent-types.mdcookies.mdheaders-parameters.mdhttp-protocol.mdindex.mdurl-handling.md
tile.json

url-handling.mddocs/

URL Building and Parsing

Comprehensive URL manipulation including parsing, building, encoding, and parameter handling with support for all URL components and proper encoding/decoding.

URL Protocol

URLProtocol Class

data class URLProtocol(val name: String, val defaultPort: Int)

Predefined Protocols

data class URLProtocol(val name: String, val defaultPort: Int) {
    companion object {
        val HTTP: URLProtocol // http, port 80
        val HTTPS: URLProtocol // https, port 443
        val WS: URLProtocol // ws, port 80
        val WSS: URLProtocol // wss, port 443
        val SOCKS: URLProtocol // socks, port 1080
        val byName: Map<String, URLProtocol>
        
        fun createOrDefault(name: String): URLProtocol
    }
}

fun URLProtocol.isWebsocket(): Boolean
fun URLProtocol.isSecure(): Boolean

Usage Examples

// Using predefined protocols
val httpProtocol = URLProtocol.HTTP
val httpsProtocol = URLProtocol.HTTPS

// Creating custom protocols
val customProtocol = URLProtocol("custom", 8080)

// Getting or creating protocols
val ftpProtocol = URLProtocol.createOrDefault("ftp")

// Protocol utilities
val isWebSocket = URLProtocol.WS.isWebsocket() // true
val isSecure = URLProtocol.HTTPS.isSecure() // true
val httpNotSecure = URLProtocol.HTTP.isSecure() // false

// Protocol lookup
val httpFromMap = URLProtocol.byName["http"] // Returns URLProtocol.HTTP

Immutable URL Class

URL Properties

class Url {
    val protocol: URLProtocol
    val host: String
    val port: Int
    val specifiedPort: Int
    val encodedPath: String
    val parameters: Parameters
    val fragment: String
    val user: String?
    val password: String?
    val trailingQuery: Boolean
    
    // Derived properties
    @Deprecated("Use rawSegments or segments instead")
    val pathSegments: List<String>
    val rawSegments: List<String>
    val segments: List<String>
    val encodedQuery: String
    val encodedPathAndQuery: String
    val encodedFragment: String
    val encodedUser: String?
    val encodedPassword: String?
    
    override fun toString(): String
}

URL Construction

URLs are typically created through URLBuilder or parsing functions rather than direct construction.

Mutable URLBuilder Class

URLBuilder Properties

class URLBuilder {
    var protocol: URLProtocol
    var host: String
    var port: Int
    var encodedPath: String
    val parameters: ParametersBuilder
    var fragment: String
    var user: String?
    var password: String?
    var trailingQuery: Boolean
    
    fun build(): Url
    fun clone(): URLBuilder
}

URLBuilder Construction

// Constructors
fun URLBuilder(url: Url): URLBuilder
fun URLBuilder(url: String): URLBuilder
fun URLBuilder(
    protocol: URLProtocol = URLProtocol.HTTP,
    host: String = "localhost",
    port: Int = protocol.defaultPort,
    path: String = "/",
    user: String? = null,
    password: String? = null,
    parameters: Parameters = Parameters.Empty,
    fragment: String = "",
    trailingQuery: Boolean = false
): URLBuilder

Path Manipulation

fun URLBuilder.appendPathSegments(vararg segments: String): URLBuilder
fun URLBuilder.appendPathSegments(segments: List<String>): URLBuilder
fun URLBuilder.path(vararg components: String): URLBuilder
fun URLBuilder.pathSegments(segments: List<String>): URLBuilder

URL Encoding and Decoding

String Extension Functions

// Encoding functions
fun String.encodeURLQueryComponent(
    encodeFull: Boolean = false,
    spaceToPlus: Boolean = false
): String

fun String.encodeURLPathPart(): String

fun String.encodeURLPath(
    encodeFull: Boolean = false
): String

fun String.encodeOAuth(): String

fun String.encodeURLParameter(spaceToPlus: Boolean = false): String

// Decoding functions
fun String.decodeURLQueryComponent(
    decode: Boolean = true,
    plusToSpace: Boolean = false
): String

fun String.decodeURLPart(
    start: Int = 0,
    end: Int = length,
    charset: Charset = Charsets.UTF_8
): String

URL Utility Functions

fun Url(urlString: String): Url
fun takeFrom(url: Url): URLBuilder
fun takeFrom(url: String): URLBuilder

Usage Examples

Basic URL Building

// Create URL from string
val url = Url("https://example.com/api/users?page=1&limit=10#section")

// Access URL components
println("Protocol: ${url.protocol}")
println("Host: ${url.host}")
println("Path: ${url.encodedPath}")
println("Query: ${url.encodedQuery}")
println("Fragment: ${url.fragment}")

// Build URL programmatically
val apiUrl = URLBuilder("https://api.example.com")
    .appendPathSegments("v1", "users", "123")
    .apply {
        parameters.append("include", "profile")
        parameters.append("format", "json")
    }
    .build()

println(apiUrl) // https://api.example.com/v1/users/123?include=profile&format=json

Advanced URL Building

// Complex URL with all components
val complexUrl = URLBuilder(
    protocol = URLProtocol.HTTPS,
    host = "secure.example.com", 
    port = 8443,
    user = "admin",
    password = "secret"
).apply {
    appendPathSegments("admin", "dashboard")
    parameters.append("tab", "users")
    parameters.append("sort", "name")
    fragment = "user-list"
}.build()

// Modify existing URL
val modifiedUrl = URLBuilder(complexUrl).apply {
    host = "backup.example.com"
    port = 9443
    parameters.clear()
    parameters.append("backup", "true")
}.build()

Path and Parameter Manipulation

// Working with path segments
val builder = URLBuilder("https://api.example.com")
builder.path("api", "v2", "resources")
// Results in: /api/v2/resources

// Appending additional segments
builder.appendPathSegments("123", "details")
// Results in: /api/v2/resources/123/details

// Working with parameters
builder.parameters.apply {
    append("page", "1")
    append("size", "50")
    append("sort", "name")
    append("sort", "date") // Multiple values for same key
    set("filter", "active") // Replace existing values
}

val finalUrl = builder.build()

URL Encoding Examples

// Query component encoding
val query = "hello world & special chars"
val encoded = query.encodeURLQueryComponent()
println(encoded) // hello%20world%20%26%20special%20chars

// Path segment encoding
val pathSegment = "documents/my file.pdf"
val encodedPath = pathSegment.encodeURLPathPart()
println(encodedPath) // documents%2Fmy%20file.pdf

// OAuth-specific encoding
val oauthParam = "some+special/chars"
val oauthEncoded = oauthParam.encodeOAuth()
println(oauthEncoded) // some%2Bspecial%2Fchars

// Decoding
val decoded = encoded.decodeURLQueryComponent()
println(decoded) // hello world & special chars

URL Cloning and Modification

val originalUrl = URLBuilder("https://example.com/api/users")
    .apply {
        parameters.append("page", "1")
        parameters.append("limit", "10")
    }
    .build()

// Clone and modify
val modifiedUrl = URLBuilder(originalUrl).apply {
    appendPathSegments("123")
    parameters.set("page", "2")
    parameters.append("include", "profile")
}.build()

println(originalUrl)  // https://example.com/api/users?page=1&limit=10
println(modifiedUrl) // https://example.com/api/users/123?page=2&limit=10&include=profile

Error Handling

try {
    val url = Url("invalid-url")
} catch (e: URLParserException) {
    println("Failed to parse URL: ${e.message}")
}

try {
    val decoded = "invalid%encoding".decodeURLPart()
} catch (e: URLDecodeException) {
    println("Failed to decode URL part: ${e.message}")
}

Advanced Features

Custom Protocols

// Define custom protocol
val customProtocol = URLProtocol("myapp", 9999)

val customUrl = URLBuilder(
    protocol = customProtocol,
    host = "internal.service",
    path = "/custom/endpoint"
).build()

println(customUrl) // myapp://internal.service:9999/custom/endpoint

URL Templates and Dynamic Building

fun buildApiUrl(
    baseUrl: String,
    version: String,
    resource: String,
    id: String? = null,
    queryParams: Map<String, String> = emptyMap()
): Url {
    return URLBuilder(baseUrl).apply {
        appendPathSegments("api", version, resource)
        id?.let { appendPathSegments(it) }
        queryParams.forEach { (key, value) ->
            parameters.append(key, value)
        }
    }.build()
}

// Usage
val userUrl = buildApiUrl(
    baseUrl = "https://api.example.com",
    version = "v1",
    resource = "users",
    id = "123",
    queryParams = mapOf(
        "include" to "profile",
        "format" to "json"
    )
)