mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-13 23:14:46 +00:00
MINOR: h2: add h2_make_h1_trailers to turn H2 headers to H1 trailers
This function is usable to transform a list of H2 header fields to a H1 trailers block. It takes care of rejecting forbidden headers and pseudo-headers when performing the conversion.
This commit is contained in:
parent
88d138ef6d
commit
9d953e7572
@ -178,6 +178,7 @@ enum h2_err {
|
||||
/* various protocol processing functions */
|
||||
|
||||
int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf);
|
||||
int h2_make_h1_trailers(struct http_hdr *list, char *out, int osize);
|
||||
int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned long long *body_len);
|
||||
int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *msgf);
|
||||
int h2_make_htx_response(struct http_hdr *list, struct htx *htx, unsigned int *msgf);
|
||||
|
71
src/h2.c
71
src/h2.c
@ -320,6 +320,77 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Takes an H2 headers list <list> terminated by a name being <NULL,0> and
|
||||
* emits the equivalent HTTP/1.1 trailers block not including the empty line.
|
||||
* The output contents are emitted in <out> for a max of <osize> bytes, and the
|
||||
* amount of bytes emitted is returned. In case of error, a negative error code
|
||||
* is returned. The caller must have verified that the message in the buffer is
|
||||
* compatible with receipt of trailers.
|
||||
*
|
||||
* The headers list <list> must be composed of :
|
||||
* - n.name != NULL, n.len > 0 : literal header name
|
||||
* - n.name == NULL, n.len > 0 : indexed pseudo header name number <n.len>
|
||||
* among H2_PHDR_IDX_* (illegal here)
|
||||
* - n.name ignored, n.len == 0 : end of list
|
||||
* - in all cases except the end of list, v.name and v.len must designate a
|
||||
* valid value.
|
||||
*/
|
||||
int h2_make_h1_trailers(struct http_hdr *list, char *out, int osize)
|
||||
{
|
||||
char *out_end = out + osize;
|
||||
uint32_t idx;
|
||||
int i;
|
||||
|
||||
for (idx = 0; list[idx].n.len != 0; idx++) {
|
||||
if (!list[idx].n.ptr) {
|
||||
/* This is an indexed pseudo-header (RFC7540#8.1.2.1) */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* RFC7540#8.1.2: upper case not allowed in header field names */
|
||||
for (i = 0; i < list[idx].n.len; i++)
|
||||
if ((uint8_t)(list[idx].n.ptr[i] - 'A') < 'Z' - 'A')
|
||||
goto fail;
|
||||
|
||||
if (h2_str_to_phdr(list[idx].n) != 0) {
|
||||
/* This is a pseudo-header (RFC7540#8.1.2.1) */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* these ones are forbidden in trailers (RFC7540#8.1.2.2) */
|
||||
if (isteq(list[idx].n, ist("host")) ||
|
||||
isteq(list[idx].n, ist("content-length")) ||
|
||||
isteq(list[idx].n, ist("connection")) ||
|
||||
isteq(list[idx].n, ist("proxy-connection")) ||
|
||||
isteq(list[idx].n, ist("keep-alive")) ||
|
||||
isteq(list[idx].n, ist("upgrade")) ||
|
||||
isteq(list[idx].n, ist("te")) ||
|
||||
isteq(list[idx].n, ist("transfer-encoding")))
|
||||
goto fail;
|
||||
|
||||
if (out + list[idx].n.len + 2 + list[idx].v.len + 2 > out_end) {
|
||||
/* too large */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* copy "name: value" */
|
||||
memcpy(out, list[idx].n.ptr, list[idx].n.len);
|
||||
out += list[idx].n.len;
|
||||
*(out++) = ':';
|
||||
*(out++) = ' ';
|
||||
|
||||
memcpy(out, list[idx].v.ptr, list[idx].v.len);
|
||||
out += list[idx].v.len;
|
||||
*(out++) = '\r';
|
||||
*(out++) = '\n';
|
||||
}
|
||||
|
||||
return out + osize - out_end;
|
||||
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse the Content-Length header field of an HTTP/2 request. The function
|
||||
* checks all possible occurrences of a comma-delimited value, and verifies
|
||||
* if any of them doesn't match a previous value. It returns <0 if a value
|
||||
|
Loading…
Reference in New Issue
Block a user