Skip to content

Commit

Permalink
http: Compress application responses
Browse files Browse the repository at this point in the history
Co-authored-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
  • Loading branch information
ac000 and alejandro-colomar committed Jan 20, 2025
1 parent f3f2fca commit 3104ae1
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 1 deletion.
93 changes: 93 additions & 0 deletions src/nxt_http_compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,79 @@ nxt_http_comp_bound(size_t size)
}


nxt_int_t
nxt_http_comp_compress_app_response(nxt_http_request_t *r, nxt_buf_t **b)
{
bool last;
size_t buf_len, in_len;
ssize_t cbytes;
// uint8_t *buf;
// nxt_buf_t *buf;
nxt_http_comp_ctx_t *ctx = &compressor_ctx;

if (ctx->idx == NXT_HTTP_COMP_SCHEME_IDENTITY) {
return NXT_OK;
}

if ((*b)->mem.pos == NULL) {
return NXT_OK;
}

last = !(*b)->next || nxt_buf_is_last(*b);

in_len = (*b)->mem.free - (*b)->mem.pos;
buf_len = nxt_http_comp_bound(in_len);

#if 1
if (buf_len > (size_t)nxt_buf_mem_size(&(*b)->mem)) {
return NXT_OK;
}

uint8_t *buf = nxt_malloc(buf_len);

cbytes = nxt_http_comp_compress(buf, buf_len, (*b)->mem.pos, in_len, last);
if (cbytes == -1) {
nxt_free(buf);
return NXT_ERROR;
}

(*b)->mem.free = nxt_cpymem((*b)->mem.pos, buf, cbytes);

nxt_free(buf);
#else
/*
* While this produces correct compressed output, the router
* process then crashes doing some shutdown/cleanup work.
*
* My best guess as to why this happens is due to our *new* b
* not being allocated from the same memory pool as the original.
*/
nxt_buf_t *buf = nxt_buf_mem_alloc(r->mem_pool, buf_len, 0);
if (nxt_slow_path(buf == NULL)) {
return NXT_ERROR;
}

nxt_memcpy(buf, *b, offsetof(nxt_buf_t, mem));

cbytes = nxt_http_comp_compress(buf->mem.start, buf_len,
(*b)->mem.pos, in_len, last);
printf("%s: cbytes = %ld\n", __func__, cbytes);
if (cbytes == -1) {
return NXT_ERROR;
}

buf->mem.free += cbytes;
/* Seemingly *not* the memory ppol b was allocated from... */
// nxt_buf_free(r->mem_pool, *b);
*b = buf;

printf("%s: buf [%p] *b [%p]\n", __func__, buf, *b);
#endif

return NXT_OK;
}


nxt_int_t
nxt_http_comp_compress_static_response(nxt_task_t *task, nxt_file_t **f,
nxt_file_info_t *fi,
Expand Down Expand Up @@ -383,6 +456,26 @@ nxt_http_comp_set_header(nxt_http_request_t *r, nxt_uint_t comp_idx)
f->value = token->start;
f->value_length = token->length;

r->resp.content_length = NULL;
r->resp.content_length_n = -1;

if (r->resp.mime_type == NULL) {
nxt_http_field_t *f;

/*
* As per RFC 2616 section 4.4 item 3, you should not send
* Content-Length when a Transfer-Encoding header is present.
*/
nxt_list_each(f, r->resp.fields) {
if (nxt_strcasecmp(f->name,
(const u_char *)"Content-Length") == 0)
{
f->skip = true;
break;
}
} nxt_list_loop;
}

return NXT_OK;
}

Expand Down
2 changes: 2 additions & 0 deletions src/nxt_http_compression.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ extern const nxt_http_comp_operations_t nxt_comp_brotli_ops;
#endif


extern nxt_int_t nxt_http_comp_compress_app_response(nxt_http_request_t *r,
nxt_buf_t **b);
extern nxt_int_t nxt_http_comp_compress_static_response(nxt_task_t *task,
nxt_file_t **f, nxt_file_info_t *fi, size_t static_buf_len,
size_t *out_total);
Expand Down
8 changes: 7 additions & 1 deletion src/nxt_router.c
Original file line number Diff line number Diff line change
Expand Up @@ -4190,9 +4190,10 @@ nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
}

if (r->header_sent) {
nxt_http_comp_compress_app_response(r, &b);

nxt_buf_chain_add(&r->out, b);
nxt_http_request_send_body(task, r, NULL);

} else {
b_size = nxt_buf_is_mem(b) ? nxt_buf_mem_used_size(&b->mem) : 0;

Expand Down Expand Up @@ -4272,6 +4273,11 @@ nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
nxt_buf_chain_add(&r->out, b);
}

ret = nxt_http_comp_check_compression(task, r);
if (ret != NXT_OK) {
goto fail;
}

nxt_http_request_header_send(task, r, nxt_http_request_send_body, NULL);

if (r->websocket_handshake
Expand Down

0 comments on commit 3104ae1

Please sign in to comment.