# class URI

- URI
- Reference
- Object

##
Overview

This class represents a URI reference as defined by RFC 3986: Uniform Resource Identifier (URI): Generic Syntax.

This class provides constructors for creating URI instances from their components or by parsing their string forms and methods for accessing the various components of an instance.

NOTE To use `URI`, you must explicitly import it with `require "uri"`

Basic example:

    require "uri"

    uri = URI.parse "http://foo.com/posts?id=30&limit=5#time=1305298413"
    # => #<URI:0x1003f1e40 @scheme="http", @host="foo.com", @port=nil, @path="/posts", @query="id=30&limit=5", ... >
    uri.scheme # => "http"
    uri.host   # => "foo.com"
    uri.query  # => "id=30&limit=5"
    uri.to_s   # => "http://foo.com/posts?id=30&limit=5#time=1305298413"

##
Resolution and Relativization

Resolution is the process of resolving one URI against another, base URI. The resulting URI is constructed from components of both URIs in the manner specified by RFC 3986 section 5.2, taking components from the base URI for those not specified in the original. For hierarchical URIs, the path of the original is resolved against the path of the base and then normalized. See `#resolve` for examples.

Relativization is the inverse of resolution as that it procures an URI that resolves to the original when resolved against the base.

For normalized URIs, the following is true:

    a.relativize(a.resolve(b)) # => b
    a.resolve(a.relativize(b)) # => b

This operation is often useful when constructing a document containing URIs that must be made relative to the base URI of the document wherever possible.

#
URL Encoding

This class provides a number of methods for encoding and decoding strings using URL Encoding (also known as Percent Encoding) as defined in RFC 3986 as well as `x-www-form-urlencoded`.

Each method has two variants, one returns a string, the other writes directly to an IO.

- `.decode(string : String, *, plus_to_space : Bool = false) : String`: Decodes a URL-encoded string.
- `.decode(string : String, io : IO, *, plus_to_space : Bool = false) : Nil`: Decodes a URL-encoded string to an IO.
- `.encode_path(string : String) : String`: URL-encodes a string.
- `.encode_path(string : String, io : IO) : Nil`: URL-encodes a string to an IO.
- `.encode_path_segment(string : String) : String`: URL-encodes a string, escaping `/`.
- `.encode_path_segment(string : String, io : IO) : Nil`: URL-encodes a string to an IO, escaping `/`.
- `.decode_www_form(string : String, *, plus_to_space : Bool = true) : String`: Decodes an `x-www-form-urlencoded` string component.
- `.decode_www_form(string : String, io : IO, *, plus_to_space : Bool = true) : Nil`: Decodes an `x-www-form-urlencoded` string component to an IO.
- `.encode_www_form(string : String, *, space_to_plus : Bool = true) : String`: Encodes a string as a `x-www-form-urlencoded` component.
- `.encode_www_form(string : String, io : IO, *, space_to_plus : Bool = true) : Nil`: Encodes a string as a `x-www-form-urlencoded` component to an IO.

`.encode_www_form` encodes white space (`` ) as `+`, while `.encode_path` and `.encode_path_segment` encode it as `%20`. The decode methods differ regarding the handling of `+` characters, respectively.

NOTE `URI::Params` provides a higher-level API for handling `x-www-form-urlencoded` serialized data.

##
Defined in:

uri.cr
uri/encoding.cr
uri/params.cr
uri/punycode.cr
uri/uri_parser.cr

##
Constructors

- .new(scheme : Nil | String = nil, host : Nil | String = nil, port : Int32 | Nil = nil, path : String = "", query : String | Params | Nil = nil, user : Nil | String = nil, password : Nil | String = nil, fragment : Nil | String = nil)
- .parse(raw_url : String) : URI

  Parses the given raw_url into an URI.

##
Class Method Summary

- .decode(string : String, io : IO, *, plus_to_space : Bool = false) : Nil

  URL-decodes a string and writes the result to io.

- .decode(string : String, *, plus_to_space : Bool = false) : String

  URL-decodes string.

- .decode(string : String, io : IO, *, plus_to_space : Bool = false, &) : Nil

  URL-decodes string and writes the result to io.

