Multiplexer is a remap plug-in that allows requests to certain origins to be multiplexed (i.e., duplicated and dispatched in parallel) to one or more other hosts. The headers are copied into the new requests as well as POST bodies. Optionally POST and PUT requests can be skipped via pparam=proxy.config.multiplexer.skip_post_put=1.


Multiplexer does the following for requests it is configured to multiplex:

  1. Add the X-Multiplexer: original header into the client’s request.

  2. For each host in pparam of the remap rule:

    1. Copies the resulting request (POST bodies are copied via the HTTP Transform mechanism).

    2. Changes the Host header of the copy according to pparam from the remap rule.

    3. Changes X-Multiplexer header value to copy instead of original.

    4. Asynchronously sends the copied request with TSHttpConnect().

    5. The copied request with the specified host is then itself processed via remap.config.

Multiplexer dispatches the requests in the background without blocking the original request. Multiplexed responses are drained and discarded. Note that you will need remap.config entries for the multiplexed hosts. If no such rules exist, the plugin will internally receive the typical 404 response for the multiplexed request since a matching remap entry for the multiplexed host will not be found, with the result that no request will be sent to that host. When creating the remap.config entries for the multiplexed hosts, be aware that the multiplexed requests will be originated with the HTTP scheme (not HTTPS), and therefore the corresponding “from” URL of the remap rule should be constructed with the http:// scheme prefix. See the sample remap.config rules below for example Multiplexer entries.

A default 1 second timeout is configured when communicating with each of the hosts receiving the multiplexed requests. This timeout can be overwritten via the multiplexer__timeout environment variable representing how many nanoseconds to wait.

The multiplexer debug tag can be used for debugging purposes (see proxy.config.diags.debug.tags). While debugging, multiplexed requests and responses are printed into the logs.

Multiplexer produces the following statistics consumed with traffic_ctl:

  • failures: number of failed multiplexed requests

  • hits: number of successful multiplexed requests

  • requests: total number of multiplexed requests

  • time(avg): average time taken between multiplexed requests and their responses

  • timeouts: number of multiplexed requests which timed-out

  • size(avg): average size of multiplexed responses

Here are some example remap.config configuration lines:



map @pparam=proxy.config.multiplexer.skip_post_put=1
  1. The first entry will multiplex requests sent to with a path of /a to The remap rule specifies that the multiplexed requests to host1 will be sent over HTTP.

  2. The second entry will multiplex requests sent to with a path of /b to The remap rule specifies that the multiplexed requests to host2 will be sent over HTTPS.

  3. The third entry will multiplex HTTPS requests sent to with a path of /c to both and

  4. The fourth entry will multiplex requests sent to with a path of /d to both and, but POST and PUT requests will not be multiplexed.


Parsing Chunk Encoded Data

Multiplexer parses chunked data with its own home brew parser. In the parser size_ is the size of a chunk to be consumed. The local variable / parameter size is raw input size as read from an TSIOBufferBlock. The “size states” are marked blue.


skinparam state {
   backgroundColor<<SIZE_STATE>> SkyBlue

state kSize <<SIZE_STATE>>
kSize : Accumulate size_\nfrom hex input.
[*] --> kSize
kSize --> kSize : hex digit
kSize --> kDataN : CR,size_ > 0
kSize --> kEndN : CR, size_ == 0
kSize --> kInvalid : *

state kDataN <<SIZE_STATE>>
kDataN --> kData : LF
kDataN --> kInvalid : *
kDataN : ASSERT(size_ > 0)

state kEndN <<SIZE_STATE>>
kEndN --> kEnd : LF
kEndN --> kInvalid : *

kData : Consume size_\nbytes of input.
kData --> kSizeR : Input consumed

state kSizeR <<SIZE_STATE>>
kSizeR --> kSizeN : CR
kSizeR --> kInvalid : *

state kSizeN <<SIZE_STATE>>
kSizeN --> kSize : LF
kSizeN --> kInvalid : *

kInvalid --> [*]
kEnd --> [*]