# (lispkit url)

Library `(lispkit url)` defines procedures for creating and decomposing URLs. URLs are represented as strings which conform to the syntax of a generic URI. Each URI consists of five components organized hierarchically in order of decreasing significance from left to right:

```
url = scheme ":" ["//" authority] path ["?" query] ["#" fragment]
```

A component is *undefined* if it has an associated delimiter and the delimiter does not appear in the URI. The scheme and path components are always defined. A component is *empty* if it has no characters. The scheme component is always non-empty. The authority component consists of several *subcomponents*:

```
authority = [userinfo "@"] host [":" port]
userinfo = username [":" password]
```

The following illustration shows all components:

![URL Syntax](https://x-devonthink-item/54C1ABDC-D6F4-4E5A-B96B-CF58D5C1E5DC)

## Generic URLs

**(url?&#x20;*****obj*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">

Returns `#t` if *obj* is a string containing a valid URL; `#f` otherwise.

**(make-url&#x20;*****proto*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(make-url&#x20;*****proto scheme*****)**\
\&#xNAN;**(make-url&#x20;*****proto scheme auth*****)**\
\&#xNAN;**(make-url&#x20;*****proto scheme auth path*****)**\
\&#xNAN;**(make-url&#x20;*****proto scheme auth path query*****)**\
\&#xNAN;**(make-url&#x20;*****proto scheme auth path query fragment*****)**

Returns a string representing the URL defined by merging the given URL components with URL prototype *proto*. *proto* is either `#f` (no prototype) or it is a string which is interpreted as a partially defined URL. The URL components provided as arguments of `make-url` overwrite the respective components of *proto*. If a URL component such as *scheme*, *auth*, *path*, etc. is set to `#f`, no changes are made to the respective component of *proto*. If they are set to `#t`, then the respective component in *proto* is removed. If a non-boolean value is provided, it replaces the respective value in *proto*. The result of applying all given URL components to *proto* is returned as the result of `make-url`. The result is not guaranteed to be a valid URL. It could, for instance, be used as a prototype for other `make-url` calls. If it is not possible to return a result that can be parsed back into a URL prototype, `#f` is returned.

*scheme* is a string defining the URL scheme. *auth* is defining the URL authority. The following formats are supported for *auth*:

* `host`: A simple string defines the host of the URL without port.
* `(host)`: A list with one element has the same effect than just using string `host` alone.
* `(host port)`: Specifies both the host of the URL as a string followed by the port of the URL as a fixnum.
* `(user host port)`: Defines the username as a string followed by the host of the URL as a string followed by a port number.
* `(user passwd host port)`: The username followed by a password, followed by a hostname followed by a port number. The first three elements of the list are strings, the last element is a number.

If a list is used to specify the URL authority, again `#f` and `#t` can be used to either not modify the respective authority component from *proto* or to remove it. *path* and *fragment* define a path or fragment of a URL as a string. *query* defines the query component of a URL using two possible formats:

* `query`: A simple string defining the full query component of the URL
* `((name . value) ...)`: An association list of query items consisting of name/value pairs of strings provides a structured representation of a query. It gets automatically mapped to a query string in which items are represented in the form `name=value`, separated by `&`.

If the URL extensibility mechanism via prototype *proto* is not used and it is the goal to defined a valid URL, then using procedures `url` and `url-copy` should be preferred over using `make-url`.

```scheme
(make-url #f "https" "lisppad.app")
  ⇒  "https://lisppad.app"
(make-url #f "https" "lisppad.app" "/libraries/lispkit")
  ⇒  "https://lisppad.app/libraries/lispkit"
(make-url #f "https" "lisppad.app" "/libraries/lispkit"
          '(("lang" . "en")("c" . "US")))
  ⇒  "https://lisppad.app/libraries/lispkit?lang=en&c=US"
```

**(url)**     \[procedure]\
\&#xNAN;**(url&#x20;*****scheme*****)**\
\&#xNAN;**(url&#x20;*****scheme auth*****)**\
\&#xNAN;**(url&#x20;*****scheme auth path*****)**\
\&#xNAN;**(url&#x20;*****scheme auth path query*****)**\
\&#xNAN;**(url&#x20;*****scheme auth path query fragment*****)**

Returns a string representing the URL defined by the given URL components. Providing `#f` for a component means the component does not exist. *scheme* is a string defining the URL scheme. *auth* is defining the URL authority supporting the following formats: `host`, `(host)`, `(host port)`, `(user host port)`, and `(user passwd host port)`. *path* and *fragment* define a path or fragment of a URL as a string. *query* defines the query component of a URL either as a query string or an association list of query items consisting of name/value pairs of strings.

`(url scheme ...)` is similar to `(make-url #f scheme ...)`, but it guarantees that the result is a valid URL. Invalid combinations of URL components result in procedure `url` returning `#f`.

**(url-copy&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-copy&#x20;*****url scheme*****)**\
\&#xNAN;**(url-copy&#x20;*****url scheme auth*****)**\
\&#xNAN;**(url-copy&#x20;*****url scheme auth path*****)**\
\&#xNAN;**(url-copy&#x20;*****url scheme auth path query*****)**\
\&#xNAN;**(url-copy&#x20;*****url scheme auth path query fragment*****)**

Returns a new string representing the URL defined by merging the given URL components with URL prototype *url*. *url* is a string which is interpreted as a partially defined URL. The URL components provided as arguments of `url-copy` overwrite the respective components of *url*. If a URL component such as *scheme*, *auth*, *path*, etc. is set to `#f`, no changes are made to the respective component of *proto*. If they are set to `#t`, then the respective component in *proto* is removed. If a non-boolean value is provided, it replaces the respective value in *url*. The result of applying all given URL components to *url* is returned as the result of `url-copy` if it constitutes a valid URL, otherwise `#f` is returned.

*scheme* is a string defining the URL scheme. *auth* is defining the URL authority supporting the following formats: `host`, `(host)`, `(host port)`, `(user host port)`, and `(user passwd host port)`. *path* and *fragment* define a path or fragment of a URL as a string. *query* defines the query component of a URL either as a query string or an association list of query items consisting of name/value pairs of strings.

**(url-scheme&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">

Returns the scheme of the URL string *url*.

**(url-authority&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-authority&#x20;*****url url-encoded?*****)**

Returns the authority of the URL string *url* as a list of four components: username, password, host and port. URL components that do not exist are represented as `#f`. If *url-encoded?* is provided and set to true, then the authority components are returned in percent-encoded form.

**(url-user&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-user&#x20;*****url url-encoded?*****)**

Returns the user name of the URL string *url* as a string, or `#f` if there is no user name defined. If *url-encoded?* is provided and set to true, then the user name is returned in percent-encoded form.

**(url-password&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-password&#x20;*****url url-encoded?*****)**

Returns the password of the URL string *url* as a string, or `#f` if there is no password defined. If *url-encoded?* is provided and set to true, then the password is returned in percent-encoded form.

**(url-host&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-host&#x20;*****url url-encoded?*****)**

Returns the host of the URL string *url* as a string, or `#f` if there is no host defined. If *url-encoded?* is provided and set to true, then the host is returned in percent-encoded form.

**(url-port&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">

Returns the port of the URL string *url* as a fixnum, or `#f` if there is no port defined.

**(url-path&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-path&#x20;*****url url-encoded?*****)**

Returns the path of the URL string *url* as a string, or `#f` if there is no path defined. If *url-encoded?* is provided and set to true, then the path is returned in percent-encoded form.

**(url-query&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-query&#x20;*****url url-encoded?*****)**

Returns the query of the URL string *url* as a string, or `#f` if there is no query defined. If *url-encoded?* is provided and set to true, then the query is returned in percent-encoded form.

**(url-query-items&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">

Returns the query of the URL string *url* as an association list of string pairs, mapping URL query parameters to values. `#f` is returned, if the query cannot be parsed.

**(url-fragment&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-fragment&#x20;*****url url-encoded?*****)**

Returns the fragment of the URL string *url* as a string, or `#f` if there is no fragment defined. If *url-encoded?* is provided and set to true, then the fragment is returned in percent-encoded form.

**(url-format&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-format&#x20;*****url schc*****)**\
\&#xNAN;**(url-format&#x20;*****url schc usrc*****)**\
\&#xNAN;**(url-format&#x20;*****url schc usrc passc*****)**\
\&#xNAN;**(url-format&#x20;*****url schc usrc passc hostc*****)**\
\&#xNAN;**(url-format&#x20;*****url schc usrc passc hostc portc*****)**\
\&#xNAN;**(url-format&#x20;*****url schc usrc passc hostc portc pathc*****)**\
\&#xNAN;**(url-format&#x20;*****url schc usrc passc hostc portc pathc qc*****)**\
\&#xNAN;**(url-format&#x20;*****url schc usrc passc hostc portc pathc qc fragc*****)**

Formats the given URL string *url* using the provided component-level configurations *schc*, *usrc*, *passc*, *hostc*, *portc*, *pathc*, *qc*, and *fragc*, and returns the result as a string. Each configuration has one of the following forms:

* `#f`: The component is omitted in the formatted URL.
* `#t`: The component is always included in the formatted URL.
* `"..."`: The component is omitted if the component of *url* matches the string.
* `("..." ...)` or `("..." ... . #t)`: The component is omitted if the list contains a string matching the component of *url*.
* `("..." ... . #f)`: The component is only displayed if the list contains a string matching the component of *url*.
* `("..." ... . comp)` where *comp* is a symbol: The component is omitted if the list contains a string matching the component specified via *comp* of *url*. The following specifiers can be used: `scheme`, `user`, `password`, `host`, `port`, `path`, `query`, and `fragment`. The component is only displayed if the list contains a string matching the component specified via *comp* of *url*. The following specifiers can be used: `scheme?`, `user?`, `password?`, `host?`, `port?`, `path?`, `query?`, and `fragment?`.

```scheme
(url-format "http://x@lisppad.app:80/index.html?lang=en"
  #t #f #f #t "80" '("/index.html" "/index.htm") #t)
  ⇒  "http://lisppad.app?lang=en"
```

**(url-parse&#x20;*****str*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-parse&#x20;*****str schs*****)**\
\&#xNAN;**(url-parse&#x20;*****str schs usrs*****)**\
\&#xNAN;**(url-parse&#x20;*****str schs usrs pass*****)**\
\&#xNAN;**(url-parse&#x20;*****str schs usrs pass ports*****)**\
\&#xNAN;**(url-parse&#x20;*****str schs usrs pass hosts ports*****)**\
\&#xNAN;**(url-parse&#x20;*****str schs usrs pass hosts ports paths*****)**\
\&#xNAN;**(url-parse&#x20;*****str schs usrs pass hosts ports paths qs*****)**\
\&#xNAN;**(url-parse&#x20;*****str schs usrs pass hosts ports paths qs frags*****)**

Parses a string *str* using the provided component-level parsing settings *schs*, *usrs*, *pass*, *hosts*, *ports*, *paths*, *qs*, and *frags*, and returns the result as a string. Each setting has one of the following forms:

* `#f`: The component is optional.
* `#t`: The component is required.
* `"..."` or number: The component is optional and if it is missing, this string or number is used as a default.

```scheme
(url-parse " http://lisppad.app:80?lang=en ok")
  ⇒  "http://lisppad.app:80?lang=en"
(url-parse " http://lisppad.app/?lang=en ok"
  #t #f #f #t 80 #t #f "target")
  ⇒  "http://lisppad.app:80/?lang=en#target"
```

## File URLs

**(file-url?&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(file-url?&#x20;*****url dir?*****)**

If *dir?* is not provided, `file-url?` returns `#t` if *obj* is a string containing a valid file URL; `#f` otherwise. If *dir?* is provided and set to true, `file-url?` returns `#t` if *obj* is a string containing a valid file URL and the file URL refers to a directory; `#f` otherwise. If *dir?* is provided and set to `#f`, `file-url?` returns `#t` if *obj* is a string containing a valid file URL and the file URL refers to a regular file; `#f` otherwise.

**(file-url&#x20;*****path*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(file-url&#x20;*****path base*****)**\
\&#xNAN;**(file-url&#x20;*****path base expand?*****)**

Returns a file URL string for the given file *path*. If file URL *base* is provided, *path* is considered to be relative to *base*. If *base* is not provided or set to `#f` and *path* is a relative path, it is considered relative to the current directory. If *expand?* is given and set to true, symbolic links are getting resolved in the resulting file URL.

**(file-url-standardize&#x20;*****url*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(file-url-standardize&#x20;*****url expand?*****)**

Returns a standardized version of file URL *url*. If *expand?* is given and set to true, symbolic links are getting resolved in the resulting file URL.

## URL encoding

**(url-encode&#x20;*****str*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-encode&#x20;*****str allowed-char*****)**\
\&#xNAN;**(url-encode&#x20;*****str allowed-char force?*****)**

Returns a URL/percent-encoded version of the string *str*. *allowed-char* defines the characters that are exempted from the encoding. By default, *allowed-char* corresponds to all characters that are allowed to be unencoded in URL queries. Argument *allowed-char* can either be:

* `#f`: All characters get encoded
* `#t`: The default characters are allowed to be unencoded.
* Symbols `user`, `password`, `host`, `path`, `query`, `fragment`: The characters that are allowed in the respective URL components.
* String: All characters included in the string are allowed to be unencoded.
* Character set: All characters included in the character set (as defined by library `(lispkit char-set)` are allowed to be unencoded.

If argument *force?* is set to `#t`, it is guaranteed that `url-encode` returns a string. If argument *force?* is set to `#f` (the default), then `url-encode` might return `#f` if encoding fails.

**(url-decode&#x20;*****str*****)**     <img src="https://1467949168-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fna2foeoaXHYkSD3fhs0t%2Fuploads%2Fgit-blob-d20368c588cfbb523beb2fae4f8be0f8ef011884%2Fproc.png?alt=media" alt="" data-size="line">\
\&#xNAN;**(url-decode&#x20;*****str force?*****)**

Returns a decoded version of the URL/percent-encoded string *str*. If argument *force?* is set to `#t`, it is guaranteed that `url-decode` returns a string. If argument *force?* is set to `#f` (the default), then `url-decode` might return `#f` if decoding fails.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.lisppad.app/libraries/lispkit/lispkit-url.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
