-
Notifications
You must be signed in to change notification settings - Fork 483
feat(protocol): add HTTP protocol implementation for libp2p #3046
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
Closed
Closed
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
d27dc75
feat: implement core HTTP protocol interfaces and types along with tests
devlux76 dcf8edd
chore: update dependencies to latest versions and clean up imports in…
devlux76 e181cce
feat: enhance HTTP client and server interfaces with protocol discove…
devlux76 a960c9a
Fix broken? Dependency on latest.
devlux76 f03353e
chore: update peerDependencies to specific versions in package.json
devlux76 48cf488
chore: specify version for @libp2p/websockets in package.json
devlux76 9b74c43
feat: fix for failing tests due to dep changes
devlux76 5c3ebc1
fix: correct formatting in HttpClientInterface documentation
devlux76 e80d82a
refactor: improve error handling and streamline node configuration in…
devlux76 57090a3
refactor: clean up whitespace in HTTP server test file
devlux76 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 hidden or 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,73 @@ | ||
# HTTP Protocol Implementation Alignment Plan | ||
|
||
## Executive Summary | ||
|
||
After thorough analysis of the codebase, README, and DESIGN documents, the implementation largely aligns with the intended design. There are a few areas where adjustments could improve this alignment or where the implementation necessarily deviated from the original design due to practical constraints. | ||
|
||
## Current State Assessment | ||
|
||
### Areas of Strong Alignment | ||
|
||
1. **Core Architecture**: The implementation successfully follows the core architecture defined in the DESIGN document with separate HTTP Client and HTTP Server components working over libp2p streams. | ||
|
||
2. **Protocol Identification**: As specified, the implementation uses `/https/1.1` as the protocol identifier for stream negotiation. | ||
|
||
3. **Message Structure**: The implementation uses Protocol Buffers v3 for message serialization with the composition pattern described in the DESIGN document, adapting well to Protocol Buffer constraints. | ||
|
||
4. **WHATWG Fetch API Compatibility**: The implementation provides a well-designed compatibility layer for the WHATWG Fetch API as specified. | ||
|
||
5. **Path-based Routing**: The router implementation correctly supports path-based request routing and middleware functionality. | ||
|
||
6. **Protocol Discovery**: The implementation now includes support for the `.well-known/libp2p/protocols` resource as specified in the libp2p HTTP specification, allowing clients to discover protocols supported by remote peers. | ||
|
||
### Areas of Misalignment or Deviation | ||
|
||
1. **Authentication Mechanisms**: As noted in the DESIGN document, authentication schemes are not fully implemented beyond the basic transport-level security provided by libp2p. | ||
|
||
2. **HTTP Response Type Definition**: The `HttpResponse` interface in `10-http-message.ts` includes extraneous fields (`content`, `status`, `headers`) that appear to be from the WHATWG Response interface, potentially causing confusion. | ||
|
||
3. **Error Handling Strategy**: The implementation has robust error handling, but it's not explicitly specified in the DESIGN document how errors should be propagated. | ||
|
||
4. **Incomplete Feature Support**: As acknowledged in the DESIGN document, not all HTTP features (caching, range requests, etc.) are fully implemented. | ||
|
||
## Alignment Strategy | ||
|
||
### Completed Alignments | ||
|
||
1. **Protocol Discovery Implementation**: ✓ Implemented the `.well-known/libp2p/protocols` endpoint as described in the specification by: | ||
- Creating a protocol registry to track supported protocols | ||
- Adding a dedicated handler for the `.well-known/libp2p/protocols` resource | ||
- Enhancing the HTTP client to support querying this endpoint | ||
- Updating interface definitions to expose the new functionality | ||
|
||
### Immediate Adjustments (No Code Changes Required) | ||
|
||
1. **Update DESIGN Document**: Clarify the relationship between the Protocol Buffers message structure and the WHATWG interfaces to avoid confusion. | ||
|
||
2. **Document Error Handling Strategy**: Add explicit error handling guidance to the DESIGN document. | ||
|
||
3. **Feature Roadmap**: Create a roadmap for implementing missing HTTP features to align with the original vision. | ||
|
||
### Short-term Improvements | ||
|
||
1. **Clean up HttpResponse Interface**: Remove extraneous fields from the HttpResponse interface in Protocol Buffers definition that seem to be mixed with WHATWG Response fields. | ||
|
||
2. **Enhanced Documentation**: Add more detailed documentation on how the various components interact, particularly the relationship between the low-level HTTP protocol API and the WHATWG Fetch API layer. | ||
|
||
3. **Improved Test Coverage**: Enhance tests to validate compliance with the design especially around error conditions and edge cases. | ||
|
||
### Medium-term Alignment Tasks | ||
|
||
1. **Authentication Implementation**: Develop the peer ID authentication schemes mentioned in the specification. | ||
|
||
2. **Extended HTTP Feature Support**: Incrementally implement missing HTTP features such as caching, conditional requests, etc. | ||
|
||
3. **Performance Optimizations**: Implement the optimization strategies mentioned in the "Future Work" section of the DESIGN document. | ||
|
||
## Conclusion | ||
|
||
The current implementation strongly aligns with the design vision outlined in the README and DESIGN documents. With the addition of the protocol discovery mechanism via the `.well-known/libp2p/protocols` endpoint, a key deviation mentioned in the original DESIGN document has been addressed. | ||
|
||
The remaining deviations are primarily due to practical constraints of Protocol Buffers or are explicitly acknowledged as areas for future work. With the suggested improvements, the alignment between design and implementation can be further enhanced. | ||
|
||
The core architecture is sound and follows good software engineering practices, making it a solid foundation for the planned improvements. No major architectural changes appear necessary, just refinements to better align with the specification and improve robustness and performance. |
This file contains hidden or 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,203 @@ | ||
# HTTP Protocol Implementation Design | ||
|
||
## Overview | ||
|
||
This document outlines the design and implementation of the HTTP protocol over libp2p based on the [official libp2p HTTP specification](https://github.com/libp2p/specs/blob/master/http/README.md). It describes the current implementation architecture, design decisions, and deviations from the specification due to technical constraints. | ||
|
||
## Specification Compliance | ||
|
||
The implementation follows the libp2p HTTP specification with some adaptations: | ||
|
||
1. **Transport Layer**: Uses libp2p streams as the underlying transport mechanism | ||
2. **Protocol Identification**: Uses `/https/1.1` as the protocol identifier for stream negotiation | ||
3. **Message Format**: Implements HTTP semantics using Protocol Buffers v3, which required several structural adaptations | ||
|
||
## Architecture | ||
|
||
### Core Components | ||
|
||
The implementation consists of three main components: | ||
|
||
1. **HTTP Client** (`HttpClient`): Sends HTTP requests to remote peers | ||
2. **HTTP Server** (`HttpServer`): Receives and processes HTTP requests from peers | ||
3. **Common HTTP Layer**: Shared message types, encoders/decoders, and utility functions | ||
|
||
### Protocol Identifier | ||
|
||
```typescript | ||
// From constants.ts | ||
export const PROTOCOL_VERSION = '1.1' | ||
export const PROTOCOL_NAME = 'https' | ||
``` | ||
|
||
The full protocol identifier used for libp2p stream negotiation is `/https/1.1`. | ||
|
||
### Message Structure | ||
|
||
Due to Protocol Buffers v3 limitations (particularly the lack of inheritance), the implementation uses a composition pattern for HTTP messages: | ||
|
||
```typescript | ||
// Base message with common fields | ||
interface HttpMessage { | ||
headers: Field[]; | ||
content: Uint8Array; | ||
trailers: Field[]; | ||
} | ||
|
||
// Request as composition rather than inheritance | ||
interface HttpRequest { | ||
baseMessage?: HttpMessage; // Composition instead of inheritance | ||
method: string; | ||
targetUri: string; | ||
protocolVersion: string; | ||
} | ||
|
||
// Response as composition rather than inheritance | ||
interface HttpResponse { | ||
baseMessage?: HttpMessage; // Composition instead of inheritance | ||
statusCode: number; | ||
reasonPhrase: string; | ||
protocolVersion: string; | ||
} | ||
``` | ||
|
||
### Deviation: Protocol Buffers v3 Adaptations | ||
|
||
Several adaptations were made to accommodate Protocol Buffers v3 constraints: | ||
|
||
1. **Composition over Inheritance**: Used composition pattern where HttpRequest and HttpResponse contain a baseMessage reference | ||
2. **Repeated Fields for Maps**: Used repeated field structures instead of map types | ||
3. **OneOf for Alternatives**: Used Protocol Buffers' `oneof` for mutually exclusive fields | ||
4. **Default Values**: All fields have default values as required by Protocol Buffers v3 | ||
5. **Explicit Message Types**: Created dedicated message types for structured data | ||
|
||
### HTTP Client Implementation | ||
|
||
The HTTP client implements: | ||
|
||
1. **Core Fetch Method**: Sends HTTP requests to remote peers and returns HTTP responses | ||
2. **WHATWG Fetch API**: Provides a web-compatible fetch interface for ease of use | ||
3. **Connection Management**: Properly handles libp2p connections and streams | ||
4. **Error Handling**: Robust error handling and logging | ||
|
||
```typescript | ||
class HttpClient implements Startable { | ||
// Core method to send HTTP request to a peer | ||
async fetch(peer: PeerId, request: http.HttpRequest, options: AbortOptions = {}): Promise<http.HttpResponse> { | ||
// Open connection to peer | ||
// Create stream using protocol identifier | ||
// Send request using Protocol Buffers | ||
// Receive and return response | ||
} | ||
} | ||
``` | ||
|
||
### HTTP Server Implementation | ||
|
||
The HTTP server implements: | ||
|
||
1. **Request Handling**: Processes incoming HTTP requests over libp2p streams | ||
2. **Path-based Routing**: Routes requests to appropriate handlers based on URI path | ||
3. **Middleware Support**: Allows processing pipelines with middleware functions | ||
4. **Error Handling**: Proper error responses and logging | ||
|
||
```typescript | ||
class HttpServer implements Startable { | ||
// Register a handler for a specific path | ||
register(path: string, handler: RequestHandler): void { | ||
this.router.route(path, handler); | ||
} | ||
|
||
// Add middleware to request processing pipeline | ||
use(middleware: Middleware): void { | ||
this.router.use(middleware); | ||
} | ||
|
||
// Handle incoming message | ||
async handleMessage(data: IncomingStreamData): Promise<void> { | ||
// Read request using Protocol Buffers | ||
// Route request to appropriate handler | ||
// Send response using Protocol Buffers | ||
} | ||
} | ||
``` | ||
|
||
### WHATWG Fetch API Compatibility | ||
|
||
The implementation provides a compatibility layer for the WHATWG Fetch API: | ||
|
||
```typescript | ||
// WHATWG Fetch API over libp2p | ||
async function fetch(url: string | URL, init?: RequestInit): Promise<Response> { | ||
// Parse URL to extract peer ID and path | ||
// Convert to HTTP request format | ||
// Send request using HTTP client | ||
// Convert HTTP response to WHATWG Response | ||
} | ||
``` | ||
|
||
## Key Deviations from Specification | ||
|
||
### 1. Namespace Implementation | ||
|
||
The specification calls for using a `.well-known/libp2p/protocols` resource for discovering application protocols. The current implementation uses direct path-based routing without this discovery mechanism. This is a known deviation from the specification. | ||
|
||
```typescript | ||
// Current implementation uses direct path registration | ||
libp2p.services.http.register('/api/users', handler); | ||
|
||
// Specification suggests protocol discovery via | ||
// GET /.well-known/libp2p/protocols | ||
``` | ||
|
||
### 2. Authentication | ||
|
||
The specification mentions that Peer ID authentication is optional, with specific authentication schemes to be defined in a future spec. The current implementation does not include explicit peer authentication beyond what libp2p provides at the transport layer. | ||
|
||
### 3. HTTP Encoding | ||
|
||
The specification allows for different encodings of HTTP semantics (HTTP/1.1, HTTP/2, HTTP/3). The current implementation specifically uses HTTP/1.1 semantics encoded in Protocol Buffers. | ||
|
||
## Implementation Limitations | ||
|
||
1. **Limited HTTP Feature Support**: Not all HTTP features (caching, range requests, etc.) are fully implemented | ||
2. **Protocol Buffers Constraints**: Some HTTP structures had to be adapted to work within Protocol Buffers' limitations | ||
3. **Authentication**: Detailed authentication schemes are not yet implemented | ||
|
||
## Future Work | ||
|
||
1. **Complete Specification Alignment**: Implement `.well-known/libp2p/protocols` resource | ||
2. **Enhanced Authentication**: Implement peer ID authentication schemes | ||
3. **Advanced HTTP Features**: Add support for more HTTP features (caching, conditional requests, etc.) | ||
4. **Performance Optimizations**: Optimize for high-throughput and low-latency scenarios | ||
|
||
## Integration with libp2p | ||
|
||
The implementation integrates with libp2p through: | ||
|
||
1. **Stream Handling**: Uses libp2p's stream multiplexing | ||
2. **Protocol Negotiation**: Registers protocol handler via libp2p's registrar | ||
3. **Connection Management**: Leverages libp2p's connection manager | ||
4. **PeerId Resolution**: Uses libp2p's peer ID system for addressing | ||
|
||
```typescript | ||
// Register protocol handler with libp2p | ||
await this.components.registrar.handle(this.protocol, (data) => { | ||
void this.handleMessage(data) | ||
.then(async () => { | ||
await data.stream.close() | ||
}) | ||
.catch(err => { | ||
this.log.error('error handling HTTP request - %e', err) | ||
}) | ||
}, { | ||
maxInboundStreams: this.init.maxInboundStreams, | ||
maxOutboundStreams: this.init.maxOutboundStreams | ||
}) | ||
``` | ||
|
||
## Conclusion | ||
|
||
The HTTP implementation over libp2p provides a robust foundation for HTTP-based communication between libp2p peers. While there are some deviations from the official specification due to practical implementation constraints, the core functionality allows for HTTP semantics over libp2p's transport layer. | ||
|
||
The implementation successfully adapts HTTP semantics to the libp2p environment, enabling familiar HTTP patterns in a peer-to-peer context. Future work will focus on closer alignment with the specification and enhanced feature support. |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.
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.
/http/1.1
and this PR uses/https/1.1
/http/1.1
is cleartext version of HTTP, as defined in RFC 2616, no TLS, no extra transformations/serializations/http/1.1
over libp2p does not have hard dependency on Protocol Buffer by designThis makes this PR effectively introduce a new, protobuf-based custom protocol with HTTP semantics, which does not have any agreed specs.
I see a lot of work and effort went into this. Some potential paths forward:
/http/1.1
wire format and specs from https://github.com/libp2p/specs/tree/master/http/http/1.1/ipfs/gateway
as opt-in experiment)/http/1.1
, and propose ways to fix it