ZIO HTTP

repository·main·Indexed 21 days ago

https://github.com/zio/zio-http

A high-performance, type-safe Scala library for building web applications and HTTP clients, powered by the ZIO effect system and Netty. It features a type-driven API, support for WebSockets, OpenAPI integration, and a dedicated testkit for direct route, client, and server testing. The ecosystem also includes zio-http-stomp for STOMP protocol support (versions 1.0, 1.1, and 1.2).

Tokens
176.2K
Snippets
510
Records
651
Agent score
74%

What's inside zio-http

  1. Introduction to Template2 DSL

    main

    ZIO HTTP Template2 is a type-safe HTML templating DSL for Scala. It allows you to write HTML, CSS, and JavaScript directly in Scala code with compile-time checking. It is designed for composability (building components as Scala functions) and eliminates the need for separate template files.

    import zio.http.template2._
    
    val page: Dom =
      html(
        head(title("Hello World")),
        body(
          h1("Hello, ZIO HTTP Template2!"),
          p("This is my first template.")
        )
      )
  2. Understand the fundamentals of SSL/TLS and PKI in ZIO HTTP

    main

    ZIO HTTP supports securing communication between clients and servers using SSL/TLS protocols. This is achieved through a Public Key Infrastructure (PKI), which uses digital certificates to verify identities and establish encrypted connections.

    Key concepts:

    • SSL/TLS: Cryptographic protocols for secure communication. TLS is the modern, secure successor to SSL.
    • PKI (Public Key Infrastructure): The framework of digital certificates and public/private key pairs used to verify identities.
    • Digital Certificate: A document binding a public key to an entity (e.g., a server domain).
    • Certificate Authority (CA): A trusted third party that verifies identities and signs certificates to create a chain of trust.

    ZIO HTTP provides implementation paths for various security levels, including self-signed certificates, Root CA-signed certificates, Intermediate CA-signed certificates, and Mutual TLS (mTLS).

  3. Key features of ZIO HTTP

    main

    ZIO HTTP provides several high-level capabilities for modern web development:

    • Imperative and Declarative Endpoints: Choose between defining logic and shape together (imperative) or separating the endpoint description from its logic (declarative).
    • Type-Driven API: Leverages Scala's type system to ensure implementation matches the endpoint description at compile time.
    • Middleware: Support for cross-cutting concerns like logging, metrics, and authentication.
    • WebSockets: Built-in support for real-time applications.
    • JSON and Binary Codecs: Integration with ZIO Schema for encoding/decoding JSON, Protobuf, Avro, and Thrift.
    • OpenAPI Support: Generate OpenAPI documentation from endpoints or generate endpoints from OpenAPI specs.
    • Testkit: First-class testing utilities to test logic without a live server.
    • Template System: A DSL for writing HTML templates using Scala code.
  4. What is a Form and FormField in ZIO HTTP

    main

    A Form is a collection of FormField objects, representing either a multipart or a URL-encoded form. It is used to handle data from HTML forms and file uploads in request bodies, or to construct response bodies.

    Each FormField consists of a name, a contentType, type-specific content, and an optional filename.

    final case class Form(formData: Chunk[FormField])
  5. What is an HttpCodec and how does it work?

    main

    In ZIO HTTP, HttpCodec is an abstraction used to bridge the gap between raw HTTP messages (Request and Response) and structured Scala data. It acts as a pair of functions for both encoding and decoding values.

    An HttpCodec defines how to:

    1. Decode: Transform a Request or Response into a structured Value.
    2. Encode: Transform a Value back into a Request or Response.

    ZIO HTTP provides specialized versions of this trait for different parts of an HTTP message, such as the body (Content), headers, methods, query parameters, and status codes.

    sealed trait HttpCodec[-AtomTypes, Value] {
      final def decodeRequest(request: Request)(implicit trace: Trace): Task[Value]
      final def decodeResponse(response: Response)(implicit trace: Trace): Task[Value]
    
      final def encodeRequest(value: Value): Request
      final def encodeResponse[Z](value: Value, outputTypes: Chunk[MediaTypeWithQFactor]): Response
    }
  6. What is the Endpoint API and how to use it

    main

    The Endpoint API is a high-level, declarative DSL used to describe HTTP endpoints. Instead of manually handling routes and parsing logic, you define the endpoint's structure (path, method, inputs, and outputs) and then implement the logic separately.

    Key benefits include:

    • Type Safety: The compiler ensures your implementation handler matches the defined input types.
    • Documentation: Automatically generates OpenAPI documentation.
    • Client Generation: Enables the generation of clients based on the endpoint definitions.

    To use it, you define an Endpoint and then call .implement(handler) where the handler is a function that returns a Route.

    import zio.http.endpoint.Endpoint
    import zio.http.RoutePattern
    
    // 1. Define the endpoint
    val endpoint = Endpoint(RoutePattern.GET / "books")
      .query(HttpCodec.query[String]("q"))
      .out[List[Book]]
    
    // 2. Implement the logic
    val route = endpoint.implement(query => BookRepo.find(query))
  7. What is the Body abstraction in ZIO HTTP?

    main

    Body is a domain model used to represent content within Request and Response objects. It acts as an abstraction layer over Netty's ByteBuf, allowing you to work with higher-level data types like strings, JSON, files, or ZIO Streams.

    Depending on the source, a Body can be represented as:

    • A fixed chunk of bytes
    • A stream of bytes (for large or unknown-length content)
    • Form data (Multipart or URL-encoded)
    • Any type that can be encoded via ZIO Schema or ZIO JSON.
  8. Overview of ZIO HTTP testing patterns

    main

    ZIO HTTP provides three distinct testing patterns depending on the scope and complexity of your test:

    1. Direct Route Testing: Invokes a Handler directly as a pure function. Best for unit testing individual handlers, request parsing, and validation logic in isolation without any network infrastructure.
    2. TestClient: A mock HTTP client implementation. Use this when your application depends on external HTTP services and you want to mock those dependencies by defining specific request/response mappings.
    3. TestServer: Starts a test server that responds to HTTP requests based on your routes. Best for integration testing multiple routes working together or verifying the exact requests made by your application code.
  9. What is TestServer and when to use it

    main

    Concept: TestServer

    TestServer is an integration testing HTTP server that simulates a real server listening on localhost. It is designed to run your routes in-process, providing a realistic request/response cycle through the full HTTP stack while remaining fast and deterministic.

    Key Characteristics:

    • Localhost Binding: Binds to an automatically assigned port on localhost. It uses real network I/O (loopback) but eliminates external network latency and disk I/O.
    • Mutable Configuration: You can dynamically add routes or exact request/response mappings during test execution.
    • Standard Interface: It implements the Server trait, meaning it works seamlessly with the standard Client interface.

    When to use it: Use TestServer instead of unit testing individual handlers when you need to test:

    • Multiple routes working together.
    • Route precedence (which route matches first).
    • State persistence across multiple sequential requests.
    • Complete feature workflows involving the full HTTP stack.
  10. What is TestClient and when to use it

    main

    TestClient is an in-memory HTTP client driver used for mocking external API dependencies in tests. Instead of making real network calls, it intercepts requests and returns configured responses synchronously and in-memory.

    Use TestClient when:

    • Your code depends on external HTTP APIs (e.g., payment processors, auth services).
    • You want to avoid slow or unreliable network I/O in CI/CD.
    • You need to test edge cases like 5xx errors, timeouts, or specific rate-limit responses.
    • You want to verify that your application is constructing outgoing requests correctly.

    Relationship to other types:

    • TestServer: Use TestServer to test your own routes; use TestClient to mock the external services your routes call.
    • TestChannel: Used for testing WebSocket communication.
    • HttpTestAspect: Used for testing mode-dependent behavior.
  11. What is Middleware in ZIO-HTTP

    main

    Middleware is a functional component used to address cross-cutting concerns (like logging, authentication, or timeouts) without duplicating boilerplate code in your business logic. It follows the Aspect-oriented Programming paradigm, allowing you to separate core logic from secondary features.

    A Middleware is parameterized by a contravariant type UpperEnv, meaning it can access the environment of the Routes it is applied to. Conceptually, a middleware accepts a Routes object and returns a new, transformed Routes object.

    trait Middleware[-UpperEnv] {
      def apply[Env1 <: UpperEnv, Err](routes: Routes[Env1, Err]): Routes[Env1, Err]
    }
  12. What is TestChannel and when to use it

    main

    A TestChannel is an in-memory, bidirectional message channel designed for testing WebSocket handlers in zio-http. It simulates a WebSocket connection between a client and a server without requiring real network I/O.

    Key Benefits:

    • Fast & Deterministic: Executes instantly in-memory without network latency or flakiness.
    • Bidirectional: Both client and server can send and receive messages independently.
    • Full Protocol Support: Supports all WebSocket frame types (text, binary, control frames).
    • Lifecycle Control: Handles handshakes and graceful shutdowns via shared promises.

    When to use it: Use TestChannel when you need to verify:

    • WebSocket echo handlers.
    • Publish-subscribe message brokers.
    • Real-time notification systems.
    • Bidirectional request-reply patterns.
    • Connection lifecycle events (handshake, close, error handling).