Configuration: HTTP buffering

This page documents the buffer_request and buffer_response directives for configuring HTTP body buffering in Ferron. Buffering collects incoming request bodies and outgoing response bodies up to a configured size limit, which can serve as an additional protection layer against Slowloris-style attacks and help control memory consumption for large payloads.

Request and response buffering

{
    buffer_request 8192
    buffer_response 65536
}

example.com {
    buffer_request 16384
    buffer_response 0
}

Both directives accept an integer value (buffer size in bytes) and can be configured at global or HTTP host scope. When set, the server buffers up to the specified number of bytes before passing the body downstream. Bodies larger than the buffer limit are still served, but the initial portion is collected first.

Global buffering directives

DirectiveArgumentsDescriptionDefault
buffer_request<int>This directive specifies the buffer size in bytes for incoming HTTP request bodies. Buffering request bodies can protect backend servers from Slowloris-style attacks by collecting the body before processing.disabled
buffer_response<int>This directive specifies the buffer size in bytes for outgoing HTTP response bodies. Buffering responses can help control memory usage and ensure consistent delivery to clients.disabled

Configuration example:

{
    buffer_request 8192
    buffer_response 32768
}

example.com {
    buffer_request 16384
}

Behavior

Request buffering

When buffer_request is configured:

  • The server collects incoming request body frames up to the configured byte limit.
  • If the request body is smaller than the buffer limit, the entire body is collected before downstream stages (like reverse proxy or authentication) process it.
  • If the request body exceeds the buffer limit, the buffered portion is collected and the remaining body stream is preserved. Downstream stages receive a chained stream consisting of the buffered frames followed by the remaining body.
  • Non-data frames (such as trailing headers) are preserved and stop further collection.

Response buffering

When buffer_response is configured:

  • The server collects outgoing response body frames up to the configured byte limit.
  • Similar to request buffering, the response body is split into buffered frames (up to the limit) and a remaining stream (if the body exceeds the limit).
  • The buffered response is reassembled and sent to the client as a chained stream.
  • Response buffering only applies to custom responses generated by the pipeline. Built-in error responses are not buffered.

Buffering and pipeline stages

The buffer stage runs early in the HTTP pipeline, after URL rewriting but before rate limiting, authentication, caching, reverse proxy, and static file stages. This ordering ensures that request bodies are buffered before they reach backend handlers.

Notes and troubleshooting

  • Disabled by default: Both buffer_request and buffer_response are disabled unless explicitly configured. This avoids unnecessary memory overhead when buffering is not needed.
  • Choosing buffer sizes: Set buffer sizes based on your expected request/response payload sizes. Typical values range from 4 KB to 64 KB. Setting the buffer too small provides little benefit; setting it too large increases memory consumption per request.
  • Slowloris protection: Request buffering is one layer of defense against Slowloris attacks. You should also configure the timeout directive to enforce connection timeouts. See ./core-directives.md for the timeout directive.
  • Memory considerations: Each active connection uses memory proportional to the buffer size when buffering is enabled. Under high concurrency, large buffer sizes can increase memory pressure. Monitor memory usage and adjust buffer sizes accordingly.
  • Disabling buffering: To disable inherited buffering at a specific host scope, set the directive to 0 (zero bytes) or remove the directive entirely if no parent scope configures it.