Skip to content

Commit f25d0c2

Browse files
authored
Merge pull request #508 from libp2p/http
add HTTP spec
2 parents 2ea41e8 + 8f44d00 commit f25d0c2

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

http/README.md

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# HTTP
2+
3+
| Lifecycle Stage | Maturity | Status | Latest Revision |
4+
| --------------- | ------------- | ------ | --------------- |
5+
| 1A | Working Draft | Active | r0, 2023-01-23 |
6+
7+
Authors: [@marten-seemann], [@MarcoPolo]
8+
9+
Interest Group: [@lidel], [@thomaseizinger]
10+
11+
[@marten-seemann]: https://github.com/marten-seemann
12+
[@MarcoPolo]: https://github.com/MarcoPolo
13+
[@lidel]: https://github.com/lidel
14+
[@thomaseizinger]: https://github.com/thomaseizinger
15+
16+
## Introduction
17+
18+
This document defines how libp2p nodes can offer and use an HTTP transport alongside their other transports to support application protocols with HTTP semantics. This allows a wider variety of nodes to participate in the libp2p network, for example:
19+
20+
- Browsers communicating with other libp2p nodes without needing a WebSocket, WebTransport, or WebRTC connection.
21+
- HTTP only edge workers can run application protocols and respond to peers on the network.
22+
- `curl` from the command line can make requests to other libp2p nodes.
23+
24+
The HTTP transport will also allow application protocols to make use of HTTP intermediaries such as HTTP caching, and layer 7 proxying and load balancing. This is all in addition to the existing features that libp2p provides such as:
25+
26+
- Connectivity – Work on top of WebRTC, WebTransport, QUIC, TCP, or an HTTP transport.
27+
- Hole punching – Work with peers behind NATs.
28+
- Peer ID Authentication – Authenticate your peer by their libp2p peer id.
29+
- Peer discovery – Learn about a peer given their peer id.
30+
31+
## HTTP Semantics vs Encodings vs Transport
32+
33+
HTTP is a bit of an overloaded term. This section aims to clarify what we’re talking about when we say “HTTP”.
34+
35+
36+
```mermaid
37+
graph TB
38+
subgraph "HTTP Semantics"
39+
HTTP
40+
end
41+
subgraph "Encoding"
42+
HTTP1.1[HTTP/1.1]
43+
HTTP2[HTTP/2]
44+
HTTP3[HTTP/3]
45+
end
46+
subgraph "Transports"
47+
Libp2p[libp2p streams]
48+
HTTPTransport[HTTP transport]
49+
end
50+
HTTP --- HTTP1.1
51+
HTTP --- HTTP1.1
52+
HTTP1.1 --- Libp2p
53+
HTTP --- HTTP2
54+
HTTP --- HTTP3
55+
HTTP1.1 --- HTTPTransport
56+
HTTP2 --- HTTPTransport
57+
HTTP3 --- HTTPTransport
58+
```
59+
60+
- *HTTP semantics* ([RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html)) is
61+
the stateless application-level protocol that you work with when writing HTTP
62+
apis (for example).
63+
64+
- *HTTP encoding* is the thing that takes your high level request/response
65+
defined in terms of HTTP semantics and encodes it into a form that can be sent
66+
over the wire.
67+
68+
- *HTTP transport* is the thing that takes your encoded request/response and
69+
sends it over the wire. For HTTP/1.1 and HTTP/2, this is a TCP+TLS connection.
70+
For HTTP/3, this is a QUIC connection.
71+
72+
When this document says *HTTP* it is generally referring to *HTTP semantics*.
73+
74+
## Interoperability with existing HTTP systems
75+
76+
A goal of this spec is to allow libp2p to be able to interoperate with existing HTTP servers and clients. Care is taken in this document to not introduce anything that would break interoperability with existing systems.
77+
78+
## HTTP Transport
79+
80+
Nodes MUST use HTTPS (i.e., they MUST NOT use plaintext HTTP). It is RECOMMENDED to use HTTP/2 and HTTP/3.
81+
82+
Nodes signal support for their HTTP transport using the `/http` component in
83+
their multiaddr. E.g., `/dns4/example.com/tls/http`. See the [HTTP multiaddr
84+
component spec](https://github.com/libp2p/specs/blob/master/http/transport-component.md) for more details.
85+
86+
## Namespace
87+
88+
libp2p does not squat the global namespace. libp2p application protocols can be
89+
discovered by the [well-known resource](https://www.rfc-editor.org/rfc/rfc8615)
90+
`.well-known/libp2p/protocols`. This allows server operators to dynamically change the
91+
URLs of the application protocols offered, and not hard-code any assumptions how
92+
a certain resource is meant to be interpreted.
93+
94+
```json
95+
96+
{
97+
"protocols": {
98+
"/kad/1.0.0": {"path": "/kademlia/"},
99+
"/ipfs/gateway": {"path": "/"},
100+
}
101+
}
102+
```
103+
104+
The resource contains a mapping of application protocols to a URL namespace. For
105+
example, this configuration file would tell a client
106+
107+
1. The Kademlia application protocol is available with prefix `/kademlia`
108+
and,
109+
2. The [IPFS Trustless Gateway API](https://specs.ipfs.tech/http-gateways/trustless-gateway/) is mounted at `/`.
110+
111+
It is valid to expose a service at `/`. It is RECOMMENDED that implementations facilitate the coexistence of different service endpoints by ensuring that more specific URLs are resolved before less specific ones. For example, when registering handlers, more specific paths like `/kademlia/foo` should take precedence over less specific handler, such as `/`.
112+
113+
## Peer ID Authentication
114+
115+
When using the HTTP Transport, Peer ID authentication is optional. You only pay
116+
for it if you need it. This benefits use cases that don’t need peer
117+
authentication (e.g., fetching content addressed data) or authenticate some
118+
other way (not tied to libp2p peer ids).
119+
120+
Specific authentication schemes for authenticating Peer IDs will be defined in
121+
a future spec.
122+
123+
## Using HTTP semantics over stream transports
124+
125+
Application protocols using HTTP semantics can run over any libp2p stream transport. Clients open a new stream using `/http/1.1` as the protocol identifer. Clients encode their HTTP request as an HTTP/1.1 message and send it over the stream. Clients parse the response as an HTTP/1.1 message and then close the stream. Clients SHOULD NOT pipeline requests over a single stream. Clients and Servers SHOULD set the [`Connection: close` header](https://datatracker.ietf.org/doc/html/rfc9112#section-9.6) to signal to clients that this is not a persistent connection.
126+
127+
HTTP/1.1 is chosen as the minimum bar for interoperability, but other encodings of HTTP semantics are possible as well and may be specified in a future update.
128+
129+
## Multiaddr URI scheme
130+
131+
In places where a URI is expected, implementations SHOULD accept a multiaddr URI
132+
in addition to a standard http or https URI. A multiaddr URI is a
133+
[URI](https://datatracker.ietf.org/doc/html/rfc3986) with the `multiaddr`
134+
scheme. It is constructed by taking the "multiaddr:" string and appending the
135+
string encoded representation of the multiaddr. E.g. the multiaddr
136+
`/ip4/1.2.3.4/udp/54321/quic-v1` would be represented as
137+
`multiaddr:/ip4/1.2.3.4/udp/54321/quic-v1`.
138+
139+
This URI can be extended to include HTTP paths with the `/http-path` component.
140+
This allows a user to make an HTTP request to a specific HTTP resource using a
141+
multiaddr. For example, a user could make a GET request to
142+
`multiaddr:/ip4/1.2.3.4/udp/54321/quic-v1/p2p/12D.../http-path/.well-known%2Flibp2p`. This also allows
143+
an HTTP redirect to another host and another HTTP resource.
144+
145+
## Using other request-response semantics (not HTTP)
146+
147+
This document has focused on using HTTP semantics, but HTTP may not be the common divisor amongst all transports (current and future). It may be desirable to use some other request-response semantics for your application-level protocol, perhaps something like rust-libp2p’s [request-response](https://docs.rs/libp2p/0.52.1/libp2p/request_response/index.html) abstraction. Nothing specified in this document prohibits mapping other semantics onto HTTP semantics to keep the benefits of using an HTTP transport.
148+
149+
As a simple example, to support the simple request-response semantics, the request MUST be encoded within a `POST` request to the proper URL (as defined in the [Namespace](#namespace) section). The response is read from the body of the HTTP response. The client MUST authenticate the server and itself **before** making the request. The reason to chose `POST` is because this mapping makes no assumptions on whether the request is cacheable. If HTTP caching is desired users should either build on HTTP semantics or chose another mapping with different assumptions.
150+
151+
Other mappings may also be valid and as long as nodes agree.

0 commit comments

Comments
 (0)