lambdaisland/uri

repository·main·Indexed 42 days ago

https://github.com/lambdaisland/uri

A pure Clojure and ClojureScript library for parsing, manipulating, and joining URIs. It provides an RFC-compliant alternative to Java-based URI libraries, supporting cross-platform development including Babashka and ClojureScript. Version 1.19.155.

Tokens
1.4K
Snippets
7
Records
7
Agent score
4%

What's inside lambdaisland/uri

  1. Install lambdaisland/uri

    main

    Add lambdaisland/uri as a dependency to your project. The library is 100% cross-platform (.cljc).

    For deps.edn:

    lambdaisland/uri {:mvn/version "1.19.155"}

    For project.clj:

    [lambdaisland/uri "1.19.155"]
    lambdaisland/uri {:mvn/version "1.19.155"}
  2. Babashka and SCI compatibility caveats

    main

    In Babashka or SCI, overriding Object methods (like toString) or implementing interfaces (like IFn) is not supported. This means standard Clojure idioms for URIs will behave differently:

    1. String conversion: Instead of (str uri), use (uri/uri-str uri).
    2. Map-style access: Instead of using the URI as a function (uri :host), use (:host uri) or (get uri :host).

    | Task | Clojure/ClojureScript | Babashka/SCI | | | :--- | :--- | :--- | | Stringify | (str uri) | (uri/uri-str uri) | | Access Key | (uri :host) | (:host uri) or (get uri :host) |

    ;; Babashka/SCI compatible patterns
    (uri/uri-str uri) ;; "https://example.com"
    (:host uri)       ;; "example.com"
    (get uri :host)   ;; "example.com"
  3. Parse a URI string with `uri`

    main

    Use the uri function to convert a URI string into a lambdaisland.uri.URI record. This record is interface-compatible with Clojure maps, allowing you to use keyword lookups (e.g., (:path uri-instance)) to access components.

    (require '[lambdaisland.uri :refer [uri]])
    
    (uri "//example.com/foo/bar")
    ;;=> #lambdaisland/uri "//example.com/foo/bar"
    
    (:path (uri "http://example.com/foo/bar"))
    ;;=> "/foo/bar"
  4. Join URIs with `join`

    main

    The join function performs RFC-compliant joining of URIs. It treats relative URIs as first-class citizens. Arguments to join can be strings, lambdaisland.uri.URI instances, or any object where (str x) returns a valid URI string (such as java.net.URI).

    (require '[lambdaisland.uri :refer [join uri]])
    
    ;; Joining strings and relative paths
    (join "//example.com/foo/bar" "./~arne/site/" "../foo.png")
    ;;=> #lambdaisland/uri "//example.com/foo/~arne/foo.png"
    
    ;; Joining a java.net.URI with lambdaisland/uri objects
    (join (java.net.URI. "http://example.com/foo/bar") (uri "./~arne/site/") "../foo.png")
    ;;=> #lambdaisland/uri "http://example.com/foo/~arne/foo.png"
  5. Parse query strings into maps with `query-map`

    main

    Use query-map to convert a URI's query string into a Clojure map. You can provide a custom :into argument to control the map type (e.g., using ordered-map from flatland.ordered.map to preserve parameter order).

    (require '[lambdaisland.uri :refer [query-map]])
    
    ;; Basic usage
    (query-map "http://example.com?a=1&b=2")
    ;;=> {:a "1", :b "2"}
    
    ;; Preserving order with ordered-map
    (require '[flatland.ordered.map :refer [ordered-map]])
    (keys (query-map "http://example.com?a=1&b=2&c=3" {:into (ordered-map)}))
    ;;=> (:a :b :c)
  6. Read URI EDN with `edn-readers`

    main

    URI instances are printed with a #lambdaisland/uri reader tag. To deserialize these strings back into URI objects using clojure.edn/read-string, you must provide the lambdaisland.uri/edn-readers map to the :readers option.

    (require '[clojure.edn :as edn]
             '[lambdaisland.uri :refer [uri]])
    
    (edn/read-string
     {:readers lambdaisland.uri/edn-readers}
     "#lambdaisland/uri \"http://example.com/foo/~arne/foo.png\"")
  7. Update URI components using `assoc`

    main

    Since a URI is a record, you can use assoc to update specific parts like :scheme, :user, :password, :host, :port, :path, :query, or :fragment. To convert the updated URI record back into a string, use str.

    (require '[lambdaisland.uri :refer [uri]])
    
    (str
     (assoc (uri "//example.com/foo/bar")
            :scheme "https"
            :user "arne"
            :password "supersecret"
            :host "lambdaisland.com"
            :port "3333"
            :path "/hello/world"
            :query "q=5"
            :fragment "section1"))
    ;;=> "https://arne:supersecret@lambdaisland.com:3333/hello/world?q=5#section1"