Improving response header fields processing.

Fields are filtered one by one before being added to fields list.
This avoids adding and then skipping connection-specific fields.
This commit is contained in:
Max Romanov 2019-08-16 00:56:38 +03:00
parent caea9d3c07
commit 29911538ea
3 changed files with 46 additions and 27 deletions

View file

@ -1110,7 +1110,7 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
}
static const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto nxt_aligned(64) = {
const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto nxt_aligned(64) = {
NXT_LVLHSH_BUCKET_SIZE(64),
{ NXT_HTTP_FIELD_LVLHSH_SHIFT, 0, 0, 0, 0, 0, 0, 0 },
nxt_http_field_hash_test,
@ -1240,27 +1240,12 @@ nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, nxt_mp_t *mp,
nxt_int_t
nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash, void *ctx)
{
nxt_int_t ret;
nxt_http_field_t *field;
nxt_lvlhsh_query_t lhq;
nxt_http_field_proc_t *proc;
lhq.proto = &nxt_http_fields_hash_proto;
nxt_int_t ret;
nxt_http_field_t *field;
nxt_list_each(field, fields) {
lhq.key_hash = field->hash;
lhq.key.length = field->name_length;
lhq.key.start = field->name;
if (nxt_lvlhsh_find(hash, &lhq) != NXT_OK) {
continue;
}
proc = lhq.value;
ret = proc->handler(ctx, field, proc->data);
ret = nxt_http_field_process(field, hash, ctx);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}

View file

@ -113,4 +113,28 @@ nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash,
void *ctx);
const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto;
nxt_inline nxt_int_t
nxt_http_field_process(nxt_http_field_t *field, nxt_lvlhsh_t *hash, void *ctx)
{
nxt_lvlhsh_query_t lhq;
nxt_http_field_proc_t *proc;
lhq.proto = &nxt_http_fields_hash_proto;
lhq.key_hash = field->hash;
lhq.key.length = field->name_length;
lhq.key.start = field->name;
if (nxt_lvlhsh_find(hash, &lhq) != NXT_OK) {
return NXT_OK;
}
proc = lhq.value;
return proc->handler(ctx, field, proc->data);
}
#endif /* _NXT_HTTP_PARSER_H_INCLUDED_ */

View file

@ -3483,7 +3483,13 @@ nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
goto fail;
}
field = NULL;
for (f = resp->fields; f < resp->fields + resp->fields_count; f++) {
if (f->skip) {
continue;
}
field = nxt_list_add(r->resp.fields);
if (nxt_slow_path(field == NULL)) {
@ -3491,26 +3497,30 @@ nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
}
field->hash = f->hash;
field->skip = f->skip;
field->skip = 0;
field->name_length = f->name_length;
field->value_length = f->value_length;
field->name = nxt_unit_sptr_get(&f->name);
field->value = nxt_unit_sptr_get(&f->value);
nxt_debug(task, "header: %*s: %*s",
ret = nxt_http_field_process(field, &nxt_response_fields_hash, r);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
nxt_debug(task, "header%s: %*s: %*s",
(field->skip ? " skipped" : ""),
(size_t) field->name_length, field->name,
(size_t) field->value_length, field->value);
if (field->skip) {
r->resp.fields->last->nelts--;
}
}
r->status = resp->status;
ret = nxt_http_fields_process(r->resp.fields,
&nxt_response_fields_hash, r);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
if (resp->piggyback_content_length != 0) {
b->mem.pos = nxt_unit_sptr_get(&resp->piggyback_content);
b->mem.free = b->mem.pos + resp->piggyback_content_length;