Commit Graph

583 Commits

Author SHA1 Message Date
Sergio Benitez 5d31ad4efb Update 'cookie' to 0.18. 2023-09-28 23:50:29 -07:00
Sergio Benitez f41474dd61 Fix broken links between codegen and http crates.
Also resolves link warnings emitted by rustdoc.

Closes #2594
2023-09-20 17:17:22 -07:00
Sergio Benitez c337f75f32 Fix 'get_pending()' docs, functionality.
The `get_pending()` method now properly decrypts private cookies that were
present in the jar originally.

Resolves #2591.
2023-08-10 16:22:28 -04:00
Sergio Benitez c2936fcb1e Update 'yansi' to 1.0.0-rc. 2023-07-11 13:18:35 -07:00
Sergio Benitez e3f1b53efa Update 'state' to 0.6. 2023-05-25 11:54:27 -07:00
Sergio Benitez b6b060f75c Document built-in data guards. 2023-05-18 18:22:40 -07:00
Sergio Benitez 29cd271f8a Only extract needed values in 'async_main'.
Previously, `async_main` would extract a full `Config`. This mean that values
like `address` were read and parsed even when they were unused. Should they
exist and be malformed, a configuration error would needlessly arise.

This commit fixes this by only extract values that are subsequently used.
2023-05-18 17:33:57 -07:00
Sergio Benitez f1f533c1e5 Improve and fix panic in 'AdHoc::normalizer()'.
The normalizer now handles more cases.
2023-05-05 11:41:44 -07:00
Sergio Benitez 311a82e3d7 Add 'Error::pretty_print()'. 2023-05-05 11:41:10 -07:00
Sergio Benitez 615e70fdad Log config provenance in debug.
This helps identify configuration issues by printing the source of every
configuration value used by Rocket.
2023-05-04 18:32:27 -07:00
Sergio Benitez db535812b0 Factor out 'Catcher' rank computation. 2023-05-04 18:32:25 -07:00
Sergio Benitez d24b5d4d6d Handle more cases in 'AdHoc::normalizer()'.
The compatibility normalizer previously missed or was overly egregious
in several cases. This commit resolves those issue. In particular:

  * Only request URIs that would not match any route are normalized.

  * Synthetic routes are added to the igniting `Rocket` so that requests
    with URIs of the form `/foo` match routes with URIs of the form
    `/foo/<b..>`, as they did prior to the trailing slash overhaul.

Tests are added for all of these cases.
2023-05-04 17:30:37 -07:00
Sergio Benitez 541952bc58 Paint route URI query parts yellow. 2023-05-04 17:30:23 -07:00
Sergio Benitez 56cf905c6e Introduce more flexible mounting.
Prior to this commit, a route with a URI of `/` could not be mounted in
such a way that the resulting effective URI contained a trailing slash.
This commit changes the semantics of mounting so that mounting such a
route to a mount point with a trailing slash yields an effective URI
with a trailing slash. When mounted to points without a trailing slash,
the effective URI does not have a trailing slash.

This commit also introduces the `Route::rebase()` and
`Catcher::rebase()` methods for easier rebasing of existing routes and
catchers.

Finally, this commit improves logging such that mount points of `/`
are underlined in the logs.

Tests and docs were added and modified as necessary.

Resolves #2533.
2023-05-03 20:03:45 -07:00
Sergio Benitez 9b0564ed27 Tidy custom forward status changes, update docs. 2023-04-11 12:55:57 -07:00
Benedikt Weber 055ad107df Allow status customization in 'Forward' outcomes.
Prior to this commit, all forward outcomes resulted in a 404. This
commit changes request and data guards so that they are able to provide
a `Status` on `Forward` outcomes. The router uses this status, if the
final outcome is to forward, to identify the catcher to invoke.

The net effect is that guards can now customize the status code of a
forward and thus the error catcher invoked if the final outcome of a
request is to forward.

Resolves #1560.
2023-04-11 12:47:20 -07:00
Sergio Benitez b61ac6eb18 Expose 'Route', 'Catcher' collision and matching.
This commit exposes four new methods:

  * `Route::collides_with(&Route)`
  * `Route::matches(&Request)`
  * `Catcher::collides_with(&Catcher)`
  * `Catcher::matches(Status, &Request)`

