Skip to content

HTTP/2 103 Early Hints Support#3991

Open
apu031 wants to merge 2 commits intohyperium:masterfrom
apu031:http-103
Open

HTTP/2 103 Early Hints Support#3991
apu031 wants to merge 2 commits intohyperium:masterfrom
apu031:http-103

Conversation

@apu031
Copy link

@apu031 apu031 commented Dec 9, 2025

Implement HTTP/2 103 Early Hints Support

Add complete HTTP/2 103 Early Hints implementation with full client and server support, building upon the initial 1xx informational responses prototype to deliver a solution for web performance optimization.

Key Features Added

Client-side Support

  • Add InformationalConfig with callback system for processing 1xx informational responses
  • Extend HTTP/2 client builder with informational_responses() configuration method
  • Implement informational response polling in h2 client task with callback invocation
  • Support real-time processing of 103 Early Hints and other informational responses
  • Handle multiple informational responses before final response arrives

Server-side Support

  • Builder opt-in pattern: Add .enable_informational() method for explicit feature activation
  • Zero-cost abstraction: When disabled (default), zero overhead - no allocations, no extensions
  • early_hints_pusher() API: Ergonomic interface for sending 103 Early Hints
    • Returns EarlyHintsPusher handle when feature enabled
    • Returns EarlyHintsError::NotSupported when feature not enabled
    • Validates 103 status code requirement
  • Add InformationalSender extension for hint transmission via mpsc channel
  • Implement server-side informational response forwarding using h2's send_informational API
  • Support multiple 103 Early Hints responses per request for progressive resource discovery
  • Validate informational responses and handle errors gracefully

Complete Implementation

  • Build upon Joel Dice's initial HTTP/1 prototype (commit 4e2483a) to add full HTTP/2 support
  • Integrate with h2 crate's informational response capabilities
  • Add robust error handling and validation
  • Include production-ready example with TLS, resource preloading, and performance monitoring
  • Provide extensive test coverage with 11 integration tests covering different scenarios

Changed Files

  • Cargo.toml: Example build configuration
  • examples/README.md: Document new HTTP/2 Early Hints example
  • examples/http2_early_hints.rs: Working example with TLS, and resource preloading
  • src/client/conn/http2.rs: Extend HTTP/2 client builder with informational response configuration
  • src/client/conn/informational.rs: New module implementing client-side informational callback system
  • src/client/conn/mod.rs: Export new informational module
  • src/ext/informational_sender.rs: New early_hints_pusher() API
  • src/ext/mod.rs: Export new Early Hints API types
  • src/proto/h1/dispatch.rs: Update HTTP/1 dispatch for informational compatibility
  • src/proto/h1/role.rs: Extend HTTP/1 role handling for informational responses
  • src/proto/h2/client.rs: HTTP/2 client informational response polling
  • src/proto/h2/server.rs: Add enable_informational config field (defaults to false), conditional channel creation, helper method for polling logic
  • src/server/conn/http2.rs: Add .enable_informational() builder method
  • tests/integration-early-hints.rs: 11 integration tests

Test Coverage

Integration Tests (11 tests, ~0.27s)

All tests pass consistently, covering:

  • Basic preconnect hints functionality
  • Resource preloading (CSS, JS, fonts, images)
  • Content Security Policy enforcement via Early Hints
  • Multiple sequential 103 responses
  • Mixed Link header types with HTTP/2 compression handling
  • Cross-origin redirect security behavior
  • Real-world web page optimization scenarios
  • Empty 103 response validation
  • Timing validation for performance benefits
  • Error response handling after hints sent

Unit Tests (18 tests, ~0.24s)

  • API layer (7 tests): Error handling, channel communication, status validation
  • Builder layer (6 tests): Configuration, method chaining, flag propagation
  • Config layer (5 tests): Defaults, mutation, cloning, debug output

Documentation Tests (2 tests)

  • Examples for early_hints_pusher() usage
  • Example for .enable_informational() builder method

Total: 152 tests passing (31 new from this PR)

API Usage Example

Server-side (Requires Opt-in)

use hyper::server::conn::http2;
use hyper::ext::early_hints_pusher;
use hyper::{Request, Response, StatusCode};

// 1. Enable feature via builder
let builder = http2::Builder::new(executor)
    .enable_informational();

// 2. Use in service handler
async fn handle(mut req: Request<Incoming>) -> Result<Response<String>, Error> {
    if let Ok(mut pusher) = early_hints_pusher(&mut req) {
        let hints = Response::builder()
            .status(StatusCode::EARLY_HINTS)
            .header("link", "</style.css>; rel=preload; as=style")
            .header("link", "</app.js>; rel=preload; as=script")
            .body(())
            .unwrap();
        
        let _ = pusher.send_hints(hints).await;
    }
    
    Ok(Response::new("<!DOCTYPE html>...".to_string()))
}

Use Cases Supported

  • 103 Early Hints: Enable early resource discovery and preloading for web performance optimization
  • 100 Continue: Support request/response optimization for large payloads
  • Resource Preloading: CSS, JavaScript, fonts, images, and fetch resources
  • CDN Preconnection: Early connection establishment to external domains
  • Progressive Enhancement: Multiple hint responses as server processing progresses

Technical Implementation

  • Builder opt-in pattern ensures zero overhead when feature not used (default state)
  • Informational responses sent without END_STREAM flag to maintain connection
  • Stream state management preserves HTTP/2 flow control during informational responses
  • Client callback system separates informational processing from main response flow
  • Server extension system allows middleware and applications to send hints seamlessly
  • Cross-origin security validated for redirect scenarios
  • Backward compatibility maintained - existing code continues to work unchanged

