aboutsummaryrefslogtreecommitdiff
path: root/docs/requests/uri.rst
blob: 17e0a2c284b2bed126823025e70d1001abde23e9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
URIs
====

A request can only be sent if the request method & URI are defined. To represent URIs, sttp comes with a ``Uri`` case class, which captures all of the parts of an address.

To specify the request method and URI, use one of the methods on the request description corresponding to the name of the method: ``.post``, ``.get``, ``.put`` etc. All of them accept a single parameter, the URI to which the request should be send, and yield a request description which, when sent, will use the given address (these methods only modify the request description; they don't send the requests).

The ``Uri`` class is immutable, and can be constructed by hand, but in many cases the URI interpolator will be useful.

URI interpolator
----------------

Using the URI interpolator it's possible to conveniently create ``Uri`` instances, for example::

  import com.softwaremill.sttp._
  
  val user = "Mary Smith"
  val filter = "programming languages"
  
  val endpoint: Uri = uri"http://example.com/$user/skills?filter=$filter"

  assert(endpoint.toString == "http://example.com/Mary%20Smith/skills?filter=programming+languages")

Note the ``uri`` prefix before the string and the standard Scala string-embedding syntax (``$user``, ``$filter``).

Any values embedded in the URI will be URL-encoded, taking into account the context (e.g., the whitespace in ``user`` will be %-encoded as ``%20D``, while the whitespace in ``filter`` will be query-encoded as ``+``). 

All components of the URI can be embedded from values: scheme, username/password, host, port, path, query and fragment.

Optional values
---------------

The URI interpolator supports optional values for hosts (subdomains), query parameters and the fragment. If the value is ``None``, the appropriate URI component will be removed. For example::

  val v1 = None
  val v2 = Some("v2")
  
  val u1 = uri"http://example.com?p1=$v1&p2=v2"
  assert(u1.toString == "http://example.com?p2=v2")
  
  val u2 = uri"http://$v1.$v2.example.com"
  assert(u2.toString == "http://v2.example.com")
  
  val u3 = uri"http://example.com#$v1"
  assert(u3.toString == "http://example.com")

Maps and sequences
------------------

Maps, sequences of tuples and sequences of values can be embedded in the query part. They will be expanded into query parameters. Maps and sequences of tuples can also contain optional values, for which mappings will be removed if ``None``.

For example::

  val ps = Map("p1" -> "v1", "p2" -> "v2")
  val u4 = uri"http://example.com?$ps&p3=p4"
  assert(u4.toString == "http://example.com?p1=v1&p2=v2&p3=p4")

Sequences in the host part will be expanded to a subdomain sequence.

Special cases
-------------

If a string containing the protocol is embedded *as the very beginning*, it will not be escaped, allowing to embed entire addresses as prefixes, e.g.: ``uri"$endpoint/login"``, where ``val endpoint = "http://example.com/api"``.

This is useful when a base URI is stored in a value, and can then be used as a base for constructing URIs.

All features combined
---------------------

A fully-featured example::

  import com.softwaremill.sttp._
  val secure = true
  val scheme = if (secure) "https" else "http"
  val subdomains = List("sub1", "sub2")
  val vx = Some("y z")
  val params = Map("a" -> 1, "b" -> 2)
  val jumpTo = Some("section2")
  uri"$scheme://$subdomains.example.com?x=$vx&$params#$jumpTo"
  
  // generates:
  // https://sub1.sub2.example.com?x=y+z&a=1&b=2#section2