Each method checks the corresponding condition: whether two routes
collide, whether a route matches a request, whether two catchers
collide, and whether a catcher matches an error arising from a request.

This functionality is used internally by Rocket to make routing
decisions. By exposing these methods, external libraries can use
guaranteed consistent logic to check the same routing conditions.

Resolves #1561.
2023-04-10 22:00:54 -07:00
Sergio Benitez 0c80f7d9e0 Return 'Path' from 'Catcher::base()'. 2023-04-10 13:42:20 -07:00
Sergio Benitez c13a6c6a79 Emit warning when 'String' is used as a parameter.
The warning is only emitted when Rocket is compiled in debug.
2023-04-10 13:38:51 -07:00
Sergio Benitez 3a44b1b28e Hide 'RouteUri' fields to ensure URI coherence.
Prior to this commit, several `RouteUri` fields were public, allowing
those values to be changed at will. These changes were at times not
reflected by the rest of the library, meaning that the values in the
route URI structure for a route became incoherent with the reflected
values. This commit makes all fields private, forcing all changes to go
through methods that can ensure coherence. All values remain accessible
via getter methods.
2023-04-10 13:26:54 -07:00
Sergio Benitez 51ed332127 Make trailing slashes significant during routing.
This commit modifies request routing in a backwards incompatible manner.
The change is summarized as: trailing slashes are now significant and
never transparently disregarded. This has the following implications,
all representing behavior that differs from that before this change:

  * Route URIs with trailing slashes (`/foo/`, `/<a>/`) are legal.
  * A request `/foo/` is routed to route `/foo/` but not `/foo`.
  * Similarly, a request `/bar/` is routed to `/<a>/` but not `/<a>`.
  * A request `/bar/foo` is not routed to `/<a>/<b>/<c..>`.

A new `AdHoc::uri_normalizer()` fairing was added that recovers the
previous behavior.

In addition to the above, the `Options::NormalizeDirs` `FileServer`
option is now enabled by default to remain consistent with the above
changes and reduce breaking changes at the `FileServer` level.
2023-04-10 12:40:39 -07:00
Sergio Benitez 908a918e8b Fuzz to validate routing collision safety.
The fuzzing target introduced in this commit attemps to assert
"collision safety". Formally, this is the property that:

  matches(request, route) := request is matched to route
  collides(route1, route2) := there is a a collision between routes

  forall requests req. !exist routes r1, r2 s.t.
    matches(req, r1) AND matches(req, r2) AND not collides(r1, r2)

Alternatively:

  forall requests req, routes r1, r2.
    matches(req, r1) AND matches(req, r2) => collides(r1, r2)

The target was run for 20 CPU hours without failure.
2023-04-07 20:27:56 -07:00
Sergio Benitez ac0a77bae2 Allow dynamic parameters to match empty segments.
The net effect of this commit is three-fold:

  * A request to `/` now matches `/<a>`. `/foo/` matches `/<a>/<b>`.
  * A segment matched to a dynamic parameter may be empty.
  * A request to `/foo/` no longer matches `/foo` or `/<a>`. Instead,
    such a request would match `/foo/<a>` or `/foo/`.

The `&str` and `String` parameter guards were updated to reflect this
change: they now error, with a newly introduced error type `Empty` in
the `rocket::error` module, when the parameter is empty. As this was the
only built-in parameter guard that would be effected by this change (all
other guards already required nonempty parameters to succeed), the
majority of applications will see no effect as a result.

For applications wanting the previous functionality, a new
`AdHoc::uri_normalizer()` fairing was introduced.
2023-04-07 20:00:09 -07:00
Sergio Benitez 0a56312607 Implement more conservative URI normalization.
* Trailing slashes are now allowed in all normalized URI paths, except
    for route attribute URIs: `/foo/` is considered normalized.
  * Query parts of URIs may now be empty: `/foo?` and `/foo/?` are now
    considered normalized.
  * The `base` field of `Catcher` is now only accessible via a new
    getter method: `Catcher::base()`.
  * `RawStr::split()` returns a `DoubleEndedIterator`.
  * Introduced a second normalization for `Origin`, "nontrailing", and
    associated methods: `Origin::normalize_nontrailing()`, and
    `Origin::is_normalized_nontrailing()`.
  * Added `Origin::has_trailing_slash()`.
  * The `Segments<Path>` iterator will now return an empty string if
    there is a trailing slash in the referenced path.
  * `Segments::len()` is now `Segments::num()`.
  * Added `RawStr::trim()`.

