Repository: urllib3/urllib3

Issue:
Start using towncrier for tracking changes
This will make sure that we don't miss anything. Asking if anyone on our team has configured towncrier in the past :)

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/urllib3/urllib3/pull/2330?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3) Report
> Merging [#2330](https://codecov.io/gh/urllib3/urllib3/pull/2330?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3) (b0d0888) into [main](https://codecov.io/gh/urllib3/urllib3/commit/21945b84b0707a3143b09ade5c59e8dbf6a69a0f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3) (21945b8) will **decrease** coverage by `0.44%`.
> The diff coverage is `n/a`.

> :exclamation: Current head b0d0888 differs from pull request most recent head a4f8a8d. Consider uploading reports for the commit a4f8a8d to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/urllib3/urllib3/pull/2330/graphs/tree.svg?width=650&height=150&src=pr&token=UYKHB2uXDn&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3)](https://codecov.io/gh/urllib3/urllib3/pull/2330?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3)

```diff
@@             Coverage Diff             @@
##              main    #2330      +/-   ##
===========================================
- Coverage   100.00%   99.55%   -0.45%     
===========================================
  Files           25       25              
  Lines         2457     2454       -3     
===========================================
- Hits          2457     2443      -14     
- Misses           0       11      +11     
```


| [Impacted Files](https://codecov.io/gh/urllib3/urllib3/pull/2330?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3) | Coverage Δ | |
|---|---|---|
| [src/urllib3/util/wait.py](https://codecov.io/gh/urllib3/urllib3/pull/2330/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3#diff-c3JjL3VybGxpYjMvdXRpbC93YWl0LnB5) | `91.11% <0.00%> (-8.89%)` | :arrow_down: |
| [src/urllib3/contrib/socks.py](https://codecov.io/gh/urllib3/urllib3/pull/2330/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3#diff-c3JjL3VybGxpYjMvY29udHJpYi9zb2Nrcy5weQ==) | `97.29% <0.00%> (-2.71%)` | :arrow_down: |
| [src/urllib3/connection.py](https://codecov.io/gh/urllib3/urllib3/pull/2330/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3#diff-c3JjL3VybGxpYjMvY29ubmVjdGlvbi5weQ==) | `98.82% <0.00%> (-1.18%)` | :arrow_down: |
| [src/urllib3/response.py](https://codecov.io/gh/urllib3/urllib3/pull/2330/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3#diff-c3JjL3VybGxpYjMvcmVzcG9uc2UucHk=) | `99.25% <0.00%> (-0.75%)` | :arrow_down: |
| [src/urllib3/\_collections.py](https://codecov.io/gh/urllib3/urllib3/pull/2330/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3#diff-c3JjL3VybGxpYjMvX2NvbGxlY3Rpb25zLnB5) | `99.43% <0.00%> (-0.57%)` | :arrow_down: |
| [src/urllib3/connectionpool.py](https://codecov.io/gh/urllib3/urllib3/pull/2330/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3#diff-c3JjL3VybGxpYjMvY29ubmVjdGlvbnBvb2wucHk=) | `100.00% <0.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/urllib3/urllib3/pull/2330?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/urllib3/urllib3/pull/2330?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3). Last update [21945b8...a4f8a8d](https://codecov.io/gh/urllib3/urllib3/pull/2330?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=urllib3).

pquentin: @sigmavirus24 Thank you for your support, and thanks for mentioning twine! This gave me the good idea or renaming the obscure `newsfragment` directory into `changelog`.
pquentin: > Are we okay to merge now or is another test case required for setting url?

I'm not happy with the way this works in the `if self.retries is not None and self.retries.history:` case. But now that I look at the 1.26.x code, `url` was just not a thing in the past: we had `geturl()`. So maybe it's fine to say that Sphinx is at fault here and should not attach an `url` attribute? (They have a really fast release cycle, and I can probably get that fix in.)
pquentin: Please take another look:

- I rebased to cleanly separate the towncrier and url changes. (Please don't squash.)
- I added a README in the changelog directory, using pytest as an inspiration.
- I addressed Seth's comment.

Patch:
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 1da640f0..c545ef44 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -2,13 +2,13 @@ version: 2
 
 python:
   install:
+    - requirements: docs/requirements.txt
     - method: pip
       path: .
       extra_requirements:
         - brotli
         - secure
         - socks
-    - requirements: docs/requirements.txt
 
 sphinx:
   fail_on_warning: true
diff --git a/CHANGES.rst b/CHANGES.rst
index 4863d465..f49f31a6 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,25 +1,5 @@
-Changes
-=======
-
-
-2.0.0 (unreleased)
-------------------
-
-* ``multipart/form-data`` header parameter formatting matches the WHATWG
-  HTML Standard as of 2021-06-10. Control characters in filenames are no
-  longer percent encoded. #2257
-* ``format_header_param_html5`` and ``format_header_param`` are
-  deprecated names for ``format_multipart_header_param``. #2257
-* The ``RequestField`` ``header_formatter`` parameter is deprecated in
-  favor of overriding the ``_render_part`` method. #2257
-* Make all parameters after `method` and `url` for `urllib3.request()` 
-  keyword only. #2283
-* The ``NewConnectionError.pool`` deprecated and will be removed
-  in a later urllib3 v2.x release. #2271
-
-
 1.26.5 (2021-05-26)
--------------------
+===================
 
 * Fixed deprecation warnings emitted in Python 3.10.
 * Updated vendored ``six`` library to 1.16.0.
@@ -28,14 +8,14 @@ Changes
 
 
 1.26.4 (2021-03-15)
--------------------
+===================
 
 * Changed behavior of the default ``SSLContext`` when connecting to HTTPS proxy
   during HTTPS requests. The default ``SSLContext`` now sets ``check_hostname=True``.
 
 
 1.26.3 (2021-01-26)
--------------------
+===================
 
 * Fixed bytes and string comparison issue with headers (Pull #2141)
 
@@ -45,21 +25,21 @@ Changes
 
 
 1.26.2 (2020-11-12)
--------------------
+===================
 
 * Fixed an issue where ``wrap_socket`` and ``CERT_REQUIRED`` wouldn't
   be imported properly on Python 2.7.8 and earlier (Pull #2052)
 
 
 1.26.1 (2020-11-11)
--------------------
+===================
 
 * Fixed an issue where two ``User-Agent`` headers would be sent if a
   ``User-Agent`` header key is passed as ``bytes`` (Pull #2047)
 
 
 1.26.0 (2020-11-10)
--------------------
+===================
 
 * **NOTE: urllib3 v2.0 will drop support for Python 2**.
   `Read more in the v2.0 Roadmap <https://urllib3.readthedocs.io/en/latest/v2-roadmap.html>`_.
@@ -101,7 +81,7 @@ Changes
 
 
 1.25.11 (2020-10-19)
---------------------
+====================
 
 * Fix retry backoff time parsed from ``Retry-After`` header when given
   in the HTTP date format. The HTTP date was parsed as the local timezone
@@ -114,7 +94,7 @@ Changes
 
 
 1.25.10 (2020-07-22)
---------------------
+====================
 
 * Added support for ``SSLKEYLOGFILE`` environment variable for
   logging TLS session keys with use with programs like
@@ -133,7 +113,7 @@ Changes
 
 
 1.25.9 (2020-04-16)
--------------------
+===================
 
 * Added ``InvalidProxyConfigurationWarning`` which is raised when
   erroneously specifying an HTTPS proxy URL. urllib3 doesn't currently
@@ -157,7 +137,7 @@ Changes
 
 
 1.25.8 (2020-01-20)
--------------------
+===================
 
 * Drop support for EOL Python 3.4 (Pull #1774)
 
@@ -165,7 +145,7 @@ Changes
 
 
 1.25.7 (2019-11-11)
--------------------
+===================
 
 * Preserve ``chunked`` parameter on retries (Pull #1715, Pull #1734)
 
@@ -179,14 +159,14 @@ Changes
 
 
 1.25.6 (2019-09-24)
--------------------
+===================
 
 * Fix issue where tilde (``~``) characters were incorrectly
   percent-encoded in the path. (Pull #1692)
 
 
 1.25.5 (2019-09-19)
--------------------
+===================
 
 * Add mitigation for BPO-37428 affecting Python <3.7.4 and OpenSSL 1.1.1+ which
   caused certificate verification to be enabled when using ``cert_reqs=CERT_NONE``.
@@ -194,7 +174,7 @@ Changes
 
 
 1.25.4 (2019-09-19)
--------------------
+===================
 
 * Propagate Retry-After header settings to subsequent retries. (Pull #1607)
 
@@ -213,7 +193,7 @@ Changes
 
 
 1.25.3 (2019-05-23)
--------------------
+===================
 
 * Change ``HTTPSConnection`` to load system CA certificates
   when ``ca_certs``, ``ca_cert_dir``, and ``ssl_context`` are
@@ -223,7 +203,7 @@ Changes
 
 
 1.25.2 (2019-04-28)
--------------------
+===================
 
 * Change ``is_ipaddress`` to not detect IPvFuture addresses. (Pull #1583)
 
@@ -232,7 +212,7 @@ Changes
 
 
 1.25.1 (2019-04-24)
--------------------
+===================
 
 * Add support for Google's ``Brotli`` package. (Pull #1572, Pull #1579)
 
@@ -240,7 +220,7 @@ Changes
 
 
 1.25 (2019-04-22)
------------------
+=================
 
 * Require and validate certificates by default when using HTTPS (Pull #1507)
 
@@ -267,12 +247,12 @@ Changes
 * Implemented a more efficient ``HTTPResponse.__iter__()`` method. (Issue #1483)
 
 1.24.3 (2019-05-01)
--------------------
+===================
 
 * Apply fix for CVE-2019-9740. (Pull #1591)
 
 1.24.2 (2019-04-17)
--------------------
+===================
 
 * Don't load system certificates by default when any other ``ca_certs``, ``ca_certs_dir`` or
   ``ssl_context`` parameters are specified.
@@ -283,7 +263,7 @@ Changes
 
 
 1.24.1 (2018-11-02)
--------------------
+===================
 
 * Remove quadratic behavior within ``GzipDecoder.decompress()`` (Issue #1467)
 
@@ -291,7 +271,7 @@ Changes
 
 
 1.24 (2018-10-16)
------------------
+=================
 
 * Allow key_server_hostname to be specified when initializing a PoolManager to allow custom SNI to be overridden. (Pull #1449)
 
@@ -317,7 +297,7 @@ Changes
 
 
 1.23 (2018-06-04)
------------------
+=================
 
 * Allow providing a list of headers to strip from requests when redirecting
   to a different host. Defaults to the ``Authorization`` header. Different
@@ -345,7 +325,7 @@ Changes
 
 
 1.22 (2017-07-20)
------------------
+=================
 
 * Fixed missing brackets in ``HTTP CONNECT`` when connecting to IPv6 address via
   IPv6 proxy. (Issue #1222)
@@ -362,7 +342,7 @@ Changes
 
 
 1.21.1 (2017-05-02)
--------------------
+===================
 
 * Fixed SecureTransport issue that would cause long delays in response body
   delivery. (Pull #1154)
@@ -376,7 +356,7 @@ Changes
 
 
 1.21 (2017-04-25)
------------------
+=================
 
 * Improved performance of certain selector system calls on Python 3.5 and
   later. (Pull #1095)
@@ -409,7 +389,7 @@ Changes
 
 
 1.20 (2017-01-19)
------------------
+=================
 
 * Added support for waiting for I/O using selectors other than select,
   improving urllib3's behaviour with large numbers of concurrent connections.
@@ -446,13 +426,13 @@ Changes
 
 
 1.19.1 (2016-11-16)
--------------------
+===================
 
 * Fixed AppEngine import that didn't function on Python 3.5. (Pull #1025)
 
 
 1.19 (2016-11-03)
------------------
+=================
 
 * urllib3 now respects Retry-After headers on 413, 429, and 503 responses when
   using the default retry logic. (Pull #955)
@@ -472,7 +452,7 @@ Changes
 
 
 1.18.1 (2016-10-27)
--------------------
+===================
 
 * CVE-2016-9015. Users who are using urllib3 version 1.17 or 1.18 along with
   PyOpenSSL injection and OpenSSL 1.1.0 *must* upgrade to this version. This
@@ -487,7 +467,7 @@ Changes
 
 
 1.18 (2016-09-26)
------------------
+=================
 
 * Fixed incorrect message for IncompleteRead exception. (Pull #973)
 
@@ -501,7 +481,7 @@ Changes
 
 
 1.17 (2016-09-06)
------------------
+=================
 
 * Accept ``SSLContext`` objects for use in SSL/TLS negotiation. (Issue #835)
 
@@ -547,7 +527,7 @@ Changes
 
 
 1.16 (2016-06-11)
------------------
+=================
 
 * Disable IPv6 DNS when IPv6 connections are not possible. (Issue #840)
 
@@ -572,13 +552,13 @@ Changes
 
 
 1.15.1 (2016-04-11)
--------------------
+===================
 
 * Fix packaging to include backports module. (Issue #841)
 
 
 1.15 (2016-04-06)
------------------
+=================
 
 * Added Retry(raise_on_status=False). (Issue #720)
 
@@ -602,7 +582,7 @@ Changes
 
 
 1.14 (2015-12-29)
------------------
+=================
 
 * contrib: SOCKS proxy support! (Issue #762)
 
@@ -611,13 +591,13 @@ Changes
 
 
 1.13.1 (2015-12-18)
--------------------
+===================
 
 * Fixed regression in IPv6 + SSL for match_hostname. (Issue #761)
 
 
 1.13 (2015-12-14)
------------------
+=================
 
 * Fixed ``pip install urllib3[secure]`` on modern pip. (Issue #706)
 
@@ -634,7 +614,7 @@ Changes
 
 
 1.12 (2015-09-03)
------------------
+=================
 
 * Rely on ``six`` for importing ``httplib`` to work around
   conflicts with other Python 3 shims. (Issue #688)
@@ -647,7 +627,7 @@ Changes
 
 
 1.11 (2015-07-21)
------------------
+=================
 
 * When ``ca_certs`` is given, ``cert_reqs`` defaults to
   ``'CERT_REQUIRED'``. (Issue #650)
@@ -692,7 +672,7 @@ Changes
   (Issue #674)
 
 1.10.4 (2015-05-03)
--------------------
+===================
 
 * Migrate tests to Tornado 4. (Issue #594)
 
@@ -708,7 +688,7 @@ Changes
 
 
 1.10.3 (2015-04-21)
--------------------
+===================
 
 * Emit ``InsecurePlatformWarning`` when SSLContext object is missing.
   (Issue #558)
@@ -729,7 +709,7 @@ Changes
 
 
 1.10.2 (2015-02-25)
--------------------
+===================
 
 * Fix file descriptor leakage on retries. (Issue #548)
 
@@ -741,7 +721,7 @@ Changes
 
 
 1.10.1 (2015-02-10)
--------------------
+===================
 
 * Pools can be used as context managers. (Issue #545)
 
@@ -755,7 +735,7 @@ Changes
 
 
 1.10 (2014-12-14)
------------------
+=================
 
 * Disabled SSLv3. (Issue #473)
 
@@ -787,7 +767,7 @@ Changes
 
 
 1.9.1 (2014-09-13)
-------------------
+==================
 
 * Apply socket arguments before binding. (Issue #427)
 
@@ -808,7 +788,7 @@ Changes
 
 
 1.9 (2014-07-04)
-----------------
+================
 
 * Shuffled around development-related files. If you're maintaining a distro
   package of urllib3, you may need to tweak things. (Issue #415)
@@ -845,7 +825,7 @@ Changes
 
 
 1.8.3 (2014-06-23)
-------------------
+==================
 
 * Fix TLS verification when using a proxy in Python 3.4.1. (Issue #385)
 
@@ -867,13 +847,13 @@ Changes
 
 
 1.8.2 (2014-04-17)
-------------------
+==================
 
 * Fix ``urllib3.util`` not being included in the package.
 
 
 1.8.1 (2014-04-17)
-------------------
+==================
 
 * Fix AppEngine bug of HTTPS requests going out as HTTP. (Issue #356)
 
@@ -884,7 +864,7 @@ Changes
 
 
 1.8 (2014-03-04)
-----------------
+================
 
 * Improved url parsing in ``urllib3.util.parse_url`` (properly parse '@' in
   username, and blank ports like 'hostname:').
@@ -936,7 +916,7 @@ Changes
 
 
 1.7.1 (2013-09-25)
-------------------
+==================
 
 * Added granular timeout support with new ``urllib3.util.Timeout`` class.
   (Issue #231)
@@ -945,7 +925,7 @@ Changes
 
 
 1.7 (2013-08-14)
-----------------
+================
 
 * More exceptions are now pickle-able, with tests. (Issue #174)
 
@@ -984,7 +964,7 @@ Changes
 
 
 1.6 (2013-04-25)
-----------------
+================
 
 * Contrib: Optional SNI support for Py2 using PyOpenSSL. (Issue #156)
 
@@ -1044,7 +1024,7 @@ Changes
 
 
 1.5 (2012-08-02)
-----------------
+================
 
 * Added ``urllib3.add_stderr_logger()`` for quickly enabling STDERR debug
   logging in urllib3.
@@ -1069,7 +1049,7 @@ Changes
 
 
 1.4 (2012-06-16)
-----------------
+================
 
 * Minor AppEngine-related fixes.
 
@@ -1081,7 +1061,7 @@ Changes
 
 
 1.3 (2012-03-25)
-----------------
+================
 
 * Removed pre-1.0 deprecated API.
 
@@ -1100,13 +1080,13 @@ Changes
 
 
 1.2.2 (2012-02-06)
-------------------
+==================
 
 * Fixed packaging bug of not shipping ``test-requirements.txt``. (Issue #47)
 
 
 1.2.1 (2012-02-05)
-------------------
+==================
 
 * Fixed another bug related to when ``ssl`` module is not available. (Issue #41)
 
@@ -1115,7 +1095,7 @@ Changes
 
 
 1.2 (2012-01-29)
-----------------
+================
 
 * Added Python 3 support (tested on 3.2.2)
 
@@ -1141,7 +1121,7 @@ Changes
 
 
 1.1 (2012-01-07)
-----------------
+================
 
 * Refactored ``dummyserver`` to its own root namespace module (used for
   testing).
@@ -1158,7 +1138,7 @@ Changes
 
 
 1.0.2 (2011-11-04)
-------------------
+==================
 
 * Fixed typo in ``VerifiedHTTPSConnection`` which would only present as a bug if
   you're using the object manually. (Thanks pyos)
@@ -1171,14 +1151,14 @@ Changes
 
 
 1.0.1 (2011-10-10)
-------------------
+==================
 
 * Fixed a bug where the same connection would get returned into the pool twice,
   causing extraneous "HttpConnectionPool is full" log warnings.
 
 
 1.0 (2011-10-08)
-----------------
+================
 
 * Added ``PoolManager`` with LRU expiration of connections (tested and
   documented).
@@ -1201,13 +1181,13 @@ Changes
 
 
 0.4.1 (2011-07-17)
-------------------
+==================
 
 * Minor bug fixes, code cleanup.
 
 
 0.4 (2011-03-01)
-----------------
+================
 
 * Better unicode support.
 * Added ``VerifiedHTTPSConnection``.
@@ -1216,13 +1196,13 @@ Changes
 
 
 0.3.1 (2010-07-13)
-------------------
+==================
 
 * Added ``assert_host_name`` optional parameter. Now compatible with proxies.
 
 
 0.3 (2009-12-10)
-----------------
+================
 
 * Added HTTPS support.
 * Minor bug fixes.
@@ -1231,13 +1211,13 @@ Changes
 
 
 0.2 (2008-11-17)
-----------------
+================
 
 * Added unit tests.
 * Bug fixes.
 
 
 0.1 (2008-11-16)
-----------------
+================
 
 * First release.
diff --git a/changelog/.gitignore b/changelog/.gitignore
new file mode 100644
index 00000000..f935021a
--- /dev/null
+++ b/changelog/.gitignore
@@ -0,0 +1,1 @@
+!.gitignore
diff --git a/changelog/2257.removal.rst b/changelog/2257.removal.rst
new file mode 100644
index 00000000..fa70cec4
--- /dev/null
+++ b/changelog/2257.removal.rst
@@ -0,0 +1,9 @@
+``multipart/form-data`` header parameter formatting matches the WHATWG
+HTML Standard as of 2021-06-10. Control characters in filenames are no
+longer percent encoded.
+
+``format_header_param_html5`` and ``format_header_param`` are
+deprecated names for ``format_multipart_header_param``.
+
+The ``RequestField`` ``header_formatter`` parameter is deprecated in
+favor of overriding the ``_render_part`` method.
diff --git a/changelog/2271.removal.rst b/changelog/2271.removal.rst
new file mode 100644
index 00000000..2a3d627c
--- /dev/null
+++ b/changelog/2271.removal.rst
@@ -0,0 +1,2 @@
+The ``NewConnectionError.pool`` attribute was deprecated and will be
+removed in a later urllib3 v2.x release.
diff --git a/changelog/2283.feature.rst b/changelog/2283.feature.rst
new file mode 100644
index 00000000..4719468a
--- /dev/null
+++ b/changelog/2283.feature.rst
@@ -0,0 +1,2 @@
+Make all parameters after ``method`` and ``url`` for
+`urllib3.request()` keyword only.
diff --git a/changelog/README.rst b/changelog/README.rst
new file mode 100644
index 00000000..8f650f70
--- /dev/null
+++ b/changelog/README.rst
@@ -0,0 +1,27 @@
+This directory contains "newsfragments" which are short files that contain a small
+**ReST**-formatted text that will be added to ``CHANGES.rst``.
+
+The ``CHANGELOG`` will be read by **users**, so this description should be aimed to
+urllib3 users instead of describing internal changes which are only relevant to the
+developers.
+
+Make sure to use full sentences in the **past tense** and use punctuation, examples::
+
+    Added support for HTTPS proxies contacting HTTPS servers.
+
+    Upgraded ``urllib3.utils.parse_url()`` to be RFC 3986 compliant.
+
+Each file should be named like ``<ISSUE>.<TYPE>.rst``, where ``<ISSUE>`` is an issue
+number, and ``<TYPE>`` is one of the `five towncrier default types
+<https://towncrier.readthedocs.io/en/actual-freaking-docs/quickstart.html#creating-news-fragments>`.
+
+So for example: ``123.feature.rst``, ``456.bugfix.rst``.
+
+If your pull request fixes an issue, use that number here. If there is no issue, then
+after you submit the pull request and get the pull request number you can add a
+changelog using that instead.
+
+You can also run ``nox -s docs`` to build the documentation with the draft changelog
+(``docs/_build/html/changelog.html``) if you want to get a preview of how your change
+will look in the final release notes. You can also see a preview from the Read the Docs
+check in pull requests.
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 530df679..0cea1269 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -9,3 +9,5 @@ trustme==0.7.0
 cryptography==3.4.7
 python-dateutil==2.8.1
 requests
+# https://github.com/twisted/towncrier/pull/356
+git+https://github.com/pquentin/towncrier.git@stop-writing-title-twice
diff --git a/docs/changelog.rst b/docs/changelog.rst
new file mode 100644
index 00000000..26a877a0
--- /dev/null
+++ b/docs/changelog.rst
@@ -0,0 +1,5 @@
+=========
+Changelog
+=========
+
+.. include:: ../CHANGES.rst
diff --git a/docs/conf.py b/docs/conf.py
index baa0f7c7..e7c792fb 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -9,6 +9,18 @@ from datetime import date
 root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
 sys.path.insert(0, root_path)
 
+# https://docs.readthedocs.io/en/stable/builds.html#build-environment
+if "READTHEDOCS" in os.environ:
+    import glob
+
+    if glob.glob("../changelog/*.*.rst"):
+        print("-- Found changes; running towncrier --", flush=True)
+        import subprocess
+
+        subprocess.run(
+            ["towncrier", "--yes", "--date", "not released yet"], cwd="..", check=True
+        )
+
 import urllib3
 
 # -- General configuration -----------------------------------------------------
diff --git a/docs/contributing.rst b/docs/contributing.rst
index bdb1232d..0c946ba3 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -15,6 +15,8 @@ If you wish to add a new feature or fix a bug:
    as expected.
 #. Format your changes with black using command `$ nox -rs format` and lint your
    changes using command `nox -rs lint`.
+#. Add a changelog entry using `towncrier
+   <https://towncrier.readthedocs.io/en/actual-freaking-docs/quickstart.html#creating-news-fragments>`__.
 #. Send a pull request and bug the maintainer until it gets merged and published.
 
 
@@ -134,8 +136,10 @@ A release candidate can be created by any contributor.
 
 - Announce intent to release on Discord, see if anyone wants to include last minute
   changes.
-- Update ``CHANGES.rst`` and ``urllib3/__init__.py`` with the proper version number
-  and commit the changes to a ``release-X.Y.Z`` branch.
+- Run ``towncrier build`` to update ``CHANGES.rst`` with the release notes, adjust as
+  necessary.
+- Update ``urllib3/__init__.py`` with the proper version number
+- Commit the changes to a ``release-X.Y.Z`` branch.
 - Create a pull request and append ``&expand=1&template=release.md`` to the URL before
   submitting in order to include our release checklist in the pull request description.
 - Follow the checklist!
diff --git a/docs/index.rst b/docs/index.rst
index 870d765a..9f7eb9ba 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -13,6 +13,7 @@ urllib3
    advanced-usage
    reference/index
    contributing
+   changelog
 
 urllib3 is a powerful, *user-friendly* HTTP client for Python.
 :ref:`Much of the Python ecosystem already uses <who-uses>` urllib3 and you should too.
diff --git a/src/urllib3/response.py b/src/urllib3/response.py
index 44387563..1407aa15 100644
--- a/src/urllib3/response.py
+++ b/src/urllib3/response.py
@@ -199,6 +199,7 @@ class BaseHTTPResponse(io.IOBase):
         version: int,
         reason: Optional[str],
         decode_content: bool,
+        request_url: Optional[str],
     ) -> None:
         if isinstance(headers, HTTPHeaderDict):
             self.headers = headers
@@ -208,6 +209,7 @@ class BaseHTTPResponse(io.IOBase):
         self.version = version
         self.reason = reason
         self.decode_content = decode_content
+        self.request_url: Optional[str]
 
         self.chunked = False
         tr_enc = self.headers.get("transfer-encoding", "").lower()
@@ -412,6 +414,7 @@ class HTTPResponse(BaseHTTPResponse):
             version=version,
             reason=reason,
             decode_content=decode_content,
+            request_url=request_url,
         )
 
         self.retries = retries
@@ -423,7 +426,10 @@ class HTTPResponse(BaseHTTPResponse):
         self._original_response = original_response
         self._fp_bytes_read = 0
         self.msg = msg
-        self._request_url = request_url
+        if self.retries is not None and self.retries.history:
+            self._request_url = self.retries.history[-1].redirect_location
+        else:
+            self._request_url = request_url
 
         if body and isinstance(body, (str, bytes)):
             self._body = body
@@ -901,10 +907,11 @@ class HTTPResponse(BaseHTTPResponse):
         If the request that generated this response redirected, this method
         will return the final redirect location.
         """
-        if self.retries is not None and self.retries.history:
-            return self.retries.history[-1].redirect_location
-        else:
-            return self._request_url
+        return self._request_url
+
+    @url.setter
+    def url(self, url: str) -> None:
+        self._request_url = url
 
     def __iter__(self) -> Iterator[bytes]:
         buffer: List[bytes] = []
diff --git a/towncrier.toml b/towncrier.toml
new file mode 100644
index 00000000..e1be27a5
--- /dev/null
+++ b/towncrier.toml
@@ -0,0 +1,7 @@
+[tool.towncrier]
+package = "urllib3"
+package_dir = "src"
+filename = "CHANGES.rst"
+directory = "changelog"
+issue_format = "`#{issue} <https://github.com/urllib3/urllib3/issues/{issue}>`__"
+title_format = "{version} ({project_date})"


Test patch:
diff --git a/test/test_response.py b/test/test_response.py
index 578d12e9..8be12d9b 100644
--- a/test/test_response.py
+++ b/test/test_response.py
@@ -869,6 +869,14 @@ class TestResponse:
         resp = HTTPResponse(fp, request_url=request_url)
         assert resp.geturl() == request_url
 
+    def test_url(self):
+        fp = BytesIO(b"")
+        request_url = "https://example.com"
+        resp = HTTPResponse(fp, request_url=request_url)
+        assert resp.url == request_url
+        resp.url = "https://anotherurl.com"
+        assert resp.url == "https://anotherurl.com"
+
     def test_geturl_retries(self):
         fp = BytesIO(b"")
         resp = HTTPResponse(fp, request_url="http://example.com")