Skip to content
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

Document /http #550

Merged
merged 15 commits into from
Jul 10, 2023
111 changes: 111 additions & 0 deletions http/transport-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# HTTP Transport Component <!-- omit in toc -->

| Lifecycle Stage | Maturity | Status | Latest Revision |
| --------------- | ------------- | ------ | --------------- |
| 1A | Working Draft | Active | r0, 2023-05-31 |

Authors: [@marcopolo]

Interest Group: [@marcopolo], [@mxinden], [@marten-seemann]

[@marcopolo]: https://github.com/marcopolo
[@mxinden]: https://github.com/mxinden
[@marten-seemann]: https://github.com/marten-seemann

## Table of Contents <!-- omit in toc -->
- [Context](#context)
- [What is an HTTP transport](#what-is-an-http-transport)
- [Multiaddr representation](#multiaddr-representation)
- [HTTP Paths](#http-paths)


## Context

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.

## What is an HTTP transport

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.

## Multiaddr representation

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](https://github.com/multiformats/multiaddr#interpreting-multiaddrs)).

The following are examples of multiaddrs for HTTP transport capable nodes:

* `/dns/example.com/tls/http`
MarcoPolo marked this conversation as resolved.
Show resolved Hide resolved
MarcoPolo marked this conversation as resolved.
Show resolved Hide resolved
MarcoPolo marked this conversation as resolved.
Show resolved Hide resolved
* `/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/tls/http`
MarcoPolo marked this conversation as resolved.
Show resolved Hide resolved


## HTTP Paths
MarcoPolo marked this conversation as resolved.
Show resolved Hide resolved

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 user protocol level. HTTP Semantics are transport-agnostic, and defined by [RFC 9110](https://httpwg.org/specs/rfc9110.html). You can
use these semantics on any transport including, but not limited to, the HTTP
transports like [HTTP/1.1](https://www.rfc-editor.org/info/rfc7235), [HTTP/2](https://www.rfc-editor.org/info/rfc9113), or [HTTP/3](https://www.rfc-editor.org/info/rfc9114).

For example, say you want to fetch a file using the [IPFS trustless HTTP
gateway](https://specs.ipfs.tech/http-gateways/trustless-gateway/). It may be tempting to
use the following multiaddr to reference a file:

```
/ip4/127.0.0.1/tcp/8080/http/httppath/ipfs%2fbafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
```

But `/http` is a transport and it doesn't accept any parameters. It would be the
same as if we used the following multiaddr:

```
/ip4/127.0.0.1/udp/1234/quic-v1/httppath/ipfs%2fbafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
```

What does `httppath/` mean here? Does it mean make a `GET` request? How would
you make a `POST` request? What about headers? Does it leave that unspecified
and ask the user to specify that as they would with curl?

We could be more precise here and specify a `/GET` component to the multiaddr
that accepts parameters and describes what user protocol we are trying to do
here.

```
/ip4/127.0.0.1/udp/1234/http/GET/httppath/ipfs%2fbafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

or

/ip4/127.0.0.1/udp/1234/quic-v1/GET/httppath/ipfs%2fbafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
```

This is fine since `httppath` passes the path parameter to `GET` which parses
the rest of the multiaddr as the address of the node to connect to and make an
HTTP GET request which can happen over an HTTP transport or any other transport
(e.g. QUIC streams or yamux+noise+tcp).

You may end up with a lot of duplicate information if you have many multiaddrs
since each one will have the same suffix of `GET/httppath/...`. Therefore this
isn't recommended, but may be useful if you just need one multiaddr
with some extra protocol information.

To summarize, HTTP Paths don't make sense appended to an `/http` component, but may make sense
appended to some other custom user protocol component.