Resolves #2512.
2023-04-07 19:59:57 -07:00
Sergio Benitez a82508b403 Set 'Secure' cookie flag by default under TLS.
If TLS is enabled and active, Rocket will now set the `Secure` cookie
attribute by default.

Resolves #2425.
2023-04-05 13:15:24 -07:00
Sergio Benitez 89534129de Add 'TempFile::open()' to stream its data.
Resolves #2296.
2023-04-05 12:45:48 -07:00
Sergio Benitez c48ce64a77 Standardize 'response::status' responders.
This commit modifies all of the non-empty responders in the
`response::status` module so that they look like `Status<R>(pub R)`.
Prior to this commit, some responders looked like this, while others
contained an `Option<R>`.

Resolves #2351.
2023-04-05 10:51:05 -07:00
Sergio Benitez 03433c10ea Allow specifying 'Status' in custom form errors.
Resolves #1694.
2023-04-05 09:56:49 -07:00
Sergio Benitez c3520fb4a1 Pin I/O handlers. Allow 'FnOnce' in 'ws' handlers.
This modifies the 'IoHandler::io()' method so that it takes a
'Pin<Box<Self>>', allowing handlers to move internally and assume that
the data is pinned.

The change is then used in the 'ws' contrib crate to allow 'FnOnce'
handlers instead of 'FnMut'. The net effect is that streams, such as
those crated by 'Stream!', are now allowed to move internally.
2023-04-04 15:33:46 -07:00
Sergio Benitez 5e7a75e1a5 Use 'parking_lot' 'Mutex' in fairing's 'Once'. 2023-04-04 15:11:09 -07:00
Sergio Benitez 887558be60 Emit warnings when data limits are reached.
Aid in debugging incorrectly configured data limits.
2023-04-03 13:27:33 -07:00
Sergio Benitez aa6ad7030a Allow setting mTLS certificates on local 'Client'.
This allows testing with client certificates.

Co-authored-by: Brett Buford <blbuford@gmail.com>
2023-03-31 11:13:40 -07:00
Sergio Benitez 64a7bfb37c Fix header lookups for connection upgrades. 2023-03-30 16:08:14 -07:00
Sergio Benitez 2a63b1a41f Downgrade I/O stream closing to warning.
Since active I/O streams will be closed by graceful shutdown, an error,
as was previously emitted, was necessarily alarmist. This reduces the
severity of the log message to a warning.
2023-03-30 12:46:34 -07:00
Sergio Benitez d97c83d7e0 Finalize support for external connection upgrades. 2023-03-29 17:06:08 -07:00
Mai-Lapyst 19e7e82fd6 Initial connection upgrade API implementation. 2023-03-29 17:06:04 -07:00
Sergio Benitez 372e9671eb Clarify 'Responder' async I/O usage in docs.
Resolves #2286.
2023-03-26 19:32:49 -07:00
Sergio Benitez 91f6288ea4 New version: 0.5.0-rc.3.
New contrib versions: 0.1.0-rc.3.
2023-03-23 16:56:17 -07:00
Sergio Benitez 14b8a082b4 Fix doc re-export inlines in crate root. 2023-03-23 16:33:11 -07:00
inyourface34456 0e6b786096 Fix typo in docs.
Fixes #2734.
2023-03-23 16:27:08 -07:00
Sergio Benitez 219a8a5468 Fix a bunch of typos. 2023-03-23 16:27:08 -07:00
badoken 569bc09a1d Support raw byte slices '&[u8]' in form fields.
Resolves #2148.
2023-03-23 15:31:24 -07:00
Unpublished 2f74380d69 Replace 'atty' with 'is-terminal'. 2023-03-23 14:57:54 -07:00
Dinu Blanovschi b556ec1bba Impl 'Fairing' for 'Arc<dyn Fairing>'. 2023-03-23 14:57:54 -07:00
Beep LIN 78e6e55aa2 Fix typo: 'FromFrom' -> 'FromForm'. 2023-03-23 14:57:54 -07:00
Sergio Benitez 0a0f540988 Support TLS keys in SEC1 format. 2023-03-23 14:57:54 -07:00
Kian-Meng Ang 06d255b52b Fix a whole bunch of typos.
Found via `codespell -L crate,ser,fo,noo,nd,cappable,pard,te,ans`.
2023-03-23 14:57:54 -07:00
Paul Weaver 825dd04ec6 Fix doc typo: "gleaming" -> "gleaning". 2023-03-23 14:57:54 -07:00
Sergio Benitez 0ed6d82d10 Defend against configured known secret keys.
This is a two-prong effort. First, we warn on launch if a known key is
used. Second, we document using invalid keys where possible.

