-
Notifications
You must be signed in to change notification settings - Fork 291
add HTTP spec #508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add HTTP spec #508
Changes from 14 commits
bc1aa59
1f075f6
12f86b8
146c09a
5398f5d
b6c1bc2
8a57943
d506145
946f516
3681472
dd5d07c
46d1857
ebe612c
7e5a077
db2b3b5
6319458
c7c9c43
454e25c
a25267b
3014b22
f96359b
1e87960
d0f0d93
8fbd64a
71415b0
4a03bb0
877899d
dc71f2c
d8850aa
78e8ca1
d30efda
8628b5a
3c0ac40
75bc635
f95e4db
e3eb9dc
95ffe6d
8f44d00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,114 @@ | ||||||
| # HTTP | ||||||
|
|
||||||
| | Lifecycle Stage | Maturity | Status | Latest Revision | | ||||||
| | --------------- | ------------- | ------ | --------------- | | ||||||
| | 1A | Working Draft | Active | r0, 2023-01-23 | | ||||||
|
|
||||||
| Authors: [@marten-seemann, @MarcoPolo] | ||||||
|
|
||||||
| Interest Group: [@lidel] | ||||||
|
|
||||||
| [@marten-seemann]: https://github.com/marten-seemann | ||||||
| [@MarcoPolo]: https://github.com/MarcoPolo | ||||||
| [@lidel]: https://github.com/lidel | ||||||
MarcoPolo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
||||||
MarcoPolo marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| ## Introduction | ||||||
|
|
||||||
| 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: | ||||||
MarcoPolo marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
|
||||||
| - Browsers communicating with other libp2p nodes without needing a WebSocket, WebTransport, or WebRTC connection. | ||||||
| - HTTP only edge workers can run application protocols and respond to peers on the network. | ||||||
| - `curl` from the command line can make requests to other libp2p nodes. | ||||||
|
|
||||||
| As well as allowing 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: | ||||||
MarcoPolo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
||||||
| - Connectivity – Work on top of WebRTC, WebTransport, QUIC, TCP, or an HTTP transport. | ||||||
| - Hole punching – Work with peers behind NATs. | ||||||
| - Peer ID Authentication – Authenticate your peer by their libp2p peer id. | ||||||
| - Peer discovery – Learn about a peer given their peer id. | ||||||
|
|
||||||
| ## HTTP Transport vs HTTP Semantics | ||||||
|
||||||
|
|
||||||
| HTTP is a bit of an overloaded term. This section aims to clarify what we’re talking about when we say “HTTP”. | ||||||
|
|
||||||
| *HTTP semantics* ([RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html)) is the stateless application-level protocol that you work with when writing HTTP apis (for example). | ||||||
|
|
||||||
| *HTTP transport* is the thing that takes your high level request/response defined in terms of HTTP semantics and encodes it and sends it over the wire. | ||||||
MarcoPolo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
||||||
| When this document says *HTTP* it is generally referring to *HTTP semantics*. | ||||||
|
|
||||||
| ## Interoperability with existing HTTP systems | ||||||
|
|
||||||
| 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. | ||||||
|
Comment on lines
+72
to
+76
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this is a bit confusing to me. Above you are saying the you generally refer to HTTP semantics and the next sentence says that a goal is to interoperate with existing HTTP servers and clients which refers to the transport, correct?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refers to both actually |
||||||
|
|
||||||
| ## HTTP Transport | ||||||
|
|
||||||
| Nodes MUST use HTTPS (i.e. they MUST NOT use plaintext HTTP). It is RECOMMENDED to use HTTP/2 and HTTP/3. | ||||||
|
|
||||||
| Nodes signal support for their HTTP transport using the `/http` component in their multiaddr. e.g. `/dns4/example.com/tls/http` . See the [HTTP multiaddr component spec](https://github.com/libp2p/specs/pull/550) for more details. | ||||||
|
||||||
| Nodes signal support for their HTTP transport using the `/http` component in their multiaddr. e.g. `/dns4/example.com/tls/http` . See the [HTTP multiaddr component spec](https://github.com/libp2p/specs/pull/550) for more details. | |
| Nodes signal support for their HTTP transport using the `/http` or `/https` component in their multiaddr. e.g. `/dns4/example.com/tls/http` or `/dns4/example.com/https` . See the [HTTP multiaddr component spec](https://github.com/libp2p/specs/blob/master/http/transport-component.md) for more details. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we explicitly state in that spec that /https is an alias for /tls/http
/https is an alias for /tls/http: multiformats/multiaddr#109 and multiformats/multicodec#145
https://github.com/multiformats/multiaddr/blob/master/protocols.csv?plain=1#L31
I'm fine to add a note about /https somewhere though
MarcoPolo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not the biggest fan of the term "services" here. I think I would prefer "protocols", "applications", or maybe something else. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe "endpoints"? (since that is what we define here, HTTP API endpoints for specific service/protocol)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe "endpoints"? (since that is what we define here, HTTP API endpoints for specific service/protocol)
The endpoints are the values though, really what we define is metadata for all supported protocols. We might extend this metadata with additional information later (see @BigLep's comment below). My vote goes down for protocols.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So today we have a pair of information: <libp2p protocol name, URL path>
I agree maps make it easy for encoding a collection of pairs.
Do we ever expect to need more information (tuple)?
Maybe encode like:
endpoints : [
{
"protocolName" : "/kad/1.0.0",
"path" : "/kademlia"
}, {
...
}
]
?
This makes it self documenting and allows expansion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that protocol IDs have to be unique anyway, how about a map of string to object?
{
"/kad/1.0.0": {
"path": "/kademlia"
}
}Perhaps we can define that implementations must accept both representations and the "string:string" representation is a short-form of the "string:object" notation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more thoughts on this:
- The path alone is not enough to form a request. We need more (out-of-band) information like what method to use.
- Do you expect a protocol-spec like kademlia to be extended on how it can be accessed from an HTTP transport? (And which methods need authentication for example?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit hesitant to add the ability to put more metadata without a use case behind it, but making it a map with path seems easy enough, and would allow adding new fields in a backwards compatible way, which is nice.
- The path alone is not enough to form a request. We need more (out-of-band) information like what method to use.
This is up to the application protocol. The application protocol defines how it works and what HTTP methods it uses for what. This metadata only describes where the application protocol is mounted at. It doesn't describe the application protocol.
- Do you expect a protocol-spec like kademlia to be extended on how it can be accessed from an HTTP transport? (And which methods need authentication for example?)
Yes. That's up to the application protocol. Kademlia could make use of the simple request-response abstraction in #561 to define this, but ultimately the application protocol decides tis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated this to be a map from protocol name to metadata that includes a path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3. Do you expect a protocol-spec like kademlia to be extended on how it can be accessed from an HTTP transport? (And which methods need authentication for example?)
Yes. That's up to the application protocol. Kademlia could make use of the simple request-response abstraction in #561 to define this, but ultimately the application protocol decides tis.
I see, thanks for explaining. Can we make this clearer? Something like:
This mapping only defines a URL namespace for certain applications protocols. It is entirely up to the application protocol (like kademlia) to define how it can be interacted with over HTTP.
MarcoPolo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is RECOMMENDED that the server resolve more specific URLs before less specific ones
Do we need to specify this? Is there an RFC that deals with path resolution that we could link instead?
from @marten-seemann #556 (comment)
I believe most HTTP path routing libraries do this already. This is RECOMMENDED because it would be confusing to a client if /kademlia (in this example) was routed one way with one server but a different way for another server with the same "services" map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MarcoPolo perhaps we could rephrase this to be more actionable for implementers.
How about:
| It is valid to expose a service at `/`. It is RECOMMENDED that the server resolve more specific URLs before less specific ones. e.g. a path of `/kademlia/foo` should be routed to the Kademlia protocol rather than the IPFS HTTP API. | |
| The implementation MUST 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 `/`, which should be registered last. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me, but I would change this to a "SHOULD" rather than a "MUST". Thanks!
MarcoPolo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL about Authentication-Info!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How and where is this token included in the response? In the noise extensions? In an HTTP header?
This is essentially a cookie, right? Would it make sense to actually use the Set-Cookie header?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cookie headers have a bit of baggage with them. For example they are a Forbidden header name, and cannot be used with a service worker proxy.
The token would be included in the Noise extensions along with the SNI used. That wasn't clear, thanks for pointing that out!

Uh oh!
There was an error while loading. Please reload this page.