Standards Compliance

  • RFC 8297: Complete HTTP Status Code 103 Early Hints implementation
  • RFC 7540: HTTP/2 specification compliance for informational responses
  • HTTP/2 HPACK: Proper header compression handling for multiple Link headers
  • Browser Security: Cross-origin redirect protection and validation

Migration Path

This implementation is fully backward compatible with opt-in behavior:

No Changes Required

Existing applications continue to work unchanged with zero performance impact.

To Enable Feature

Add single builder method call:

// Before: Feature automatically disabled
let builder = http2::Builder::new(executor);

// After: Single line to enable
let builder = http2::Builder::new(executor)
    .enable_informational();

Then use early_hints_pusher() in handlers:

if let Ok(mut pusher) = early_hints_pusher(&mut req) {
    pusher.send_hints(hints).await?;
}

No breaking changes. Pay only for what you use.


Browser Tests

  • Chrome:
Screenshot 2025-12-09 at 5 27 54 AM
  • Firefox:
Screenshot 2025-12-09 at 5 29 33 AM

The implementation provides a robust foundation for web performance optimization while maintaining the reliability and safety expected from the hyper HTTP library.

Resolves #3980 and #2426 for HTTP/2 103 Early Hints support and extends the informational responses capability for HTTP/2 protocols.



Revision 2

Addresses @JakubKoralewski 's feedback

This implementation addresses all concerns raised during code review:

  1. Unconditional allocation → Builder opt-in with zero-cost default
  2. API design consistency → Follows informational_pusher pattern
  3. Performance impact → Zero overhead when disabled
  4. Redundant feature gates → Removed unnecessary annotations
  5. Dependency version → h2 = 0.4.13
  6. Example quality → Only critical resources hinted
  7. Polling optimization → Restricted to Service state only

@apu031
Copy link
Author

apu031 commented Dec 9, 2025

Hello @dicej , @pablocm, @vikanezrimaya, @nox, @seanmonstar!

My commit originally builds on @dicej's prototype commit 4e2483a in PR - #3815. However, this code is obsolete and does not build anymore. Therefore, I have included both the commits in my PR. @seanmonstar @nox let me know if this would be the right way to move forward.

The code changes follow the proposed public API suggested from @vikanezrimaya. After merging this, I will release a PR for Axum wrapper.

Note - The tests will pass once we merge the h2 repo's PR - hyperium/h2#865

Thank you very much once again for your time and support. 🙏🏼

This is a prototype intended to spur discussion about what support for 1xx
informational responses should look like in a Hyper server.  The good news is
that it works great (for HTTP/1 only, so far).  The bad news is it's kind of
ugly.  Here's what I did:

- Add `ext::InformationalSender`, a type which wraps a
  `futures_channel::mspc::Sender<Response<()>>`.  This may be added as an
  extension to an inbound `Request` by the Hyper server, and the application
  and/or middleware may use it to send one or more informational responses
  before sending the real one.

- Add code to `proto::h1::dispatch` and friends to add such an extension to each
  inbound request and then poll the `Receiver` end along with the future
  representing the final response.  If the app never sends any informational
  responses, then everything proceeds as normal.  Otherwise, we send those
  responses as they become available until the final response is ready.

TODO items:
- [ ] Also support informational responses in the HTTP/2 server.
- [ ] Determine best way to handle when the app sends an informational response
  with a non-1xx status code.  Currently we just silently ignore it.
- [ ] Come up with a less hacky API?
- [ ] Add test coverage.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
Copy link

@JakubKoralewski JakubKoralewski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I'm interested in 10x support so thought I'd contribute a review. Thanks for this work. I am not a contributor just hope to make it easier to review for someone in charge.

Add HTTP/2 103 Early Hints implementation with client and server support:

- Add builder opt-in pattern via enable_informational() for zero-cost abstraction
- Create early_hints_pusher() API for server-side hint transmission via mpsc channel
- Add InformationalCallback system for client-side informational response handling
- Extend HTTP/2 client builder with informational_responses() configuration method
- Implement informational response polling in h2 client task with callback invocation
- Add server-side informational response forwarding using h2's send_informational API
- Include test coverage: 11 integration tests, 18 unit tests, 2 doc tests
- Add complete working example with TLS, resource preloading, and performance monitoring
- Update Cargo.toml with h2 = 0.4.13 dependency requirement

The implementation enables servers to send resource preload hints before final responses,
allowing browsers to start downloading critical resources early and improve page load
performance. Feature is opt-in and disabled by default for zero overhead when not used.
Clients can register callbacks to process 103 Early Hints and other informational responses.

Closes hyperium#3980, hyperium#2426
@apu031
Copy link
Author

apu031 commented Feb 5, 2026

Hi, I'm interested in 10x support so thought I'd contribute a review. Thanks for this work. I am not a contributor just hope to make it easier to review for someone in charge.

Hey Jakub (@JakubKoralewski),

I wanted to take a moment to express my sincere gratitude for the exceptional code review you provided on this PR. Your thorough analysis and insightful feedback have been absolutely invaluable, and I genuinely mean it when I say this PR is significantly better because of your input.

@apu031
Copy link
Author

apu031 commented Feb 5, 2026

Hey @seanmonstar, and @nox!

I guess things are going super busy as the new year started. Truly appreciate your feedback and effort on the last hyperium/h2#865.

Could you please take a look into this PR?

Hopefully, we get it merged soon for everyone to use it.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add HTTP/2 103 Early Hints Support to Hyper

3 participants