Co-authored-by: Jonas Møller <jonas@moesys.no>
2023-03-23 14:57:54 -07:00
Riley Patterson 01663ed47c Fix 'msgpack' module feature enabling docs. 2023-03-23 14:57:54 -07:00
Alexander van Ratingen 2191369b37 Fix typos in docs. 2023-03-23 14:57:54 -07:00
Sergio Benitez 1edfa15d52 Fix several broken rustdoc links. 2023-03-23 14:57:54 -07:00
Sergio Benitez 9377af5978 Make real IP header configurable via 'ip_header'.
Adds an `ip_header` configuration parameter that allows modifying the
header Rocket attempts to use to retrieve the "real IP" address of the
client via `Request` methods like `client_ip()`. Additionally allows
disabling the use of any such header.
2023-03-20 12:57:21 -07:00
Sergio Benitez 1ed7a6e77e Fix log indentation.
Regression introduced in 885cdfd6 resulted in items in logs messages not
being properly indented.
2022-11-08 14:55:30 -08:00
Sergio Benitez 885cdfd61c Always log launch message.
Users experience confusion when the server appears to do "nothing" when
compiled in release mode. In reality, the server has started, but it
offers no indication in that direction via log message. Often users
misconfigure the port or address, but that information isn't displayed.

This commit makes it such that only the final "Rocket has launched!"
log message is displayed, which includes the listening address, port,
and protocol.
2022-08-30 13:51:23 -07:00
Sergio Benitez c08c39e16f Implement 'FromForm' for 'Arc<T>'. 2022-08-30 13:51:18 -07:00
Kevin Wang f7e703bc5e Fix 'Limits' deserialization.
Fixes #2268.
2022-08-01 13:11:02 -07:00
Sergio Benitez 8e8dfc7d45 Clarify built-in request guard implementations. 2022-07-17 18:45:11 -07:00
Sergio Benitez 30b8a77fc9 Avoid dropping 'Error' inside '#[launch]' future.
Due to tokio-rs/tokio#4780, a panicking top-level future combined with
an uncooperative background task prevents runtime shutdown. To avoid
this in the case of `Rocket::launch()` returning an `Error`, which
panics on drop if it isn't inspected, we return the `Result` to the
caller (i.e., `main`) instead of the `block_on` future. This prevent the
panic from occuring inside of the `block_on` future and so the runtime
terminates even with uncooperative I/O.
2022-06-20 23:49:41 -07:00
Sergio Benitez 04819d8cfd Add pool retrieval to sync_db_pools.
Generates a new method on attributed types, `pool()`, which returns an
opaque reference to a type that can be used to get pooled connections.

Also adds a code-generated example to the crate docs which includes
real, proper function signatures and fully checked examples.

Resolves #1884.
Closes #1972.
2022-05-24 16:47:09 -07:00
Matthew Pomes 5cb70ec58c Salvage everything viable from bad requests.
Co-authored-by: Sergio Benitez <sb@sergio.bz>
2022-05-23 23:47:53 -07:00
Matthew Pomes 47946cc55c Add 'max_blocking' threads config value. 2022-05-23 21:55:16 -07:00
Sergio Benitez 907af10ea4 Tolerate more timing issues in SSE heartbeat test. 2022-05-23 16:36:06 -07:00
Matthew Pomes f21da79f44 Make 'form::ErrorKind' 'From' impl const generic.
Converts an older style array impl to one that uses const generics,
allowing any array length, not just a few sizes.
2022-05-19 18:17:06 -07:00
Sergio Benitez 26b58846a7 Mark fns returning 'Rocket<Build>' 'must_use'.
Remove 'must_use' on the generic 'Rocket<P>', which was overly
conservative. This change, in effect, marks only 'Rocket<Build>'
'must_use', which is a much more precise implementation of the intended
safety guard.
2022-05-19 10:45:24 -07:00
Sergio Benitez bf2bd0e9ed Impl 'Responder' for 'Box<T: Responder + Sized>'.
In other words, allow boxing sized responders.