- .decode_www_form(string : String, io : IO, *, plus_to_space : Bool = true) : Nil

  URL-decodes string as `x-www-form-urlencoded` and writes the result to io.

- .decode_www_form(string : String, *, plus_to_space : Bool = true) : String

  URL-decodes string as `x-www-form-urlencoded`.

- .default_port(scheme : String) : Int32 | Nil

  Returns the default port for the given scheme if known, otherwise returns `nil`.

- .encode(string : String, io : IO, *, space_to_plus : Bool = false) : Nil

  URL-encodes string and writes the result to io.

  DEPRECATED Use `.encode_path` instead.

- .encode(string : String, *, space_to_plus : Bool = false) : String

  URL-encodes string.

  DEPRECATED Use `.encode_path` instead.

- .encode(string : String, io : IO, space_to_plus : Bool = false, &) : Nil

  URL-encodes string and writes the result to an `IO`.

- .encode_path(io : IO, string : String) : Nil

  Encodes string so it can be safely placed as a potentially multi-segmented URI path, replacing special characters with URI escape sequences as needed.

- .encode_path(string : String) : String

  Encodes string so it can be safely placed as a potentially multi-segmented URI path, replacing special characters with URI escape sequences as needed.

- .encode_path_segment(io : IO, string : String) : Nil

  Encodes string so it can be safely placed inside a URI path segment, replacing special characters (including `/`) with URI escape sequences as needed.

- .encode_path_segment(string : String) : String

  Encodes string so it can be safely placed inside a URI path segment, replacing special characters (including `/`) with URI escape sequences as needed.

- .encode_www_form(string : String, io : IO, *, space_to_plus : Bool = true) : Nil

  URL-encodes string as `x-www-form-urlencoded` and writes the result to io.

- .encode_www_form(string : String, *, space_to_plus : Bool = true) : String

  URL-encodes string as `x-www-form-urlencoded`.

- .reserved?(byte) : Bool

  Returns whether given byte is reserved character defined in RFC 3986 §2.2.

- .set_default_port(scheme : String, port : Int32 | Nil) : Nil

  Registers the default port for the given scheme.

- .unreserved?(byte) : Bool

  Returns whether given byte is unreserved character defined in RFC 3986 §2.3.

- .unwrap_ipv6(host) : String

  Unwraps IPv6 address wrapped in square brackets.

##
Instance Method Summary

- #==(other : self)

  Returns `true` if this reference is the same as other.

- #absolute? : Bool

  Returns `true` if URI has a scheme specified.

- #authority(io : IO) : Nil

  Returns the authority component of this URI.

- #authority : String | Nil

  Returns the authority component of this URI.

- #fragment : String | Nil

  Returns the fragment component of the URI.

- #fragment=(fragment : String | Nil)

  Sets the fragment component of the URI.

- #hash(hasher)

  See `Object#hash(hasher)`

- #host : String | Nil

  Returns the host component of the URI.

- #host=(host : String | Nil)

  Sets the host component of the URI.

- #hostname : String | Nil

  Returns the host part of the URI and unwrap brackets for IPv6 addresses.

- #normalize : URI

  Returns a normalized copy of this URI.

- #normalize! : URI

  Normalizes this URI instance.

- #opaque? : Bool

  Returns `true` if this URI is opaque.

- #password : String | Nil

  Returns the password component of the URI.

- #password=(password : String | Nil)

  Sets the password component of the URI.

- #path : String

  Returns the path component of the URI.

- #path=(path : String)

  Sets the path component of the URI.

- #port : Int32 | Nil

  Returns the port component of the URI.

- #port=(port : Int32 | Nil)

  Sets the port component of the URI.

- #query : String | Nil

  Returns the query component of the URI.

- #query=(query : String | Nil)

  Sets the query component of the URI.

- #query_params : URI::Params

  Returns a `URI::Params` of the URI#query.

- #query_params=(params : URI::Params)

  Sets `#query` to stringified params.

- #relative? : Bool

  Returns `true` if URI does not have a scheme specified.

- #relativize(uri : URI | String) : URI

  Relativizes uri against this URI.

- #request_target : String

  Returns the concatenation of `#path` and `#query` as it would be used as a request target in an HTTP request.

