blob: 0831326449452b8ec91097a09d1e363adcadc0f3 [file] [log] [blame]
Christopher Fauletbda62e72019-07-12 15:05:58 +02001 -----------------------------------------------
2 HTX API
3 Version 1.0
Christopher Fauletd1ac2b92020-12-02 19:12:22 +01004 ( Last update: 2020-12-02 )
Christopher Fauletbda62e72019-07-12 15:05:58 +02005 -----------------------------------------------
6 Author : Christopher Faulet
7 Contact : cfaulet at haproxy dot com
8
91. Background
10
11Historically, HAProxy stored HTTP messages in a raw fashion in buffers, keeping
Ilya Shipitsin2075ca82020-03-06 23:22:22 +050012parsing information separately in a "struct http_msg" owned by the stream. It was
Christopher Fauletbda62e72019-07-12 15:05:58 +020013optimized to the data transfer, but not so much for rewrites. It was also HTTP/1
14centered. While it was the only HTTP version supported, it was not a
15problem. But with the rise of HTTP/2, it starts to be hard to still use this
16representation.
17
18At the first age of the HTTP/2 in HAProxy, H2 messages were converted into
19H1. This was terribly unefficient because it required two parsing passes, a
20first one in H2 and a second one in H1, with a conversion in the middle. And of
21course, the same was also true in the opposite direction. outgoing H1 messages
22had to be converted back in H2 to be sent. Even worse, because the H2->H1
23conversion, only client H2 connections were supported.
24
25So, to address all these problems, we decided to replace the old raw
26representation by a version-agnostic and self-structured internal HTTP
27representation, the HTX. As an additional benefit, with this new representation,
28the message parsing and its processing are now separated, making all the HTTP
Ilya Shipitsin2075ca82020-03-06 23:22:22 +050029analysis simpler and cleaner. The parsing of HTTP messages is now handled by
Christopher Fauletbda62e72019-07-12 15:05:58 +020030the multiplexers (h1 or h2).
31
32
332. The HTX message
34
35The HTX is a structure containing useful information about an HTTP message
36followed by a contiguous array with some parts of the message. These parts are
37called blocks. A block is composed of metadata (htx_blk) and an associated
38payload. Blocks' metadata are stored starting from the end of the array while
39their payload are stored at the beginning. Blocks' metadata are often simply
Ilya Shipitsin2075ca82020-03-06 23:22:22 +050040called blocks. it is a misuse of language that's simplify explanations.
Christopher Fauletbda62e72019-07-12 15:05:58 +020041
42Internally, this structure is "hidden" in a buffer. This way, there are few
43changes into intermediate layers (stream-interface and channels). They still
44manipulate buffers. Only the multiplexer and the stream have to know how data
45are really stored. From the HTX perspective, a buffer is just a memory
46area. When an HTX message is stored in a buffer, this one appears as full.
47
48 * General view of an HTX message :
49
50
51 buffer->area
52 |
53 |<------------ buffer->size == buffer->data ----------------------|
54 | |
55 | |<------------- Blocks array (htx->size) ------------------>|
56 V | |
57 +-----+-----------------+-------------------------+---------------+
58 | HTX | PAYLOADS ==> | | <== HTX_BLKs |
59 +-----+-----------------+-------------------------+---------------+
60 | | | |
61 |<-payloads part->|<----- free space ------>|<-blocks part->|
62 (htx->data)
63
64
65The blocks part remains linear and sorted. You may think about it as an array
66with negative indexes. But, instead of using negative indexes, we use positive
67positions to identify a block. This position is then converted to an address
68relatively to the beginning of the blocks array.
69
70 tail head
71 | |
72 V V
73 .....--+----+-----------------------+------+------+
74 | Bn | ... | B1 | B0 |
75 .....--+----+-----------------------+------+------+
76 ^ ^ ^
77 Addr of the block Addr of the block Addr of the block
78 at the position N at the position 1 at the position 0
79
80
Ilya Shipitsin2075ca82020-03-06 23:22:22 +050081In the HTX structure, 3 "special" positions are stored:
Christopher Fauletbda62e72019-07-12 15:05:58 +020082
83 - tail : Position of the newest inserted block
84 - head : Position of the oldest inserted block
85 - first : Position of the first block to (re)start the analyse
86
87The blocks part never wrap. If we have no space to allocate a new block and if
88there is a hole at the beginning of the blocks part (so at the end of the blocks
89array), we move back all blocks.
90
91
92 tail head tail head
93 | | | |
94 V V V V
95 ...+--------------+---------+ blocks ...----------+--------------+
96 | X== HTX_BLKS | | defrag | <== HTX_BLKS |
97 ...+--------------+---------+ =====> ...----------+--------------+
98
99
100The payloads part is a raw space that may wrap. You never access to a block's
101payload directly. Instead you get a block to retrieve the address of its
102payload.
103
104
105 +------------------------( B0.addr )--------------------------+
106 | +-------------------( B1.addr )----------------------+ |
107 | | +-----------( B2.addr )----------------+ | |
108 V V V | | |
109 +-----+----+-------+----+--------+-------------+-------+----+----+----+
110 | HTX | P0 | P1 | P2 | ...==> | | <=... | B2 | B1 | B0 |
111 +-----+----+-------+----+--------+-------------+-------+----+----+----+
112
113
114Because the payloads part may wrap, there are 2 usable free spaces:
115
Thayne McCombscdbcca92021-01-07 21:24:41 -0700116 - The free space in front of the blocks part. This one is used if and only if
117 the other one was not used yet.
Christopher Fauletbda62e72019-07-12 15:05:58 +0200118
119 - The free space at the beginning of the message. Once this one is used, the
120 other one is never used again, until a message defragmentation.
121
122
123 * Linear payloads part :
124
125
126 head_addr end_addr tail_addr
127 | | |
128 V V V
129 +-----+--------------------+-------------+--------------------+-------...
130 | HTX | | PAYLOADS | | HTX_BLKs
131 +-----+--------------------+-------------+--------------------+-------...
132 |<-- free space 2 -->| |<-- free space 1 -->|
133 (used if the other is too small) (used in priority)
134
135
136 * Wrapping payloads part :
137
138
139 head_addr end_addr tail_addr
140 | | |
141 V V V
142 +-----+----+----------------+--------+----------------+-------+-------...
143 | HTX | | PAYLOADS part2 | | PAYLOADS part1 | | HTX_BLKs
144 +-----+----+----------------+--------+----------------+-------+-------...
145 |<-->| |<------>| |<----->|
146 unusable free space unusable
147 free space free space
148
149
Ilya Shipitsin11057a32020-06-21 21:18:27 +0500150Finally, when the usable free space is not enough to store a new block, unusable
Christopher Fauletbda62e72019-07-12 15:05:58 +0200151parts may be get back with a full defragmentation. The payloads part is then
152realigned at the beginning of the blocks array and the free space becomes
153continuous again.
154
155
1563. The HTX blocks
157
158An HTX block can be as well a start-line as a header, a body part or a
159trailer. For all these types of block, a payload is attached to the block. It
Christopher Fauletd1ac2b92020-12-02 19:12:22 +0100160can also be a marker, the end-of-headers or end-of-trailers. For these blocks,
161there is no payload but it counts for a byte. It is important to not skip it
162when data are forwarded.
Christopher Fauletbda62e72019-07-12 15:05:58 +0200163
164As already said, a block is composed of metadata and a payload. Metadata are
165stored in the blocks part and are composed of 2 fields :
166
167 - info : It a 32 bits field containing the block's type on 4 bits followed
168 by the payload length. See below for details.
169
170 - addr : The payload's address, if any, relatively to the beginning the
171 array used to store part of the HTTP message itself.
172
173
174 * Block's info representation :
175
176 0b 0000 0000 0000 0000 0000 0000 0000 0000
177 ---- ------------------------ ---------
178 type value (1 MB max) name length (header/trailer - 256B max)
179 ----------------------------------
180 data length (256 MB max)
181 (body, method, path, version, status, reason)
182
183
184Supported types are :
185
186 - 0000 (0) : The request start-line
187 - 0001 (1) : The response start-line
188 - 0010 (2) : A header block
189 - 0011 (3) : The end-of-headers marker
190 - 0100 (4) : A data block
191 - 0101 (5) : A trailer block
192 - 0110 (6) : The end-of-trailers marker
Christopher Fauletbda62e72019-07-12 15:05:58 +0200193 - 1111 (15) : An unused block
194
195Other types are unused for now and reserved for futur extensions.
196
197An HTX message is typically composed of following blocks, in this order :
198
199 - a start-line
200 - zero or more header blocks
201 - an end-of-headers marker
202 - zero or more data blocks
203 - zero or more trailer blocks (optional)
204 - an end-of-trailers marker (optional but always set if there is at least
205 one trailer block)
Christopher Fauletbda62e72019-07-12 15:05:58 +0200206
207Only one HTTP request at a time can be stored in an HTX message. For HTTP
208response, it is more complicated. Only one "final" response can be stored in an
209HTX message. It is a response with status-code 101 or greater or equal to
Ilya Shipitsin2075ca82020-03-06 23:22:22 +0500210200. But it may be preceded by several 1xx informational responses. Such
Christopher Fauletd1ac2b92020-12-02 19:12:22 +0100211responses are part of the same HTX message.
Christopher Fauletbda62e72019-07-12 15:05:58 +0200212
Christopher Fauletd1ac2b92020-12-02 19:12:22 +0100213When the end of the message is reached a special flag is set on the message
214(HTX_FL_EOM). It means no more data are expected for this message, except
215tunneled data. But tunneled data will never be mixed with message data. Thus
216once the flag marking the end of the message is set, it is easy to know the
217message ends.
218
Christopher Fauletbda62e72019-07-12 15:05:58 +0200219
2203.1. The start-line
221
222Every HTX message starts with a start-line. Its payload is a "struct htx_sl". In
223addition to the parts of the HTTP start-line, this structure contains some
224information about the represented HTTP message, mainly in the form of flags
225(HTX_SL_F_*). For instance, if an HTTP message contains the header
226"conten-length", then the flag HTX_SL_F_CLEN is set.
227
228Each HTTP message has its own start-line. So an HTX request has one and only one
229start-line because it must contain only one HTTP request at a time. But an HTX
230response may have more than one start-line if the final HTTP response is
231precedeed by some 1xx informational responses.
232
233In HTTP/2, there is no start-line. So the H2 multiplexer must create one when it
234converts an H2 message to HTX :
235
236 - For the request, it uses the pseudo headers ":method", ":path" or
237 ":authority" depending on the method and the hardcoded version "HTTP/2.0".
238
239 - For the response, it used the hardcoded version "HTTP/2.0", the
240 pseudo-header ":status" and an empty reason.
241
242
2433.2. The headers and trailers
244
245HTX Headers and trailers are quite similar. Different types are used to simplify
246headers processing. But from the HTX point of view, there is no real difference,
247except their position in the HTX message. The header blocks always follow an HTX
248start-line while trailer blocks come after the data. If there is no data, they
249follow the end-of-headers marker.
250
251Headers and trailers are the only blocks containing a Key/Value payload. The
252corresponding end-of marker must always be placed after each group to mark, as
253it name suggests, the end.
254
255In HTTP/1, trailers are only present on chunked messages. But chunked messages
256do not always have trailers. In this case, the end-of-trailers block may or may
257not be present. Multiplexers must be able to handle both situations. In HTTP/2,
258trailers are only present if a HEADERS frame is sent after DATA frames.
259
260
2613.3. The data
262
263The payload body of an HTTP message is stored as DATA blocks in the HTX
264message. For HTTP/1 messages, it is the message body without the chunks
265formatting, if any. For HTTP/2, it is the payload of DATA frames.
266
267The DATA blocks are the only HTX blocks that may be partially processed (copied
268or removed). All other types of block must be entierly processed. This means
269DATA blocks can be resized.
270
271
2723.4. The end-of markers
273
Christopher Fauletd1ac2b92020-12-02 19:12:22 +0100274These blocks are used to delimit parts of an HTX message. It exists two
275markers :
Christopher Fauletbda62e72019-07-12 15:05:58 +0200276
277 - end-of-headers (EOH)
278 - end-of-trailers (EOT)
Christopher Fauletbda62e72019-07-12 15:05:58 +0200279
Christopher Fauletd1ac2b92020-12-02 19:12:22 +0100280EOH is always present in an HTX message. EOT is optional.
Christopher Fauletbda62e72019-07-12 15:05:58 +0200281
282
2834. The HTX API
284
285
2864.1. Get/set HTX message from/to the underlying buffer
287
288The first thing to do to process an HTX message is to get it from the underlying
289buffer. There are 2 functions to do so, the second one relying on the first:
290
291 - htxbuf() returns an HTX message from a buffer. It does not modify the
292 buffer. It only initialize the HTX message if the buffer is empty.
293
294 - htx_from_buf() uses htxbuf(). But it also updates the underlying buffer so
295 that it appears as full.
296
297Both functions return a "zero-sized" HTX message if the buffer is null. This
298way, you are sure to always have a valid HTX message. The first function is the
299default function to use. The second one is only useful when some content will be
300added. For instance, it used by the HTX analyzers when HAproxy generates a
301response. This way, the buffer is in a right state and you don't need to take
302care of it anymore outside the possible error paths.
303
304Once the processing done, if the HTX message has been modified, the underlying
305buffer must be also updated, except you uses htx_from_buf() and you only add
306data. For all other cases, the function htx_to_buf() must be called.
307
308Finally, the function htx_reset() may be called at any time to reset an HTX
309message. And the function buf_room_for_htx_data() may be called to know if a raw
310buffer is full from the HTX perspective. It is used during conversion from/to
311the HTX.
312
313
3144.2. Helpers to deal with free space in an HTX message
315
316Once you have an HTX message, following functions may help you to process it :
317
318 - htx_used_space() and htx_meta_space() return, respectively, the total
319 space used in an HTX message and the space used by block's metadata only.
320
321 - htx_free_space() and htx_free_data_space() return, respectively, the total
322 free space in an HTX message and the free space available for the payload
323 if a new HTX block is stored (so it is the total free space minus the size
324 of an HTX block).
325
326 - htx_is_empty() and htx_is_not_empty() are boolean functions to know if an
327 HTX message is empty or not.
328
329 - htx_get_max_blksz() returns the maximum size available for the payload,
330 not exceeding a maximum, metadata included.
331
332 - htx_almost_full() should be used to know if an HTX message uses at least
333 3/4 of its capacity.
334
335
3364.3. HTX Blocks manipulations
337
338Once you know how much space is available in an HTX message, the next step is to
339add HTX blocks. First of all the function htx_nbblks() returns the number of
340blocks allocated in an HTX message. Then, there is an add function per block's
341type:
342
343 - htx_add_stline() adds a start-line. The type (request or response) and the
344 flags of the start-line must be provided, as well as its three parts
345 (method,uri,version or version,status-code,reason).
346
347 - htx_add_header() and htx_add_trailers() are similar. The name and the
348 value must be provided. The inserted HTX block is returned on success or
349 NULL if an error occurred.
350
351 - htx_add_endof() must be used to add any end-of marker. The block's type
352 (EOH, EOT or EOM) must be specified. The inserted HTX block is returned on
353 success or NULL if an error occurred.
354
355 - htx_add_all_headers() and htx_add_all_trailers() add, respectively, a list
356 of headers and a list of trailers, followed by the appropriate end-of
357 marker. On success, this marker is returned. Otherwise, NULL is
358 returned. Note there is no rollback on the HTX message when an error
359 occurred. Some headers or trailers may have been added. So it is the
360 caller responsibility to take care of that.
361
362 - htx_add_data() must be used to add a DATA block. Unlike previous
363 functions, this one returns the number of bytes copied or 0 if nothing was
364 copied. If possible, the data are appended to the last DATA block, if
365 any. Only a part of the payload may be copied because this function will
366 try to limit the message defragmentation and the wrapping of blocks as far
367 as possible. If you really need to add all data or nothing, the function
368 htx_add_data_atonce() must be used instead. Because it tries to insert all
369 the payload, this function returns the inserted block on success.
370 Otherwise it returns NULL.
371
372When an HTX block is added, it is always the last one (the tail). But, if you
373need to add a block at a specific place, it is not really handy. 2 functions may
374help you (others could be added) :
375
376 - htx_add_last_data() adds a DATA block just after all other DATA blocks and
377 before any trailers and EOT or EOM markers. It relies on
378 htx_add_data_atonce(), so a defragmentation may be performed.
379
380 - htx_move_blk_before() moves a specific block just after another one. Both
381 blocks must already be in the HTX message and the block to move must
382 always be placed after the "pivot".
383
384Once added, there are three functions to update the block's payload :
385
386 - htx_replace_stline() updates a start-line. The HTX block must be passed as
387 argument. Only string parts of the start-line are updated by this
388 function. On success, it returns the new start-line. So it is pretty easy
389 to update its flags. NULL is returned if an error occurred.
390
391 - htx_replace_header() fully replaces a header (its name and its value) by a
392 new one. The HTX block must be passed a argument, as well as its new name
393 and its new value. The new header can be smaller or larger than the old
394 one. This function returns the new HTX block on success, or NULL is an
395 error occurred.
396
397 - htx_replace_blk_value() replaces a part of a block's payload or its
398 totality. It works for HEADERS, TRAILERS or DATA blocks. The HTX block
399 must be provided with the part to remove and the new one. The new part can
400 be smaller or larger than the old one. This function returns the new HTX
401 block on success, or NULL is an error occurred.
402
403Finally, You may remove a block using the function htx_remove_blk(). This
404function returns the block following the one removed or NULL if it is the tail
405block.
406
407
4084.4. The HTX start-line
409
410Unlike other HTX blocks, the start-line is a bit special because its payload is
411a structure followed by its three parts :
412
413 +--------+-------+-------+-------+
414 | HTX_SL | PART1 | PART2 | PART3 |
415 +--------+-------+-------+-------+
416
417Some macros and functions may help to manipulate these parts :
418
419 - HTX_SL_P{N}_LEN() and HTX_SL_P{N}_PTR() are macros to get the length of a
420 part and a pointer on it. {N} should be 1, 2 or 3.
421
422 - HTX_SL_REQ_MLEN(), HTX_SL_REQ_ULEN(), HTX_SL_REQ_VLEN(),
423 HTX_SL_REQ_MPTR(), HTX_SL_REQ_UPTR() and HTX_SL_REQ_VPTR() are macros to
424 get info about a request start-line. These macros only wrap HTX_SL_P*
425 ones.
426
427 - HTX_SL_RES_VLEN(), HTX_SL_RES_CLEN(), HTX_SL_RES_RLEN(),
428 HTX_SL_RES_VPTR(), HTX_SL_RES_CPTR() and HTX_SL_RES_RPTR() are macros to
429 get info about a response start-line. These macros only wrap HTX_SL_P*
430 ones.
431
432 - htx_sl_p1(), htx_sl_p2() and htx_sl_p2() are functions to get the ist
433 corresponding to the right part of a start-line.
434
435 - htx_sl_req_meth(), htx_sl_req_uri() and htx_sl_req_vsn() get the ist
436 corresponding to the right part of a request start-line.
437
438 - htx_sl_res_vsn(), htx_sl_res_code() and htx_sl_res_reason() get the ist
439 corresponding to the right part of a response start-line.
440
441
4424.5. Iterate on the HTX message
443
444To iterate on an HTX message, the first thing to do is to get the HTX block to
445start the loop. There are three special blocks in an HTX message that may be
446good candidates to start a loop :
447
448 * the head block. It is the oldest inserted block. Multiplexers always start
449 to consume an HTX message from this block. The function htx_get_head()
450 returns its position and htx_get_head_blk() returns the blocks itself. In
451 addition, the function htx_get_head_type() returns its block's type.
452
453 * the tail block. It is the newest inserted block. The function htx_get_tail()
454 returns its position and htx_get_tail_blk() returns the blocks itself. In
455 addition, the function htx_get_tail_type() returns its block's type.
456
457 * the first block. It is the block where to (re)start the analyse. It is used
458 as start point by HTX analyzers. The function htx_get_first() returns its
459 position and htx_get_first_blk() returns the blocks itself. In addition, the
460 function htx_get_first_type() returns its block's type.
461
462For all these functions, if the HTX message is empty, -1 is returned for the
463block's position, NULL instead of a block and HTX_BLK_UNUSED for its type.
464
465Then to iterate on blocks, you may move foreword or backward :
466
467 * htx_get_prev() and htx_get_next() return, respectively, the position of the
468 previous block or the next block, given a specific position. Or -1 if an edge
469 is reached.
470
471 * htx_get_prev_blk() and htx_get_next_blk() return, respectively, the previous
472 block or the next one, given a specific block. Or NULL if an edge is
473 reached.
474
475
4764.6. Advanced functions
477
478Some more advanced functions may be used to do complex processing on the HTX
479message. These functions are used by HTX analyzers or by multiplexers.
480
481 * htx_truncate() removes all blocks after the one containing a specific offset
482 relatively to the head block of the HTX message. If the offset is inside a
483 DATA block, it is truncated. For all other blocks, the removal starts to the
484 next block.
485
486 * htx_drain() tries to remove a specific amount of bytes of payload. If the
487 last block is a DATA block, it may be truncated if necessary. All other
488 block are removed at once or kept. This function returns a mixed value, with
489 the first block not removed, or NULL if everything was removed, and the
490 amount of data drained.
491
492 * htx_xfer_blks() transfers HTX blocks from an HTX message to another,
493 stopping on the first block of a specified type or when a specific amount of
494 bytes, including meta-data, was moved. If the last block is a DATA block, it
495 may be partially moved. All other block are transferred at once or
496 kept. This function returns a mixed value, with the last block moved, or
497 NULL if nothing was moved, and the amount of data transferred. When HEADERS
498 or TRAILERS blocks must be transferred, this function transfers all of
499 them. Otherwise, if it is not possible, it triggers an error. It is the
500 caller responsibility to transfer all headers or trailers at once.