Resolves #1999.
2022-05-10 15:48:40 -05:00
Dimitri Sabadie c17cc9d23f Fix typo in 'Rocket' docs: iterior -> interior. 2022-05-10 15:08:03 -05:00
Sergio Benitez 4dcd92837f New version: 0.5.0-rc.2.
New contrib versions: 0.1.0-rc.2.
2022-05-09 06:32:46 -05:00
Sergio Benitez 58b96b8e94 Update CHANGELOG for rc.2, missing rc.1 changes.
Closes #1923.
2022-05-09 01:30:57 -05:00
Sergio Benitez 4c8bd61c4f Unhide 'http' exports that shouldn't be hidden. 2022-05-08 01:08:22 -05:00
Sergio Benitez 46c441ad8b Add 'rocket::execute()'.
The function allows executing arbitrary futures, including Rocket's
`launch()` future, on Rocket's async runtime.

Resolves #1881.
2022-05-07 15:54:21 -05:00
Sergio Benitez 7908dc43ca Introduce shutdown fairings.
Also adds 'Client::terminate()' to run graceful shutdown in testing.

Resolves #1707.
2022-05-07 06:12:32 -05:00
Sergio Benitez 0ba56ccbb3 Revamp shutdown to recover shutdown 'Rocket'.
The core improvement is that `Rocket::launch()` now resolves to
`Ok(Rocket<Ignite>)` on nominal shutdown. Furthermore, shutdown never
terminates the running process.

Other changes directly related to shutdown:

  * Runtime worker thread names are now irrelevant to graceful shutdown.
  * `ErrorKind::Runtime` was removed; `ErrorKind::Shutdown` was added.
  * The `force` config value is only read from the default provider.
  * If `force`, Rocket's constructed async runtime is terminated.

Other related changes:

  * The exported `hyper` module docs properly reflect public re-exports.
2022-05-07 06:12:24 -05:00
Sergio Benitez 761ffb009e Add clarity around 'serde' re-exports.
Closes #2038.
2022-05-06 04:38:27 -05:00
Marc-Stefan Cassola a9452c6fa4 Fix 'FromRequest' docs typo: 'request' -> 'route'. 2022-05-05 08:02:32 -05:00
Sergio Benitez 38e43d0840 Improve and clarify 'Rocket' phase docs. 2022-05-04 12:40:20 -07:00
Sergio Benitez 1586ef9572 Downgrade URI discord debug assertion to warning.
Closes #1831.
2022-05-04 09:44:26 -07:00
Sergio Benitez 07460df279 Rework TLS listener/connection implementations.
The previous implementation allowed a trivial DoS attack in which the
client need simply maintain open connections with incomplete handshakes.
This commit resolves that by allowing a server worker to progress as
soon as a TCP connection has been established. This comes at the expense
of a more complex implementation necessitated by deficiencies in Hyper.

Potentially resolves #2118.
2022-05-03 13:56:25 -07:00
Sergio Benitez e9d46b917e Fully 'drop()' I/O struct in 'CancellableIo'.
This should improve the reliability of graceful shutdown.
2022-05-03 13:55:43 -07:00
Sergio Benitez bf84b1cdb5 Enable TCP_NODELAY on TCP-based connections.
We may want a more fine-grained approach to immediately transmitting
application data, but Hyper does not yet expose a suitable API.

Resolves #2062.
2022-04-28 13:22:06 -07:00
Sergio Benitez 6fc24789e9 Fix SSE heartbeat so it never interrupts events.
Previously, the heartbeat message, in its raw form, was ":\n\n". This
commit changes the message to be ":\n".

The former message, when parsed as Server-Sent Events, contained an
empty comment (as desired) _and_ a new line (erroneously). The new line
resulted in emitting any event that was presently being emitted, even if
it wasn't complete. That is, emitting an event partly, such as the
event's data but not its name. Removing the extra new line resolves this
issue and ensures that events aren't interrupted by the heartbeat.

