This is a Kotlin Multiplatform library for working with RFC 3986, and is a fork of the Java library.
The original author describes some benefits of using the library over Java's URI library (which could be of interest to JVM/Android consumers) in the readme.
The library offers four key functionalities for robust URI management:
Each feature is designed to handle URIs accurately and effectively, ensuring reliable and precise management across various application contexts.
You can include the library from either Maven Central or Jitpack.
You can include the library in the common source set like this:
dependencies {
implementation("io.github.kotlingeekdev:uri-reference-kmp:1.0")
}Inside your root-level build.gradle(.kts) file, you should add jitpack:
// build.gradle.kts
allprojects {
repositories {
// ...
maven { setUrl("https://jitpack.io") }
}
// ...
}or
// build.gradle
allprojects {
repositories {
// ...
maven { url "https://jitpack.io" }
}
// ...
}In newer projects, you need to also update the settings.gradle(.kts) file's dependencyResolutionManagement block:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' } // <--
}
}
then, in your module's build.gradle(.kts), you need to add:
// build.gradle.kts
dependencies {
//...
implementation("com.github.KotlinGeekDev.uri-reference-kmp:uri-reference-kmp:v1.0")
}
If you're including it in an Android app, you can just add:
// app/build.gradle.kts
dependencies {
//...
implementation("com.github.KotlinGeekDev.uri-reference-kmp:uri-reference-kmp-android:1.0")
}Apache License, Version 2.0
To parse URI references, use URIReference.parse(uriRef: String) or URIReference.parse(uriRef: String, charset: Charset). Below are some examples of using URIReference.parse(uriRef: String).
val uriRef = URIReference.parse("http://example.com/a/b") // Parse.
println(uriRef.toString()) // "http://example.com/a/b"
println(uriRef.isRelativeReference()) // false
println(uriRef.getScheme()) // "http"
println(uriRef.hasAuthority()) // true
println(uriRef.getAuthority().toString()) // "example.com"
println(uriRef.getUserinfo()) // null
println(uriRef.getHost().getType()) // "REGNAME"
println(uriRef.getHost().getValue()) // "example.com"
println(uriRef.getPort()) // -1
println(uriRef.getPath()) // "/a/b"
println(uriRef.getQuery()) // null
println(uriRef.getFragment()) // nullval uriRef = URIReference.parse("//example.com/a/b") // Parse.
println(uriRef.toString()) // "//example.com/a/b"
println(uriRef.isRelativeReference()) // false
println(uriRef.getScheme()) // null
println(uriRef.hasAuthority()) // true
println(uriRef.getAuthority().toString()) // "example.com"
println(uriRef.getUserinfo()) // null
println(uriRef.getHost().getType()) // "REGNAME"
println(uriRef.getHost().getValue()) // "example.com"
println(uriRef.getPort()) // -1
println(uriRef.getPath()) // "/a/b"
println(uriRef.getQuery()) // null
println(uriRef.getFragment()) // nullval uriRef = URIReference.parse("http://101.102.103.104") // Parse.
println(uriRef.toString()) // "http://101.102.103.104"
println(uriRef.isRelativeReference()) // false
println(uriRef.getScheme()) // "http"
println(uriRef.hasAuthority()) // true
println(uriRef.getAuthority().toString()) // "101.102.103.104"
println(uriRef.getUserinfo()) // null
println(uriRef.getHost().getType()) // "IPV4"
println(uriRef.getHost().getValue()) // "101.102.103.104"
println(uriRef.getPort()) // -1
println(uriRef.getPath()) // ""
println(uriRef.getQuery()) // null
println(uriRef.getFragment()) // nullval uriRef = URIReference.parse("http://[2001:0db8:0001:0000:0000:0ab9:C0A8:0102]") // Parse.
println(uriRef.toString()) // "http://[2001:0db8:0001:0000:0000:0ab9:C0A8:0102]"
println(uriRef.isRelativeReference()) // false
println(uriRef.getScheme()) // "http"
println(uriRef.hasAuthority()) // true
println(uriRef.getAuthority().toString()) // "[2001:0db8:0001:0000:0000:0ab9:C0A8:0102]"
println(uriRef.getUserinfo()) // null
println(uriRef.getHost().getType()) // "IPV6"
println(uriRef.getHost().getValue()) // "[2001:0db8:0001:0000:0000:0ab9:C0A8:0102]"
println(uriRef.getPort()) // -1
println(uriRef.getPath()) // ""
println(uriRef.getQuery()) // null
println(uriRef.getFragment()) // nullval uriRef = URIReference.parse("http://[v9.abc:def]") // Parse.
println(uriRef.toString()) // "http://[v9.abc:def]"
println(uriRef.isRelativeReference()) // false
println(uriRef.getScheme()) // "http"
println(uriRef.hasAuthority()) // true
println(uriRef.getAuthority().toString()) // "[v9.abc:def]"
println(uriRef.getUserinfo()) // null
println(uriRef.getHost().getType()) // "IPVFUTURE"
println(uriRef.getHost().getValue()) // "[v9.abc:def]"
println(uriRef.getPort()) // -1
println(uriRef.getPath()) // ""
println(uriRef.getQuery()) // null
println(uriRef.getFragment()) // nullval uriRef = URIReference.parse("http://%65%78%61%6D%70%6C%65.com") // Parse.
println(uriRef.toString()) // "http://%65%78%61%6D%70%6C%65.com"
println(uriRef.isRelativeReference()) // false
println(uriRef.getScheme()) // "http"
println(uriRef.hasAuthority()) // true
println(uriRef.getAuthority().toString()) // "%65%78%61%6D%70%6C%65.com"
println(uriRef.getUserinfo()) // null
println(uriRef.getHost().getType()) // "REGNAME"
println(uriRef.getHost().getValue()) // "%65%78%61%6D%70%6C%65.com"
println(uriRef.getPort()) // -1
println(uriRef.getPath()) // ""
println(uriRef.getQuery()) // null
println(uriRef.getFragment()) // nullWarning
If parsing fails, those methods throws NullPointerException or IllegalArgumentException. See Java doc for more details.
To resolve a relative reference against a URI reference, use resolve(uriRef: String) or resolve(uriRef: URIReference). Below is an example demonstrating how to resolve a relative reference against a base URI.
// A base URI.
val baseUri = URIReference.parse("http://example.com")
// A relative reference.
val relRef = URIReference.parse("/a/b")
// Resolve the relative reference against the base URI.
val resolved = baseUri.resolve(relRef)
println(resolved.toString()) // "http://example.com/a/b"
println(resolved.isRelativeReference()) // false
println(resolved.getScheme()) // "http"
println(resolved.hasAuthority()) // true
println(resolved.getAuthority().toString()) // "example.com"
println(resolved.getUserinfo()) // null
println(resolved.getHost().getType()) // "REGNAME"
println(resolved.getHost().getValue()) // "example.com"
println(resolved.getPort()) // -1
println(resolved.getPath()) // "/a/b"
println(resolved.getQuery()) // null
println(resolved.getFragment()) // nullFor normalization, invoke normalize() on a URIReference instance to normalize.
val normalized = URIReference.parse("hTTp://example.com") // Parse.
.normalize() // Normalize.
println(normalized.toString()) // "http://example.com/"
println(normalized.isRelativeReference()) // false
println(normalized.getScheme()) // "http"
println(normalized.hasAuthority()) // true
println(normalized.getAuthority().toString()) // "example.com"
println(normalized.getUserinfo()) // null
println(normalized.getHost().getType()) // "REGNAME"
println(normalized.getHost().getValue()) // "example.com"
println(normalized.getPort()) // -1
println(normalized.getPath()) // "/"
println(normalized.getQuery()) // null
println(normalized.getFragment()) // nullval normalized = URIReference.parse("http://%65%78%61%6D%70%6C%65.com") // Parse.
.normalize() // Normalize.
println(normalized.toString()) // "http://example.com/"
println(normalized.isRelativeReference()) // false
println(normalized.getScheme()) // "http"
println(normalized.hasAuthority()) // true
println(normalized.getAuthority().toString()) // "example.com"
println(normalized.getUserinfo()) // null
println(normalized.getHost().getType()) // "REGNAME"
println(normalized.getHost().getValue()) // "example.com"
println(normalized.getPort()) // -1
println(normalized.getPath()) // "/"
println(normalized.getQuery()) // null
println(normalized.getFragment()) // nullval normalized = URIReference.parse("http://example.com/a/b/c/../d/") // Parse.
.normalize() // Normalize.
println(normalized.toString()) // "http://example.com/a/b/d/"
println(normalized.isRelativeReference()) // false
println(normalized.getScheme()) // "http"
println(normalized.hasAuthority()) // true
println(normalized.getAuthority().toString()) // "example.com"
println(normalized.getUserinfo()) // null
println(normalized.getHost().getType()) // "REGNAME"
println(normalized.getHost().getValue()) // "example.com"
println(normalized.getPort()) // -1
println(normalized.getPath()) // "/a/b/d/"
println(normalized.getQuery()) // null
println(normalized.getFragment()) // null// Parse a relative reference.
val relRef = URIReference.parse("/a/b/c/../d/")
// Resolve the relative reference against "http://example.com".
// NOTE: Relative references must be resolved before normalization.
val resolved = relRef.resolve("http://example.com")
// Normalize the resolved URI.
val normalized = resolved.normalize()
println(normalized.toString()) // "http://example.com/a/b/d/"
println(normalized.isRelativeReference()) // false
println(normalized.getScheme()) // "http"
println(normalized.hasAuthority()) // true
println(normalized.getAuthority().toString()) // "example.com"
println(normalized.getUserinfo()) // null
println(normalized.getHost().getType()) // "REGNAME"
println(normalized.getHost().getValue()) // "example.com"
println(normalized.getPort()) // -1
println(normalized.getPath()) // "/a/b/d/"
println(normalized.getQuery()) // null
println(normalized.getFragment()) // nullCaution
Relative reference must be resolved before normalization as RFC 3986, 5.2.1 states as below.
RFC 3986, 5.2.1. Pre-parse the Base URI
A URI reference must be transformed to its target URI before it can be normalized.---
To construct URI references, use URIReferenceBuilder class.
val uriRef = URIReferenceBuilder()
.setScheme("http")
.setHost("example.com")
.setPath("/a/b/c")
.appendQueryParam("k1", "v1")
.build()
println(uriRef.toString()) // "http://example.com/a/b/c?k1=v1"
println(uriRef.isRelativeReference()) // false
println(uriRef.getScheme()) // "http"
println(uriRef.hasAuthority()) // true
println(uriRef.getAuthority().toString()) // "example.com"
println(uriRef.getUserinfo()) // null
println(uriRef.getHost().getType()) // "REGNAME"
println(uriRef.getHost().getValue()) // "example.com"
println(uriRef.getPort()) // -1
println(uriRef.getPath()) // "/a/b/c"
println(uriRef.getQuery()) // "k1=v1"
println(uriRef.getFragment()) // nullval uriRef = URIReferenceBuilder()
.fromURIReference("http://example.com/a/b/c?k1=v1")
.appendPath("d", "e", "f")
.appendQueryParam("k2", "v2")
.build()
println(uriRef.toString()) // "http://example.comd/a/b/c/d/e/f?k1=v1&k2=v2"
println(uriRef.isRelativeReference()) // false
println(uriRef.getScheme()) // "http"
println(uriRef.hasAuthority()) // true
println(uriRef.getAuthority().toString()) // "example.com"
println(uriRef.getUserinfo()) // null
println(uriRef.getHost().getType()) // "REGNAME"
println(uriRef.getHost().getValue()) // "example.com"
println(uriRef.getPort()) // -1
println(uriRef.getPath()) // "/a/b/c/d/e/f"
println(uriRef.getQuery()) // "k1=v1&k2=&v2"
println(uriRef.getFragment()) // nullWarning
The current implementation of URIReferenceBuilder class won't throw an exception until build() method is invoked even if invalid input is given since validation for each URI component is performed only when build() is called.
This library designs most classes such as URIReference to be immutable. Here are some examples.
// Example 1: Invoking the "normalize()" method creates a new URIReference instance.
val normalized = URIReference.parse("hTTp://example.com").normalize()
// Example 2: Invoking the "resolve(String uriRef)" method creates a new URIReference instance.
val resolved = URIReference.parse("http://example.com").resolve("/a/b")