* returns 0.
* <chk> buffer must not wrap.
*/
-int h1_format_htx_hdr(const struct ist n, const struct ist v, struct buffer *chk)
+int h1_format_htx_hdr(const struct ist n, const struct ist v, struct buffer *chk,
+ struct h1_hdrs_map *hdrs_map)
{
+ struct ebpt_node *node;
+ struct h1_hdr_entry *entry;
+ struct ist name = n;
size_t sz = chk->data;
if (n.len + v.len + 4 > b_room(chk))
return 0;
- if (!chunk_memcat(chk, n.ptr, n.len) ||
+ if (hdrs_map && !eb_is_empty(&hdrs_map->map)) {
+ node = ebis_lookup_len(&hdrs_map->map, istptr(n), istlen(n));
+ if (node) {
+ entry = container_of(node, struct h1_hdr_entry, node);
+ name = entry->name;
+ }
+ }
+
+ if (!chunk_memcat(chk, name.ptr, name.len) ||
!chunk_memcat(chk, ": ", 2) ||
!chunk_memcat(chk, v.ptr, v.len) ||
!chunk_memcat(chk, "\r\n", 2))
* 0 if <outbuf> is full or not empty. No check is performed on the message, it must be
* valid. Trailers are silently ignored if the message is not chunked.
*/
-int h1_format_htx_msg(const struct htx *htx, struct buffer *outbuf)
+int h1_format_htx_msg(const struct htx *htx, struct buffer *outbuf, struct h1_hdrs_map *hdrs_map)
{
const struct htx_sl *sl;
const struct htx_blk *blk;
n = htx_get_blk_name(htx, blk);
v = htx_get_blk_value(htx, blk);
- if (!h1_format_htx_hdr(n, v, outbuf))
+ if (!h1_format_htx_hdr(n, v, outbuf, hdrs_map))
goto full;
}
else if (type == HTX_BLK_EOH) {
n = htx_get_blk_name(htx, blk);
v = htx_get_blk_value(htx, blk);
- if (!h1_format_htx_hdr(n, v, outbuf))
+ if (!h1_format_htx_hdr(n, v, outbuf, hdrs_map))
goto full;
}
else if (type == HTX_BLK_EOT)
h1_update_res_conn_value(h1s, h1m, conn_val);
}
-/* Try to adjust the case of the message header name using the global map
- * <hdrs_map>.
+/* Depending on the proxy options, return the global map to use to adjust the
+ * case of the message headers if conversion must be performed, or NULL.
*/
-static void h1_adjust_case_outgoing_hdr(struct h1s *h1s, struct h1m *h1m, struct ist *name)
+static struct h1_hdrs_map *h1_get_hdrs_map(struct h1c *h1c, int isresp)
{
- struct ebpt_node *node;
- struct h1_hdr_entry *entry;
-
- /* No entry in the map, do nothing */
- if (eb_is_empty(&hdrs_map.map))
- return;
-
/* No conversion for the request headers */
- if (!(h1m->flags & H1_MF_RESP) && !(h1s->h1c->px->options2 & PR_O2_H1_ADJ_BUGSRV))
- return;
-
+ if (!isresp && !(h1c->px->options2 & PR_O2_H1_ADJ_BUGSRV))
+ return NULL;
/* No conversion for the response headers */
- if ((h1m->flags & H1_MF_RESP) && !(h1s->h1c->px->options2 & PR_O2_H1_ADJ_BUGCLI))
- return;
+ if (isresp && !(h1c->px->options2 & PR_O2_H1_ADJ_BUGCLI))
+ return NULL;
- node = ebis_lookup_len(&hdrs_map.map, name->ptr, name->len);
- if (!node)
- return;
- entry = container_of(node, struct h1_hdr_entry, node);
- name->ptr = entry->name.ptr;
- name->len = entry->name.len;
+ return &hdrs_map;
}
/* Append the description of what is present in error snapshot <es> into <out>.
static size_t h1_make_headers(struct h1s *h1s, struct h1m *h1m, struct htx *htx, size_t count)
{
struct h1c *h1c = h1s->h1c;
+ struct h1_hdrs_map *hdrs_map = h1_get_hdrs_map(h1c, (h1m->flags & H1_MF_RESP));
struct htx_blk *blk;
struct buffer outbuf;
enum htx_blk_type type;
isteqi(n, h1c->px->server_id_hdr_name))
goto nextblk;
- /* Try to adjust the case of the header name */
- if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV))
- h1_adjust_case_outgoing_hdr(h1s, h1m, &n);
- if (!h1_format_htx_hdr(n, v, &outbuf))
+ if (!h1_format_htx_hdr(n, v, &outbuf, hdrs_map))
goto full;
}
else if (type == HTX_BLK_EOH) {
static size_t h1_make_eoh(struct h1s *h1s, struct h1m *h1m, struct htx *htx, size_t count)
{
struct h1c *h1c = h1s->h1c;
+ struct h1_hdrs_map *hdrs_map = h1_get_hdrs_map(h1c, (h1m->flags & H1_MF_RESP));
struct htx_blk *blk;
struct buffer outbuf;
enum htx_blk_type type;
else {
/* It is the request: Add "Content-Length: 0" header and skip payload */
struct ist n = ist("content-length");
- if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV))
- h1_adjust_case_outgoing_hdr(h1s, h1m, &n);
- if (!h1_format_htx_hdr(n, ist("0"), &outbuf))
+ if (!h1_format_htx_hdr(n, ist("0"), &outbuf, hdrs_map))
goto full;
h1m->flags = (h1m->flags & ~(H1_MF_XFER_ENC|H1_MF_CHNK)) | H1_MF_CLEN;
v = ist("");
h1_process_output_conn_mode(h1s, h1m, &v);
if (v.len) {
- /* Try to adjust the case of the header name */
- if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV))
- h1_adjust_case_outgoing_hdr(h1s, h1m, &n);
- if (!h1_format_htx_hdr(n, v, &outbuf))
+ if (!h1_format_htx_hdr(n, v, &outbuf, hdrs_map))
goto full;
}
h1s->flags |= H1S_F_HAVE_O_CONN;
/* chunking needed but header not seen */
n = ist("transfer-encoding");
v = ist("chunked");
- if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV))
- h1_adjust_case_outgoing_hdr(h1s, h1m, &n);
- if (!h1_format_htx_hdr(n, v, &outbuf))
+ if (!h1_format_htx_hdr(n, v, &outbuf, hdrs_map))
goto full;
TRACE_STATE("add \"Transfer-Encoding: chunked\"", H1_EV_TX_DATA|H1_EV_TX_HDRS, h1c->conn, h1s);
h1s->flags |= H1S_F_HAVE_CHNK;
if (srv) {
n = h1c->px->server_id_hdr_name;
v = ist(srv->id);
-
- /* Try to adjust the case of the header name */
- if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV))
- h1_adjust_case_outgoing_hdr(h1s, h1m, &n);
- if (!h1_format_htx_hdr(n, v, &outbuf))
+ if (!h1_format_htx_hdr(n, v, &outbuf, hdrs_map))
goto full;
}
TRACE_STATE("add server name header", H1_EV_TX_DATA|H1_EV_TX_HDRS, h1c->conn, h1s);
if (!h1_format_htx_hdr(ist("Sec-Websocket-Key"),
ist(h1s->ws_key),
- &outbuf)) {
+ &outbuf, hdrs_map)) {
goto full;
}
}
h1_calculate_ws_output_key(h1s->ws_key, key);
if (!h1_format_htx_hdr(ist("Sec-Websocket-Accept"),
ist(key),
- &outbuf)) {
+ &outbuf, hdrs_map)) {
goto full;
}
}
static size_t h1_make_trailers(struct h1s *h1s, struct h1m *h1m, struct htx *htx, size_t count)
{
struct h1c *h1c = h1s->h1c;
+ struct h1_hdrs_map *hdrs_map = h1_get_hdrs_map(h1c, (h1m->flags & H1_MF_RESP));
struct htx_blk *blk;
struct buffer outbuf;
enum htx_blk_type type;
n = htx_get_blk_name(htx, blk);
v = htx_get_blk_value(htx, blk);
- /* Try to adjust the case of the header name */
- if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV))
- h1_adjust_case_outgoing_hdr(h1s, h1m, &n);
- if (!h1_format_htx_hdr(n, v, &outbuf))
+ if (!h1_format_htx_hdr(n, v, &outbuf, hdrs_map))
goto full;
}
else if (type == HTX_BLK_EOT) {
TRACE_STATE("waiting for h1c obuf allocation", H1_EV_H1C_ERR|H1_EV_H1C_BLK, h1c->conn);
goto out;
}
- if (errmsg)
- ret = h1_format_htx_msg(htxbuf(errmsg), &h1c->obuf);
+ if (errmsg) {
+ struct h1_hdrs_map *hdrs_map = h1_get_hdrs_map(h1c, 1);
+
+ ret = h1_format_htx_msg(htxbuf(errmsg), &h1c->obuf, hdrs_map);
+ }
else
ret = b_istput(&h1c->obuf, ist(http_err_msgs[rc]));
if (unlikely(ret <= 0)) {