Fixes #2152.
2022-04-27 13:59:03 -07:00
Sergio Benitez 810f472524 Update 'uuid' to 1.0. 2022-04-26 22:04:47 -07:00
Sergio Benitez 6bdd2f8186 Consider form parsing strategy for 'Vec', 'Map'.
Prior to this commit, 'Vec', 'HashMap', and 'BTreeMap' would parse
leniently irrespetive of the requested parsing strategy. This commit
changes their behavior so that the parsing strategy is respected.

Resolves #2131.
2022-04-21 08:17:58 -07:00
Konrad Borowski 7bbe0457a5 Use new 2021 edition functionality.
* Remove `TryInto` and `TryFrom` imports.
  * Replace `IntoIter::new()` with `.into_iter()`.
2022-04-19 18:35:55 -07:00
Sergio Benitez 38bd5663c2 Use non-deprecated 'rmp_serde::from_slice'. 2022-04-19 13:20:44 -07:00
Sergio Benitez 82cd53de36 Add 'must_use' to 'Rocket'.
Closes #2146.
2022-04-19 13:03:58 -07:00
Sergio Benitez 1b37d571c2 Rework 'local_cache!' so it returns unique refs.
Fixes #1987.
2022-04-18 18:12:54 -07:00
Sergio Benitez 8573b6069f Use 'print' for logging in debug.
In cc98f98, logging was changed to use a new 'write_out!' macro that
internally used 'write!' instead of 'print!' to log. This had an
unfortunate side-effect: 'libtest' via 'cargo test' no longer captures
the log output of tests.

The reason this occurs is due to the way that Cargo, or rather
`libtest`, captures log output: it uses hidden, unstable functions that
replace a special sink that `print!`, and _only_ `print!` writes to.
Using `write!` directly, as the commit does, bypasses this sink, and so
`cargo` never captures the output.

As a compromise, we only use the better implementation when we're not
compiled with `debug_assertions` or running tests, so at least tests run
in debug-mode won't spew output.
2022-04-14 15:01:51 -07:00
Sergio Benitez ae0ccf43f1 Fix parsing docs for 'Lenient'.
Resolves #2039.
2022-03-09 14:09:22 -08:00
Sergio Benitez 4fcb57b704 Log HTTP/2 availability at start-up. 2022-03-08 15:24:14 -08:00
Edgar Onghena ff7cf68461 Make HTTP/2 optional via 'http2' feature.
Closes #2030.
2022-03-08 15:13:24 -08:00
arlecchino cc98f98aa7 Implement and log with panic-free 'write_out!'.
Resolves #2019.
2022-03-08 14:41:01 -08:00
Alex Sears 91e3b4397a Fix 'observe' and 'retrieve' typos in cookie docs. 2022-02-23 14:40:01 -08:00
Aurora 3bd65e7e18 Use docstring '///' comment in 'Responder' docs. 2022-02-23 14:36:03 -08:00
David Venhoek 83e7fe1157 Log launch messages at info level.
Fixes #1828.
Closes #1871.
2022-02-23 14:16:18 -08:00
Sergio Benitez 8825f936ef Add 'includeSubdomains' in HSTS preload header.
Resolves #2049.
Closes #2050.

Co-authored-by: Soham Roy <sohamroy@sohamroy.me>
2022-02-22 18:19:09 -08:00
Sergio Benitez fda05bddd2 Update 'rustls' to 0.20.
Also updates 'tokio-rustls' to a compatible version.

Additionally depends on 'rustls-pemfile' which includes functionality
that was previously part of 'rustls' itself.
2022-02-22 17:30:42 -08:00
arlecchino 1ba41b3990 Remove 'CookieJar::get_private_pending()'.
This commit removes the 'CookieJar::get_private_pending()' method in
favor of the already existing and correct 'CookieJar::get_pending()'
method. Previously, the 'CookieJar::get_private_pending()' method
attempted to decrypt the value of a pending cookie, which in reality is
plaintext, thus failing. Because the pending value is plaintext, the
'CookieJar::get_pending()' method suffices.

Documentation has been updated to refer to 'CookieJar::get_pending()'.

Fixes #2063.
2022-02-17 11:04:30 -08:00
Sergio Benitez 0ba5aac53e Update codebase for latest nightly and stable. 2022-02-16 10:08:55 -08:00
Rodolphe Bréard 7a54a1293e Display launch address using 'SocketAddr' fmt.
This fixes IPv6 address display and future-proofs any such display.
2021-08-24 19:40:42 -07:00