-
Notifications
You must be signed in to change notification settings - Fork 281
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
Simple request/response #561
Open
MarcoPolo
wants to merge
9
commits into
master
Choose a base branch
from
marco/simple-req-resp
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
a132130
Define a simple request/response abstraction
MarcoPolo 37670f4
typo
MarcoPolo bc696cb
Update simple-request-response/README.md
MarcoPolo 1e1c96d
Update simple-request-response/README.md
MarcoPolo bb709b6
Server closes stream too
MarcoPolo 0cc0cb8
Add considerations for applications
MarcoPolo 82ac1c6
Edits after conversation with Thomas
MarcoPolo 9db523b
Change to SHOULD NOT pipeline to keep backwards compat with things li…
MarcoPolo 932622d
Rename folder
MarcoPolo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# A request/response interface for application protocols on any transport | ||
|
||
| Lifecycle Stage | Maturity | Status | Latest Revision | | ||
| --------------- | ------------- | ------ | --------------- | | ||
| 1A | Working Draft | Active | r0, 2023-07-14 | | ||
|
||
Authors: [@MarcoPolo] | ||
|
||
Interest Group: [@mxinden] [@marten-seemann] [@thomaseizinger] | ||
|
||
[@marten-seemann]: https://github.com/marten-seemann | ||
[@MarcoPolo]: https://github.com/MarcoPolo | ||
[@mxinden]: https://github.com/mxinden | ||
[@thomaseizinger]: https://github.com/thomaseizinger | ||
|
||
## Introduction | ||
|
||
Many application protocols map well to request/response semantics where a peer | ||
makes a request to another peer, and receives a response back. For example, | ||
requesting a file from a peer and getting the file back. In contrast to | ||
request/response, stream semantics allow two peers to continously send data | ||
back and forth with no specific ordering. Both styles have their uses. This | ||
document focuses on _one_ way of implementing request/response semantics and | ||
how to map it to stream based transports and an HTTP transport. | ||
|
||
## The interface | ||
|
||
At its core, request-response means: | ||
- taking _one_ blob from the requesting peer (aka the client) | ||
- delivering this blob to the responding peer (aka the server) | ||
- taking _one_ blob from the responding peer | ||
- delivering this blob to the requesting peer | ||
|
||
The defining characteristics are: | ||
|
||
- Each party can only send one message | ||
- The interaction is linear in time (the response can only be initiated after the request has been received) | ||
|
||
This is in contrast to for example streaming protocols where the responding peer may send any number of messages or event/notification-based protocols where a message may be received without a prior request. | ||
|
||
What the blobs are and how they are encoded is subject to the application | ||
protocol and not defined in this interface. | ||
|
||
A rough suggestion for implementors to follow is provide something like: | ||
``` | ||
async fn handleRequest(request) -> response | ||
``` | ||
|
||
where the request/response may be read incrementally and asynchronously and the | ||
request/response may also be sent incrementally and asynchronously. This is | ||
similar to how many implementations do HTTP request/response: | ||
|
||
- JS [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) api returns a [`Response`](https://fetch.spec.whatwg.org/#response) object as soon as the server returns headers. The | ||
body of both requests and responses are `ReadableStreams`. | ||
- Go's [http.Request](https://pkg.go.dev/net/[email protected]#Request) and [http.Response](https://pkg.go.dev/net/[email protected]#Response) bodies are both [`io.ReadCloser`](https://pkg.go.dev/[email protected]#ReadCloser) types. | ||
- The Rust [hyper](https://docs.rs/hyper) crate has a similar [`HTTPBody`](https://docs.rs/hyper/latest/hyper/body/trait.HttpBody.html) that reads request/response data | ||
incrementally and asynchronously. | ||
|
||
## Goals of this document | ||
|
||
The primary goal of this document is to define an interface that application | ||
protocols can build on and transports can fulfill. | ||
|
||
Another goal is to be backwards compatible with existing application protocols | ||
that follow these semantics to make upgrading them easier so that they may take | ||
advantage of the new HTTP transport without sacrificing backwards compatibility. | ||
|
||
The final goal is to define something simple such that it's easy to follow, | ||
implement, and use. | ||
|
||
## How to map to a libp2p stream | ||
|
||
Each request and response should happen in a single stream. There SHOULD NOT be | ||
pipelining. After sending a request, the client SHOULD close its write side | ||
(signalling EOF to the peer). After handling the response, the client SHOULD | ||
close the stream. After sending the response the server SHOULD close the stream | ||
Comment on lines
+75
to
+76
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. This sentence doesn't make sense, the client already closed the stream. 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. Both sides can close the stream, right? |
||
side (signalling EOF to the peer as well as signalling no future writes will be accepted.). | ||
|
||
## How to map to an HTTP transport | ||
|
||
The client's request is placed in the body of an HTTP POST request. The server | ||
places its response in the body of the HTTP response. Headers are unused by the | ||
application protocol (but may be used by the libp2p implementation to provide | ||
authentication). The HTTP path used for the application protocol is defined by | ||
the server's `.well-known/libp2p` HTTP resource (see the | ||
[HTTP](../http/README.md) spec for more details). | ||
|
||
## Considerations for applications | ||
|
||
- Applications should define a reasonable maximum amount of expected data, and | ||
limit the amount of data they receive at any time. For example, Kademlia may | ||
limit the maximum size of a request to | ||
[16KiB](https://github.com/libp2p/rust-libp2p/blob/master/protocols/kad/src/protocol.rs#L48) | ||
or | ||
[4MiB](https://github.com/libp2p/go-libp2p/blob/master/core/network/network.go#L23). | ||
|
||
## Prior Art | ||
|
||
This spec is inspired by existing work to use request response protocols on top | ||
of libp2p streams including, but not limited to: | ||
- go-libp2p-kad-dht | ||
- Identify Push | ||
- AutoNATV2 | ||
|
||
This is also inspired by rust-libp2p's [Request/Response | ||
crate](https://docs.rs/libp2p-request-response/0.25.0/libp2p_request_response/). | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
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.
For backwards compatibility, this can't be a MUST.
I'd like to have existing request/response over streams (like identify), to already be compliant with this spec.
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.
Previous discussion: #561 (comment)