xitca-web

repository·main·Indexed 21 days ago

https://github.com/hfqr/xitca-web

A high-performance HTTP library and web framework written in safe Rust, featuring a low-memory footprint and zero-copy serialization/deserialization. The ecosystem includes specialized crates for gRPC codecs, multipart/form-data parsing, rate limiting, WebSockets, and asynchronous PostgreSQL integration via xitca-postgres. It supports compilation for the wasm32-wasip1-threads target using Wasmtime.

Tokens
72.9K
Snippets
240
Records
317
Agent score
76%

What's inside xitca-web

  1. Overview of the gRPC codec crate

    main

    This crate provides a gRPC codec implementation designed for HTTP types. It handles the gRPC length-prefixed framing and manages the encoding/decoding of Protobuf messages using prost.

    Key capabilities include:

    • Framing: Implements gRPC length-prefixed framing.
    • Streaming: Supports request stream decoding and response body encoding using the http_body_alt::Body trait.
    • Compression: Provides optional support for brotli, gzip, deflate, and zstd compression algorithms.
  2. Overview of async network IO traits and types

    main
    The io module provides asynchronous network I/O traits and types designed to work with both tokio and tokio-uring runtimes. It serves as a foundational layer for handling asynchronous input/output operations within the xitca-web ecosystem.
  3. Overview of the xitca-web router

    main

    The router in xitca-web is a fork of the matchit crate. It is designed to provide a routing mechanism that prioritizes ease of use and safety over raw micro-benchmark performance.

    Key Characteristics

    Pros:

    • Clean Public Types: The router avoids lifetime pollution in its public types, making it significantly easier to pass route parameters around your application.
    • 100% Safe Rust: The router implementation itself is written entirely in safe Rust (though it may rely on dependencies that use unsafe).

    Cons:

    • Immutable Router Value: Once the router is initialized, its value is immutable.
    • Performance: It may be potentially slower in micro-benchmarks compared to the original matchit.
  4. Overview of http-multipart

    main
    The http-multipart crate provides asynchronous multipart/form-data parsing for HTTP. It is designed for high performance through in-place streaming parsing, which minimizes memory copies and additional allocations. It focuses on stack-pinned streaming types to provide native async/await support.
  5. Overview of the http-ws crate

    main
    The http-ws crate provides an asynchronous WebSocket implementation designed for easy integration with existing HTTP ecosystems. It leverages common HTTP types and streaming interfaces to ensure compatibility with standard Rust web development patterns.
  6. Overview of xitca-web features

    main

    xitca-web is a composable Rust async web framework designed with the following core principles:

    • 100% safe Rust: Built entirely using safe Rust code.
    • Composable API: Provides high-level APIs for common usage while allowing easy extension or mixing with mid-level and low-level components.
    • Static Typing: Emphasizes static typing to minimize the need for runtime dynamic type casting.
    • Efficiency: Maintains a minimal dependency tree to ensure fast compile times.
  7. Features of xitca-postgres

    main

    SSL/TLS Support

    Powered by rustls.

    QUIC Transport Layer

    Offers a transparent QUIC transport layer and proxy for lossy remote database connections.

    Connection Pool

    Built-in connection pool with pipelining support enabled.

    io_uring Support

    Uses tokio-uring-xitca for completion-based async IO via the TCP network layer. Note: This requires the nightly Rust compiler.

  8. Key features of the http-body-alt crate

    main

    The http-body-alt crate provides an alternative implementation of the http-body trait designed to address specific limitations in the original crate. Key improvements include:

    • Explicit Empty Body Support: Uses SizeHint::None to clearly express when there is no HTTP body.
    • Stream Integration: Implements the futures::Stream trait directly for the body type, which helps avoid unnecessary adapter nesting.
    • Simplified Pattern Matching: Makes Frame::Data and Frame::Trailers public, allowing for simpler and more direct pattern matching when processing body frames.
  9. Key Features of xitca-web

    main

    xitca-web is a 100% safe Rust HTTP library and web framework providing:

    • Protocol Support: HTTP/1.x, HTTP/2, and HTTP/3.
    • Routing: Powerful request routing with optional opt-in macros.
    • Ecosystem Compatibility: Full Tokio compatibility and cross-crate integration with Tower.
    • WebSockets: Support for both client and server WebSockets.
    • Content Handling: Transparent compression/decompression (br, gzip, deflate, zstd) and multipart streams.
    • Security: SSL support via Xitca-tls or rustls.
    • Extensibility: Middleware support (e.g., Logger, Tracing) and static asset serving.
  10. How tokio-uring manages in-flight operation state

    main

    In tokio-uring, asynchronous operations (like reads or writes) reference resources such as buffers and file descriptors that must remain valid and untouched by the application while the kernel is using them. Because Rust futures can be dropped at any time, tokio-uring solves the memory safety problem by taking ownership of these resources and storing them in an internal in_flight_operations store (using a Slab).

    Lifecycle of an Operation

    1. Submission: When a task starts an operation, the runtime allocates an Operation entry, stores the buffer, and sets the lifecycle to Submitted. The operation is pushed to the submission queue.
    2. Execution: The operation remains in-flight. The runtime delays synchronization with the kernel until the task yields, allowing for batching of multiple operations to reduce latency.
    3. Completion: When the kernel returns a result via the completion queue, the runtime updates the lifecycle to Completed and notifies the task's Waker.
    4. Cancellation (Drop): If a future is dropped before completion:
      • If the request is still in the submission queue, it is removed.
      • If it is already in-flight, the runtime submits a best-effort cancellation request to the kernel and sets the lifecycle to Ignored. The runtime continues to hold the internal state until the kernel eventually completes the operation to ensure memory safety.
    struct Operation {
        state: State,
        lifecycle: Lifecycle,
    }
    
    enum Lifecycle {
        Submitted,
        Waiting(Waker),
        Ignored,
        Completed(Completion),
    }
  11. Manage buffers with IoBuf

    main

    In tokio-uring, buffers used for read and write operations must remain alive and pinned in memory while the operation is in-flight. Because of this, standard &mut [u8] slices cannot be used. Instead, use the IoBuf type provided by the crate.

    IoBuf can be either individually heap-allocated or checked out from a pre-registered buffer pool managed by io-uring.

    Important Safety Note: IoBuf and buffer pools are !Send. They must remain on the same thread that checked them out to ensure safe return to the pool or kernel.

    // Individually heap-allocated
    let my_buf = IoBuf::with_capacity(4096);
    
    // Checked-out from a pool
    match my_buffer_pool.checkout() {
        Ok(io_buf) => ...,
        Err(e) => panic!("buffer pool empty"),
    }
  12. Work with byte streams (TcpStream, File streams)

    main

    Byte stream types like TcpStream manage their own buffers internally. Instead of passing a buffer to a read method, you interact with the stream using buffered I/O patterns (implementing AsyncBufRead).

    Standard Buffered I/O

    Use fill_buf() to get a view of the internal buffer and consume() to mark data as processed.

    Zero-copy Piping

    For high-performance data transfer between two streams, use take_read_buf() to extract an IoBuf from a source stream and place_write_buf() to provide it to a destination stream.

    File Streams

    Unlike TcpStream, the File type does not provide a single byte stream. Instead, you request specific read_stream() or write_stream() handles. These streams maintain their own cursors, allowing for concurrent positional I/O on the same file.

    // Standard buffered I/O pattern
    let data: &[u8] = my_stream.fill_buf().await?;
    my_stream.consume(data.len());
    
    // Zero-copy piping pattern
    my_tcp_stream.fill_buf().await?;
    let buf: IoBuf = my_tcp_stream.take_read_buf();
    
    // ... mutate buf if needed ...
    
    my_other_stream.place_write_buf(buf);
    my_other_stream.flush().await?;
    
    // File stream pattern
    let read_stream = my_file.read_stream();
    let write_stream = my_file.write_stream();
    
    let buf: IoBuf = read_stream.take_read_buf().await?;
    write_stream.place_write_buf(buf).await?;
    write_stream.flush().await?;