- #resolve(uri : URI | String) : URI

  Resolves uri against this URI.

- #scheme : String | Nil

  Returns the scheme component of the URI.

- #scheme=(scheme : String | Nil)

  Sets the scheme component of the URI.

- #to_s(io : IO) : Nil

  Appends a short String representation of this object which includes its class name and its object address.

- #update_query_params(& : URI::Params -> _) : URI

  Yields the value of `#query_params` commits any modifications of the `URI::Params` instance to self.

- #user : String | Nil

  Returns the user component of the URI.

- #user=(user : String | Nil)

  Sets the user component of the URI.

- #userinfo : String | Nil

  Returns the user-information component containing the provided username and password.

### Instance methods inherited from class `Reference`

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s

### Constructor methods inherited from class `Reference`

new new, unsafe_construct(address : Pointer, *args, **opts) : self unsafe_construct

### Class methods inherited from class `Reference`

pre_initialize(address : Pointer) pre_initialize

### Instance methods inherited from class `Object`

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io, root : String)
from_json(string_or_io) from_json, from_yaml(string_or_io : String | IO) from_yaml

### Macros inherited from class `Object`

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

##
Constructor Detail

def self.new(scheme : Nil | String = nil, host : Nil | String = nil, port : Int32 | Nil = nil, path : String = "", query : String | Params | Nil = nil, user : Nil | String = nil, password : Nil | String = nil, fragment : Nil | String = nil) #
def self.parse(raw_url : String) : URI #

Parses the given raw_url into an URI. The raw_url may be relative or absolute.

    require "uri"

    uri = URI.parse("http://crystal-lang.org") # => #<URI:0x1068a7e40 @scheme="http", @host="crystal-lang.org", ... >
    uri.scheme                                 # => "http"
    uri.host                                   # => "crystal-lang.org"

##
Class Method Detail

def self.decode(string : String, io : IO, *, plus_to_space : Bool = false) : Nil #

URL-decodes a string and writes the result to io.

See `.decode(string : String, *, plus_to_space : Bool = false) : String` for details.

def self.decode(string : String, *, plus_to_space : Bool = false) : String #

URL-decodes string.

    require "uri"

    URI.decode("hello%20world!")                                 # => "hello world!"
    URI.decode("put:%20it+%D0%B9")                               # => "put: it+й"
    URI.decode("http://example.com/Crystal%20is%20awesome%20=)") # => "http://example.com/Crystal is awesome =)"

By default, `+` is decoded literally. If plus_to_space is `true`, `+` is decoded as space character (`0x20`). Percent-encoded values such as `%20` and `%2B` are always decoded as characters with the respective codepoint.

    require "uri"

    URI.decode("peter+%2B+paul")                      # => "peter+++paul"
    URI.decode("peter+%2B+paul", plus_to_space: true) # => "peter + paul"

- `.encode` is the reverse operation.
- `.decode_www_form` encodes plus to space by default.

def self.decode(string : String, io : IO, *, plus_to_space : Bool = false, &) : Nil #

URL-decodes string and writes the result to io.

The block is called for each percent-encoded ASCII character and determines whether the value is to be decoded. When the return value is falsey, the character is decoded. Non-ASCII characters are always decoded.

By default, `+` is decoded literally. If plus_to_space is `true`, `+` is decoded as space character (`0x20`).

This method enables some customization, but typical use cases can be implemented by either `.decode(string : String, *, plus_to_space : Bool = false) : String` or `.decode_www_form(string : String, *, plus_to_space : Bool = true) : String`.

def self.decode_www_form(string : String, io : IO, *, plus_to_space : Bool = true) : Nil #

URL-decodes string as `x-www-form-urlencoded` and writes the result to io.

See `self.decode_www_form(string : String, *, plus_to_space : Bool = true) : String` for details.

def self.decode_www_form(string : String, *, plus_to_space : Bool = true) : String #

URL-decodes string as `x-www-form-urlencoded`.

    require "uri"

    URI.decode_www_form("hello%20world!")                           # => "hello world!"
    URI.decode_www_form("put:%20it+%D0%B9")                         # => "put: it й"
    URI.decode_www_form("http://example.com/Crystal+is+awesome+=)") # => "http://example.com/Crystal is awesome =)"

