File: building.rst

package info (click to toggle)
python-rfc3986 1.5.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 488 kB
  • sloc: python: 2,950; makefile: 16
file content (184 lines) | stat: -rw-r--r-- 5,691 bytes parent folder | download | duplicates (2)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
===============
 Building URIs
===============

Constructing URLs often seems simple. There are some problems with
concatenating strings to build a URL:

- Certain parts of the URL disallow certain characters

- Formatting some parts of the URL is tricky and doing it manually isn't fun

To make the experience better |rfc3986| provides the
:class:`~rfc3986.builder.URIBuilder` class to generate valid
:class:`~rfc3986.uri.URIReference` instances. The
:class:`~rfc3986.builder.URIBuilder` class will handle ensuring that each
component is normalized and safe for real world use.


Example Usage
=============

.. note::

    All of the methods on a :class:`~rfc3986.builder.URIBuilder` are
    chainable (except :meth:`~rfc3986.builder.URIBuilder.finalize` and
    :meth:`~rfc3986.builder.URIBuilder.geturl` as neither returns a
    :class:`~rfc3986.builder.URIBuilder`).

Building From Scratch
---------------------

Let's build a basic URL with just a scheme and host. First we create an
instance of :class:`~rfc3986.builder.URIBuilder`. Then we call
:meth:`~rfc3986.builder.URIBuilder.add_scheme` and
:meth:`~rfc3986.builder.URIBuilder.add_host` with the scheme and host
we want to include in the URL. Then we convert our builder object into
a :class:`~rfc3986.uri.URIReference` and call
:meth:`~rfc3986.uri.URIReference.unsplit`.

.. doctest::

    >>> from rfc3986 import builder
    >>> print(builder.URIBuilder().add_scheme(
    ...     'https'
    ... ).add_host(
    ...     'github.com'
    ... ).finalize().unsplit())
    https://github.com


Replacing Components of a URI
-----------------------------

It is possible to update an existing URI by constructing a builder from an
instance of :class:`~rfc3986.uri.URIReference` or a textual representation:

.. doctest::

    >>> from rfc3986 import builder
    >>> print(builder.URIBuilder.from_uri("http://github.com").add_scheme(
    ...     'https'
    ... ).finalize().unsplit())
    https://github.com

The Builder is Immutable
------------------------

Each time you invoke a method, you get a new instance of a
:class:`~rfc3986.builder.URIBuilder` class so you can build several different
URLs from one base instance.

.. doctest::

    >>> from rfc3986 import builder
    >>> github_builder = builder.URIBuilder().add_scheme(
    ...     'https'
    ... ).add_host(
    ...     'api.github.com'
    ... )
    >>> print(github_builder.add_path(
    ...     '/users/sigmavirus24'
    ... ).finalize().unsplit())
    https://api.github.com/users/sigmavirus24
    >>> print(github_builder.add_path(
    ...     '/repos/sigmavirus24/rfc3986'
    ... ).finalize().unsplit())
    https://api.github.com/repos/sigmavirus24/rfc3986

Convenient Path Management
--------------------------

Because our builder is immutable, one could use the
:class:`~rfc3986.builder.URIBuilder` class to build a class to make HTTP
Requests that used the provided path to extend the original one.

.. doctest::

    >>> from rfc3986 import builder
    >>> github_builder = builder.URIBuilder().add_scheme(
    ...     'https'
    ... ).add_host(
    ...     'api.github.com'
    ... ).add_path(
    ...     '/users'
    ... )
    >>> print(github_builder.extend_path("sigmavirus24").geturl())
    https://api.github.com/users/sigmavirus24
    >>> print(github_builder.extend_path("lukasa").geturl())
    https://api.github.com/users/lukasa


Convenient Credential Handling
------------------------------

|rfc3986| makes adding authentication credentials convenient. It takes care of
making the credentials URL safe. There are some characters someone might want
to include in a URL that are not safe for the authority component of a URL.

.. doctest::

    >>> from rfc3986 import builder
    >>> print(builder.URIBuilder().add_scheme(
    ...     'https'
    ... ).add_host(
    ...     'api.github.com'
    ... ).add_credentials(
    ...     username='us3r',
    ...     password='p@ssw0rd',
    ... ).finalize().unsplit())
    https://us3r:p%40ssw0rd@api.github.com

Managing Query String Parameters
--------------------------------

Further, |rfc3986| attempts to simplify the process of adding query parameters
to a URL. For example, if we were using Elasticsearch, we might do something
like:

.. doctest::

    >>> from rfc3986 import builder
    >>> print(builder.URIBuilder().add_scheme(
    ...     'https'
    ... ).add_host(
    ...     'search.example.com'
    ... ).add_path(
    ...     '_search'
    ... ).add_query_from(
    ...     [('q', 'repo:sigmavirus24/rfc3986'), ('sort', 'created_at:asc')]
    ... ).finalize().unsplit())
    https://search.example.com/_search?q=repo%3Asigmavirus24%2Frfc3986&sort=created_at%3Aasc

If one also had an existing URL with query string that we merely wanted to
append to, we can also do that with |rfc3986|.

.. doctest::

    >>> from rfc3986 import builder
    >>> print(builder.URIBuilder().from_uri(
    ...    'https://search.example.com/_search?q=repo%3Asigmavirus24%2Frfc3986'
    ... ).extend_query_with(
    ...     [('sort', 'created_at:asc')]
    ... ).finalize().unsplit())
    https://search.example.com/_search?q=repo%3Asigmavirus24%2Frfc3986&sort=created_at%3Aasc

Adding Fragments
----------------

Finally, we provide a way to add a fragment to a URL. Let's build up a URL to
view the section of the RFC that refers to fragments:

.. doctest::

    >>> from rfc3986 import builder
    >>> print(builder.URIBuilder().add_scheme(
    ...     'https'
    ... ).add_host(
    ...     'tools.ietf.org'
    ... ).add_path(
    ...     '/html/rfc3986'
    ... ).add_fragment(
    ...     'section-3.5'
    ... ).finalize().unsplit())
    https://tools.ietf.org/html/rfc3986#section-3.5