Skip to content

HTTP

This page explains how Palfrey handles HTTP requests and responses.

Request lifecycle

  1. read and parse request head (method, target, version, headers)
  2. read body via Content-Length or chunked transfer
  3. build HTTP ASGI scope
  4. run app receive/send flow
  5. serialize and write response

Body-reading example:

from __future__ import annotations


async def read_body(receive):
    """Collect request body chunks into one byte string."""
    body = b""
    more_body = True
    while more_body:
        message = await receive()
        body += message.get("body", b"")
        more_body = message.get("more_body", False)
    return body


async def app(scope, receive, send):
    """Echo request size in plain text."""
    if scope["type"] != "http":
        return

    body = await read_body(receive)
    response = f"Received {len(body)} bytes".encode()
    await send(
        {
            "type": "http.response.start",
            "status": 200,
            "headers": [
                (b"content-type", b"text/plain; charset=utf-8"),
                (b"content-length", str(len(response)).encode("ascii")),
            ],
        }
    )
    await send({"type": "http.response.body", "body": response})

Streaming response example:

from __future__ import annotations

import asyncio


async def app(scope, receive, send):
    """Send a chunked response with small delays."""
    if scope["type"] != "http":
        return

    await send(
        {
            "type": "http.response.start",
            "status": 200,
            "headers": [(b"content-type", b"text/plain; charset=utf-8")],
        }
    )

    for chunk in (b"chunk-1\n", b"chunk-2\n", b"chunk-3\n"):
        await send({"type": "http.response.body", "body": chunk, "more_body": True})
        await asyncio.sleep(0.2)

    await send({"type": "http.response.body", "body": b"", "more_body": False})

Response behavior highlights

  • Content-Length is respected and validated
  • chunked responses are supported
  • keep-alive is decided from request/response semantics
  • configurable default headers (server, date)

Request safety controls

  • head/body size limits
  • optional concurrency limits
  • keep-alive timeout
  • backlog and graceful shutdown controls

Important edge cases

Expect: 100-continue

Palfrey supports the 100 Continue flow before body consumption.

HEAD requests

Headers are returned while body payload is suppressed.

Malformed requests

Palfrey returns protocol-appropriate error responses (for example 400).

Non-technical explanation

HTTP handling is a disciplined workflow:

  • read request clearly
  • process with app logic
  • send a standards-compliant reply
  • keep or close the connection safely