By default, `+` is decoded as space character (`0x20`). If plus_to_space is `false`, `+` is decoded literally as `+`. Percent-encoded values such as `%20` and `%2B` are always decoded as characters with the respective codepoint.

    require "uri"

    URI.decode_www_form("peter+%2B+paul")                       # => "peter + paul"
    URI.decode_www_form("peter+%2B+paul", plus_to_space: false) # => "peter+++paul"

- `.encode_www_form` is the reverse operation.
- `.decode` encodes plus literally by default.

def self.default_port(scheme : String) : Int32 | Nil #

Returns the default port for the given scheme if known, otherwise returns `nil`.

    require "uri"

    URI.default_port "http"  # => 80
    URI.default_port "ponzi" # => nil

def self.encode(string : String, io : IO, *, space_to_plus : Bool = false) : Nil #

URL-encodes string and writes the result to io.

See `.encode(string : String, *, space_to_plus : Bool = false) : String` for details.

DEPRECATED Use `.encode_path` instead.

def self.encode(string : String, *, space_to_plus : Bool = false) : String #

URL-encodes string.

Reserved and unreserved characters are not escaped, so this only modifies some special characters as well as non-ASCII characters. `.reserved?` and `.unreserved?` provide more details on these character classes.

    require "uri"

    URI.encode("hello world!")                             # => "hello%20world!"
    URI.encode("put: it+й")                                # => "put:%20it+%D0%B9"
    URI.encode("http://example.com/Crystal is awesome =)") # => "http://example.com/Crystal%20is%20awesome%20=)"

By default, the space character (`0x20`) is encoded as `%20` and `+` is encoded literally. If space_to_plus is `true`, space character is encoded as `+` and `+` is encoded as `%2B`:

    require "uri"

    URI.encode("peter + paul")                      # => "peter%20+%20paul"
    URI.encode("peter + paul", space_to_plus: true) # => "peter+%2B+paul"

- `.decode` is the reverse operation.
- `.encode_www_form` also escapes reserved characters.

DEPRECATED Use `.encode_path` instead.

def self.encode(string : String, io : IO, space_to_plus : Bool = false, &) : Nil #

URL-encodes string and writes the result to an `IO`.

The block is called for each ascii character (codepoint less than `0x80`) and determines whether the value is to be encoded. When the return value is falsey, the character is encoded. Non-ASCII characters are always encoded.

By default, the space character (`0x20`) is encoded as `%20` and `+` is encoded literally. If space_to_plus is `true`, space character is encoded as `+` and `+` is encoded as `%2B`.

This method enables some customization, but typical use cases can be implemented by either `.encode_path(string : String) : String`, `.encode_path_segment(string : String) : String` or `.encode_www_form(string : String, *, space_to_plus : Bool = true) : String`.

def self.encode_path(io : IO, string : String) : Nil #

Encodes string so it can be safely placed as a potentially multi-segmented URI path, replacing special characters with URI escape sequences as needed.

Unreserved characters such as ASCII letters, digits, and the characters `_.-~` are not encoded, as well as the character `/` which represent a segment separator in hierarchical paths (RFC 3986 §3.3).

    require "uri"

    URI.encode_path("foo/bar/baz")  # => "foo/bar/baz"
    URI.encode_path("hello world!") # => "hello%20world%21"
    URI.encode_path("put: it+й")    # => "put%3A%20it%2B%D0%B9"

- `.decode` is the reverse operation.
- `.encode_path_segment` encodes a single path segment, escaping `/`.

def self.encode_path(string : String) : String #

Encodes string so it can be safely placed as a potentially multi-segmented URI path, replacing special characters with URI escape sequences as needed.

Unreserved characters such as ASCII letters, digits, and the characters `_.-~` are not encoded, as well as the character `/` which represent a segment separator in hierarchical paths (RFC 3986 §3.3).

    require "uri"

    URI.encode_path("foo/bar/baz")  # => "foo/bar/baz"
    URI.encode_path("hello world!") # => "hello%20world%21"
    URI.encode_path("put: it+й")    # => "put%3A%20it%2B%D0%B9"

