Skip to content
This repository was archived by the owner on Oct 8, 2025. It is now read-only.

Commit 284709f

Browse files
http: Compress application responses
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>
1 parent 950d061 commit 284709f

File tree

3 files changed

+102
-1
lines changed

3 files changed

+102
-1
lines changed

src/nxt_http_compression.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,79 @@ nxt_http_comp_bound(size_t size)
162162
}
163163

164164

165+
nxt_int_t
166+
nxt_http_comp_compress_app_response(nxt_http_request_t *r, nxt_buf_t **b)
167+
{
168+
bool last;
169+
size_t buf_len, in_len;
170+
ssize_t cbytes;
171+
// uint8_t *buf;
172+
// nxt_buf_t *buf;
173+
nxt_http_comp_ctx_t *ctx = &compressor_ctx;
174+
175+
if (ctx->idx == NXT_HTTP_COMP_SCHEME_IDENTITY) {
176+
return NXT_OK;
177+
}
178+
179+
if ((*b)->mem.pos == NULL) {
180+
return NXT_OK;
181+
}
182+
183+
last = !(*b)->next || nxt_buf_is_last(*b);
184+
185+
in_len = (*b)->mem.free - (*b)->mem.pos;
186+
buf_len = nxt_http_comp_bound(in_len);
187+
188+
#if 1
189+
if (buf_len > (size_t)nxt_buf_mem_size(&(*b)->mem)) {
190+
return NXT_OK;
191+
}
192+
193+
uint8_t *buf = nxt_malloc(buf_len);
194+
195+
cbytes = nxt_http_comp_compress(buf, buf_len, (*b)->mem.pos, in_len, last);
196+
if (cbytes == -1) {
197+
nxt_free(buf);
198+
return NXT_ERROR;
199+
}
200+
201+
(*b)->mem.free = nxt_cpymem((*b)->mem.pos, buf, cbytes);
202+
203+
nxt_free(buf);
204+
#else
205+
/*
206+
* While this produces correct compressed output, the router
207+
* process then crashes doing some shutdown/cleanup work.
208+
*
209+
* My best guess as to why this happens is due to our *new* b
210+
* not being allocated from the same memory pool as the original.
211+
*/
212+
nxt_buf_t *buf = nxt_buf_mem_alloc(r->mem_pool, buf_len, 0);
213+
if (nxt_slow_path(buf == NULL)) {
214+
return NXT_ERROR;
215+
}
216+
217+
nxt_memcpy(buf, *b, offsetof(nxt_buf_t, mem));
218+
219+
cbytes = nxt_http_comp_compress(buf->mem.start, buf_len,
220+
(*b)->mem.pos, in_len, last);
221+
printf("%s: cbytes = %ld\n", __func__, cbytes);
222+
if (cbytes == -1) {
223+
return NXT_ERROR;
224+
}
225+
226+
buf->mem.free += cbytes;
227+
/* Seemingly *not* the memory ppol b was allocated from... */
228+
// nxt_buf_free(r->mem_pool, *b);
229+
*b = buf;
230+
231+
printf("%s: buf [%p] *b [%p]\n", __func__, buf, *b);
232+
#endif
233+
234+
return NXT_OK;
235+
}
236+
237+
165238
nxt_int_t
166239
nxt_http_comp_compress_static_response(nxt_task_t *task, nxt_file_t **f,
167240
nxt_file_info_t *fi,
@@ -395,6 +468,26 @@ nxt_http_comp_set_header(nxt_http_request_t *r, nxt_uint_t comp_idx)
395468
f->value = token->start;
396469
f->value_length = token->length;
397470

471+
r->resp.content_length = NULL;
472+
r->resp.content_length_n = -1;
473+
474+
if (r->resp.mime_type == NULL) {
475+
nxt_http_field_t *f;
476+
477+
/*
478+
* As per RFC 2616 section 4.4 item 3, you should not send
479+
* Content-Length when a Transfer-Encoding header is present.
480+
*/
481+
nxt_list_each(f, r->resp.fields) {
482+
if (nxt_strcasecmp(f->name,
483+
(const u_char *)"Content-Length") == 0)
484+
{
485+
f->skip = true;
486+
break;
487+
}
488+
} nxt_list_loop;
489+
}
490+
398491
return NXT_OK;
399492
}
400493

src/nxt_http_compression.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ extern const nxt_http_comp_operations_t nxt_comp_brotli_ops;
9090
#endif
9191

9292

93+
extern nxt_int_t nxt_http_comp_compress_app_response(nxt_http_request_t *r,
94+
nxt_buf_t **b);
9395
extern nxt_int_t nxt_http_comp_compress_static_response(nxt_task_t *task,
9496
nxt_file_t **f, nxt_file_info_t *fi, size_t static_buf_len,
9597
size_t *out_total);

src/nxt_router.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4190,9 +4190,10 @@ nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
41904190
}
41914191

41924192
if (r->header_sent) {
4193+
nxt_http_comp_compress_app_response(r, &b);
4194+
41934195
nxt_buf_chain_add(&r->out, b);
41944196
nxt_http_request_send_body(task, r, NULL);
4195-
41964197
} else {
41974198
b_size = nxt_buf_is_mem(b) ? nxt_buf_mem_used_size(&b->mem) : 0;
41984199

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

4276+
ret = nxt_http_comp_check_compression(task, r);
4277+
if (ret != NXT_OK) {
4278+
goto fail;
4279+
}
4280+
42754281
nxt_http_request_header_send(task, r, nxt_http_request_send_body, NULL);
42764282

42774283
if (r->websocket_handshake

0 commit comments

Comments
 (0)