Capturing Traffic Data

When writing HTTP rules in HAProxy, the running context is important: you are either at the request time or at the response time. Each context is isolated, which means that you cannot use an HTTP header found in the request when processing the response.

Hence, capturing data from traffic allows you to reuse that data at any time in the session.

To do this, you declare capture slots in HAProxy, store data in these slots, and use them when required, such as:

  • during the request processing
  • during the response processing
  • for logging

Declaring Capture Slots

A slot is a memory area where HAProxy stores captured data. It is identified by an <id> (number).

There is no limit to the number of slots; HAProxy just consumes more memory.

HAProxy allocates capture slots when parsing configuration and automatically creates the <id> .

Declare a slot

The following directive declares explicitly a slot for capture purposes. It must be configured in a front end section:

declare capture [ request | response ] len <length>

With the following parameters:

[ request | response ] Context where this slot is to be used
len <length> Number of characters to capture

Declare a slot and capture data

The following directives are only available in a frontend section:

capture cookie <name> len <length>
capture request header <name> len <length>
capture response header <name> len <length>
tcp-request content <sample> len <length>
tcp-response content <sample> len <length>
http-request capture <sample> len <length>
http-response capture <sample> len <length>

With the following parameters:

  <name> Name of the HTTP header field to capture
  <sample> A sample fetch to capture any kind of data
 
tcp-request content and tcp-response content rules Sample fetches from internal states, Layer 4, Layer 5 and Layer 6
http-request and http-response rules Any of the sample fetch
len <length> Number of characters to capture

Manage capture slots

Bear in mind that capture slot IDs are unique and common to the different ways used to capture data.

The following directives create an implicit new slot ID and allocates memory for it:

  • declare capture
  • capture request
  • capture response
  • http-request capture <sample> len <length>
  • http-response capture <sample> len <length>

HAProxy creates implicit <id> numbers in the exact order as the rules above are written. This means that when you add a rule before another one, you change the <id>.

Warning: When adding or removing rules, always check there is no impact on the data capture or data access.

Capturing Data

The following directives are only available in a frontend section and can be used to capture data from the traffic:

http-request capture <sample> id <id>
http-response capture <sample> id <id>

With the following parameters:

<sample> a sample fetch to capture any kind of data
id <id> slot ID where to store captured data

Accessing Captured Data

The following sample fetches are available to access captured data:

capture.req.hdr(<id>)
capture.res.hdr(<id>)

With the following parameter:

id <id> slot ID from which to retrieve captured data

Configuration examples

Declare capture slots:

The configuration below declares 3 slots (0, 1 and 2).

  • slot 0 can be used by http-request ... id 0 or http-response ... id 0 capture rules
  • slot 1 captures directly the User-Agent header
  • slot 2 is reserved to capture the response header named Server:
frontend f_myapp
  declare capture request len 32               # implicit id 0
  capture request header User-Agent len 64     # implicit id 1
  http-response capture res.hdr(Server) len 32 # implicit id 2

Insert a cookie if none presented by the client

The HTTP Host header is sent by clients and may be needed it to perform HTTP redirection.

frontend f_myapp
  declare capture request len 1
  # capture slot '0' contains a boolean based on FirstVisit cookie sent by client:
  #  . 0 (false) if none
  #  . 1 (true)  if at least one
  http-request capture req.cook_cnt(FirstVisit),bool id 0
  # send a cookie if the client did not send one:
  http-response add-header Set-Cookie "FirstVisit: yes" if { capture.req.hdr(0) eq 0 }

Log captured data

Capture the destination IP (from a client) and log it:

frontend f_myapp
  tcp-request content capture dst len 15
  log-format %[capture.req.hdr(0)]
In this case, simply use the %fi log-format variable.