- `.decode` is the reverse operation.
- `.encode_path_segment` encodes a single path segment, escaping `/`.

def self.encode_path_segment(io : IO, string : String) : Nil #

Encodes string so it can be safely placed inside a URI path segment, replacing special characters (including `/`) with URI escape sequences as needed.

Unreserved characters such as ASCII letters, digits, and the characters `_.-~` are not encoded (see `.unreserved?`).

    require "uri"

    URI.encode_path_segment("foo;bar;baz")  # => "foo%3Bbar%3Bbaz"
    URI.encode_path_segment("foo/bar/baz")  # => "foo%2Fbar%2Fbaz"
    URI.encode_path_segment("foo,bar,baz")  # => "foo%2Cbar%2Cbaz"
    URI.encode_path_segment("hello world!") # => "hello%20world%21"
    URI.encode_path_segment("put: it+й")    # => "put%3A%20it%2B%D0%B9"

- `.decode` is the reverse operation.
- `.encode_path` encodes a path consisting of multiple segments, not escaping `/`.
- `.encode_www_form` escapes space character as `+`.

def self.encode_path_segment(string : String) : String #

Encodes string so it can be safely placed inside a URI path segment, replacing special characters (including `/`) with URI escape sequences as needed.

Unreserved characters such as ASCII letters, digits, and the characters `_.-~` are not encoded (see `.unreserved?`).

    require "uri"

    URI.encode_path_segment("foo;bar;baz")  # => "foo%3Bbar%3Bbaz"
    URI.encode_path_segment("foo/bar/baz")  # => "foo%2Fbar%2Fbaz"
    URI.encode_path_segment("foo,bar,baz")  # => "foo%2Cbar%2Cbaz"
    URI.encode_path_segment("hello world!") # => "hello%20world%21"
    URI.encode_path_segment("put: it+й")    # => "put%3A%20it%2B%D0%B9"

- `.decode` is the reverse operation.
- `.encode_path` encodes a path consisting of multiple segments, not escaping `/`.
- `.encode_www_form` escapes space character as `+`.

def self.encode_www_form(string : String, io : IO, *, space_to_plus : Bool = true) : Nil #

URL-encodes string as `x-www-form-urlencoded` and writes the result to io.

See `.encode_www_form(string : String, *, space_to_plus : Bool = true)` for details.

def self.encode_www_form(string : String, *, space_to_plus : Bool = true) : String #

URL-encodes string as `x-www-form-urlencoded`.

Reserved characters are escaped, unreserved characters are not. `.reserved?` and `.unreserved?` provide more details on these character classes.

    require "uri"

    URI.encode_www_form("hello world!")                             # => "hello+world%21"
    URI.encode_www_form("put: it+й")                                # => "put%3A+it%2B%D0%B9"
    URI.encode_www_form("http://example.com/Crystal is awesome =)") # => "http%3A%2F%2Fexample.com%2FCrystal+is+awesome+%3D%29"

The encoded string returned from this method can be used as name or value components for a `application/x-www-form-urlencoded` format serialization. `URI::Params` provides a higher-level API for this use case.

By default, the space character (`0x20`) is encoded as `+` and `+` is encoded as `%2B`. If space_to_plus is `false`, space character is encoded as `%20` and `'+'` is encoded literally.

    require "uri"

    URI.encode_www_form("peter + paul")                       # => "peter+%2B+paul"
    URI.encode_www_form("peter + paul", space_to_plus: false) # => "peter%20%2B%20paul"

- `.decode_www_form` is the reverse operation.
- `.encode_path` escapes space character as `%20`.

def self.reserved?(byte) : Bool #

Returns whether given byte is reserved character defined in RFC 3986 §2.2.

Reserved characters are ':', '/', '?', '#', '[', ']', '@', '!', '$', '&', "'", '(', ')', '*', '+', ',', ';' and '='.

def self.set_default_port(scheme : String, port : Int32 | Nil) : Nil #

Registers the default port for the given scheme.

If port is `nil`, the existing default port for the scheme, if any, will be unregistered.

    require "uri"

    URI.set_default_port "ponzi", 9999

