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

Commit ea1f708

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 fbbde5c commit ea1f708

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
@@ -166,6 +166,79 @@ nxt_http_comp_bound(size_t size)
166166
}
167167

168168

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

483+
r->resp.content_length = NULL;
484+
r->resp.content_length_n = -1;
485+
486+
if (r->resp.mime_type == NULL) {
487+
nxt_http_field_t *f;
488+
489+
/*
490+
* As per RFC 2616 section 4.4 item 3, you should not send
491+
* Content-Length when a Transfer-Encoding header is present.
492+
*/
493+
nxt_list_each(f, r->resp.fields) {
494+
if (nxt_strcasecmp(f->name,
495+
(const u_char *)"Content-Length") == 0)
496+
{
497+
f->skip = true;
498+
break;
499+
}
500+
} nxt_list_loop;
501+
}
502+
410503
return NXT_OK;
411504
}
412505

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)