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 */
|
/* various protocol processing functions */
|
||||||
|
|
||||||
int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf);
|
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_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_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);
|
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;
|
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
|
/* Parse the Content-Length header field of an HTTP/2 request. The function
|
||||||
* checks all possible occurrences of a comma-delimited value, and verifies
|
* 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
|
* if any of them doesn't match a previous value. It returns <0 if a value
|
||||||
|
Loading…
Reference in New Issue
Block a user