def self.unreserved?(byte) : Bool #

Returns whether given byte is unreserved character defined in RFC 3986 §2.3.

Unreserved characters are ASCII letters, ASCII digits, `_`, `.`, `-` and `~`.

def self.unwrap_ipv6(host) : String #

Unwraps IPv6 address wrapped in square brackets.

Everything that is not wrapped in square brackets is returned unchanged.

    URI.unwrap_ipv6("[::1]")       # => "::1"
    URI.unwrap_ipv6("127.0.0.1")   # => "127.0.0.1"
    URI.unwrap_ipv6("example.com") # => "example.com"

##
Instance Method Detail

def ==(other : self) #
Description copied from class Reference

Returns `true` if this reference is the same as other. Invokes `same?`.

def absolute? : Bool #

Returns `true` if URI has a scheme specified.

def authority(io : IO) : Nil #

Returns the authority component of this URI. It is formatted as `user:pass@host:port` with missing parts being omitted.

If the URI does not have any authority information, the result is `nil`.

    uri = URI.parse "http://user:pass@example.com:80/path?query"
    uri.authority # => "user:pass@example.com:80"

    uri = URI.parse("/relative")
    uri.authority # => nil

def authority : String | Nil #

Returns the authority component of this URI. It is formatted as `user:pass@host:port` with missing parts being omitted.

If the URI does not have any authority information, the result is `nil`.

    uri = URI.parse "http://user:pass@example.com:80/path?query"
    uri.authority # => "user:pass@example.com:80"

    uri = URI.parse("/relative")
    uri.authority # => nil

def fragment : String | Nil #

Returns the fragment component of the URI.

    require "uri"

    URI.parse("http://foo.com/bar#section1").fragment # => "section1"

def fragment=(fragment : String | Nil) #

Sets the fragment component of the URI.

def hash(hasher) #
Description copied from class Reference

See `Object#hash(hasher)`

def host : String | Nil #

Returns the host component of the URI.

    require "uri"

    URI.parse("http://foo.com").host # => "foo.com"

def host=(host : String | Nil) #

Sets the host component of the URI.

def hostname : String | Nil #

Returns the host part of the URI and unwrap brackets for IPv6 addresses.

    require "uri"

    URI.parse("http://[::1]/bar").hostname # => "::1"
    URI.parse("http://[::1]/bar").host     # => "[::1]"

def normalize : URI #

Returns a normalized copy of this URI.

See `#normalize!` for details.

def normalize! : URI #

Normalizes this URI instance.

The following normalizations are applied to the individual components (if available):

- `#scheme` is lowercased.
- `#host` is lowercased.
- `#port` is removed if it is the `.default_port?` of the scheme.
- `#path` is resolved to a minimal, semantic equivalent representation removing dot segments `/.` and `/..`.

    uri = URI.parse("HTTP://example.COM:80/./foo/../bar/")
    uri.normalize!
    uri # => "http://example.com/bar/"

def opaque? : Bool #

Returns `true` if this URI is opaque.

A URI is considered opaque if it has a `#scheme` but no hierarchical part, i.e. no `#host` and the first character of `#path` is not a slash (`/`).

def password : String | Nil #

Returns the password component of the URI.

    require "uri"

    URI.parse("http://admin:password@foo.com").password # => "password"

def password=(password : String | Nil) #

Sets the password component of the URI.

def path : String #

Returns the path component of the URI.

    require "uri"

    URI.parse("http://foo.com/bar").path # => "/bar"

def path=(path : String) #

Sets the path component of the URI.

def port : Int32 | Nil #

Returns the port component of the URI.

    require "uri"

    URI.parse("http://foo.com:5432").port # => 5432

def port=(port : Int32 | Nil) #

Sets the port component of the URI.

def query : String | Nil #

Returns the query component of the URI.

    require "uri"

    URI.parse("http://foo.com/bar?q=1").query # => "q=1"

def query=(query : String | Nil) #

Sets the query component of the URI.

def query_params : URI::Params #

Returns a `URI::Params` of the URI#query.

    require "uri"

    uri = URI.parse "http://foo.com?id=30&limit=5#time=1305298413"
    uri.query_params # => URI::Params{"id" => ["30"], "limit" => ["5"]}

