Lifecycle Stage | Maturity | Status | Latest Revision |
---|---|---|---|
1A | Working Draft | Active | r0, 2023-05-31 |
Authors: @marcopolo
Interest Group: @marcopolo, @mxinden, @marten-seemann
This document is only about advertising support for an HTTP transport. It doesn't make any assertions about how libp2p should interact with that transport. That will be defined in a future document.
This exists to clarify the role of the /http
component in Multiaddrs early to
avoid confusion and conflicting interpretations.
An HTTP transport is simply a node that can speak some standardized version of
HTTP. Intuitively if you can curl
it with HTTP, then it speaks HTTP.
Most environments will have a way to create an HTTP Client and Server, and the
specific HTTP version used will be opaque. We use the /http
component at the
end of the multidadr to signal that this server supports an HTTP transport. The
end user agent decides on HTTP version to use, based on the multiaddr prefix,
application, server negotiation, and specific use case. This follows what
existing http://
URL implementations do.
The multiaddr of a node with an HTTP transport ends with /http
and is prefixed
by information that would let an HTTP client know how to reach the server
(remember that multiaddrs are interpreted right to
left).
The following are examples of multiaddrs for HTTP transport capable nodes:
/dns/example.com/tls/http
/ip4/1.2.3.4/tcp/443/tls/http
/ip6/2001:0db8:85a3:0000:0000:8a2e:0370:7334/tcp/443/tls/http
/ip4/1.2.3.4/udp/50781/quic-v1/http
Note: When we use /quic-v1/http
or /tcp/443/tls/http
(or any other
transport) implementations MUST use the correct HTTP ALPN (e.g. h3
or h2
respectively) and not libp2p
when using the HTTP transport.
It may be tempting to add an HTTP path to end of the multiaddr to specify some
information about a user protocol. However the /http
component is not a user
protocol, and it doesn't accept any parameters. It only signals that a node is
capable of an HTTP transport.
The HTTP Path exists in the semantics level. HTTP Semantics are transport-agnostic, and defined by RFC 9110. You can use these semantics on any transport including, but not limited to, the HTTP transports like HTTP/1.1, HTTP/2, or HTTP/3.
In general, it's better to keep the multiaddrs as a way of addressing an endpoint and keep the semantics independent of any specific transport. This way you can use the same semantics among many specific transports.
However, sometimes it's helpful to share a single multiaddr that contains some
extra application-level data (as opposed to transport data). The recommendation
is to use a new multicodec in the private
range for your
application. Then apply whatever application parameters to the right of your new
multicodec and transport information to the left. E.g.
<transport>/myapp/<parameters>
or /ip4/127.0.0.1/tcp/8080/http/myapp/custom-prefix/foo%2fbar
. Your
application has the flexibility to handle the parameters in any way it wants
(e.g. set HTTP headers, an HTTP path prefix, cookies, etc).
This is a bit cumbersome when you are trying to use multiple transports since you may end up with many multiaddrs with different transports but the same suffix. A potential solution here is to keep them separate. A list of multiaddrs for the transports being used, and another multiaddr for the application-level data. This is one suggestion, and many other strategies would work as well.