def query_params=(params : URI::Params) #

Sets `#query` to stringified params.

    require "uri"

    uri = URI.new
    uri.query_params = URI::Params.parse("foo=bar&foo=baz")
    uri.to_s # => "?foo=bar&foo=baz"

def relative? : Bool #

Returns `true` if URI does not have a scheme specified.

def relativize(uri : URI | String) : URI #

Relativizes uri against this URI.

An exact copy of uri is returned if

- this URI or uri are `#opaque?`, or
- the scheme and authority (`#host`, `#port`, `#user`, `#password`) components are not identical.

Otherwise a new relative hierarchical URI is constructed with `#query` and `#fragment` components from uri and with a path component that describes a minimum-difference relative path from `#path` to uri's path.

    URI.parse("http://foo.com/bar/baz").relativize("http://foo.com/quux")         # => "../quux"
    URI.parse("http://foo.com/bar/baz").relativize("http://foo.com/bar/quux")     # => "quux"
    URI.parse("http://foo.com/bar/baz").relativize("http://quux.com")             # => "http://quux.com"
    URI.parse("http://foo.com/bar/baz").relativize("http://foo.com/bar/baz#quux") # => "#quux"

This method is the inverse operation to `#resolve` (see [Resolution and Relativization](#Resolution and Relativization)).

def request_target : String #

Returns the concatenation of `#path` and `#query` as it would be used as a request target in an HTTP request.

If `#path` is empty in an hierarchical URI, `"/"` is used.

    require "uri"

    uri = URI.parse "http://example.com/posts?id=30&limit=5#time=1305298413"
    uri.request_target # => "/posts?id=30&limit=5"

    uri = URI.new(path: "", query: "foo=bar")
    uri.request_target # => "/?foo=bar"

def resolve(uri : URI | String) : URI #

Resolves uri against this URI.

If uri is `#absolute?`, or if this URI is `#opaque?`, then an exact copy of uri is returned.

Otherwise the URI is resolved according to the specifications in RFC 3986 section 5.2.

    URI.parse("http://foo.com/bar/baz").resolve("../quux")         # => "http://foo.com/quux"
    URI.parse("http://foo.com/bar/baz").resolve("/quux")           # => "http://foo.com/quux"
    URI.parse("http://foo.com/bar/baz").resolve("http://quux.com") # => "http://quux.com"
    URI.parse("http://foo.com/bar/baz").resolve("#quux")           # => "http://foo.com/bar/baz#quux"

This method is the inverse operation to `#relativize` (see [Resolution and Relativization](#Resolution and Relativization)).

def scheme : String | Nil #

Returns the scheme component of the URI.

    require "uri"

    URI.parse("http://foo.com").scheme           # => "http"
    URI.parse("mailto:alice@example.com").scheme # => "mailto"

def scheme=(scheme : String | Nil) #

Sets the scheme component of the URI.

def to_s(io : IO) : Nil #
Description copied from class Reference

Appends a short String representation of this object which includes its class name and its object address.

    class Person
      def initialize(@name : String, @age : Int32)
      end
    end

    Person.new("John", 32).to_s # => #<Person:0x10a199f20>

def update_query_params(& : URI::Params -> _) : URI #

Yields the value of `#query_params` commits any modifications of the `URI::Params` instance to self. Returns the modified `URI::Params`

    require "uri"
    uri = URI.parse("http://foo.com?id=30&limit=5#time=1305298413")
    uri.update_query_params { |params| params.delete_all("limit") } # => URI::Params{"id" => ["30"]}

    puts uri.to_s # => "http://foo.com?id=30#time=1305298413"

def user : String | Nil #

Returns the user component of the URI.

    require "uri"

    URI.parse("http://admin:password@foo.com").user # => "admin"

def user=(user : String | Nil) #

Sets the user component of the URI.

def userinfo : String | Nil #

Returns the user-information component containing the provided username and password.

    require "uri"

    uri = URI.parse "http://admin:password@foo.com"
    uri.userinfo # => "admin:password"

The return value is URL encoded (see `#encode_www_form`).