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

Commit ab66623

Browse files
committed
http: Compress static responses
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
1 parent 5237c85 commit ab66623

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

src/nxt_http_compression.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,109 @@ nxt_http_comp_bound(size_t size)
181181
}
182182

183183

184+
nxt_int_t
185+
nxt_http_comp_compress_static_response(nxt_task_t *task, nxt_file_t **f,
186+
nxt_file_info_t *fi,
187+
size_t static_buf_len,
188+
size_t *out_total)
189+
{
190+
char tmp_path[NXT_MAX_PATH_LEN];
191+
size_t in_size, out_size, rest;
192+
u_char *p;
193+
uint8_t *in, *out;
194+
nxt_int_t ret;
195+
nxt_file_t tfile;
196+
nxt_runtime_t *rt = task->thread->runtime;
197+
198+
static const char *template = "unit-compr-XXXXXX";
199+
200+
*out_total = 0;
201+
202+
if (nxt_slow_path(strlen(rt->tmp) + 1 + strlen(template) + 1
203+
> NXT_MAX_PATH_LEN))
204+
{
205+
return NXT_ERROR;
206+
}
207+
208+
p = nxt_cpymem(tmp_path, rt->tmp, strlen(rt->tmp));
209+
*p++ = '/';
210+
p = nxt_cpymem(p, template, strlen(template));
211+
*p = '\0';
212+
213+
tfile.fd = mkstemp(tmp_path);
214+
if (nxt_slow_path(tfile.fd == -1)) {
215+
nxt_alert(task, "mkstemp(%s) failed %E", tmp_path, nxt_errno);
216+
return NXT_ERROR;
217+
}
218+
unlink(tmp_path);
219+
220+
in_size = nxt_file_size(fi);
221+
out_size = nxt_http_comp_bound(in_size);
222+
223+
ret = ftruncate(tfile.fd, out_size);
224+
if (nxt_slow_path(ret == -1)) {
225+
nxt_alert(task, "ftruncate(%d<%s>, %uz) failed %E",
226+
tfile.fd, tmp_path, out_size, nxt_errno);
227+
nxt_file_close(task, &tfile);
228+
return NXT_ERROR;
229+
}
230+
231+
in = nxt_mem_mmap(NULL, in_size, PROT_READ, MAP_SHARED, (*f)->fd, 0);
232+
if (nxt_slow_path(in == MAP_FAILED)) {
233+
nxt_file_close(task, &tfile);
234+
return NXT_ERROR;
235+
}
236+
237+
out = nxt_mem_mmap(NULL, out_size, PROT_READ|PROT_WRITE, MAP_SHARED,
238+
tfile.fd, 0);
239+
if (nxt_slow_path(out == MAP_FAILED)) {
240+
nxt_mem_munmap(in, in_size);
241+
nxt_file_close(task, &tfile);
242+
return NXT_ERROR;
243+
}
244+
245+
rest = in_size;
246+
247+
do {
248+
bool last;
249+
size_t n;
250+
ssize_t cbytes;
251+
252+
n = nxt_min(rest, static_buf_len);
253+
254+
last = n == rest;
255+
256+
printf("%s: out_off [%ld] in_off [%ld] last [%s]\n",
257+
__func__, *out_total, in_size - rest, last ? "true" : "false");
258+
259+
cbytes = nxt_http_comp_compress(out + *out_total, out_size - *out_total,
260+
in + in_size - rest, n, last);
261+
printf("%s: cbytes [%ld]\n", __func__, cbytes);
262+
263+
*out_total += cbytes;
264+
rest -= n;
265+
} while (rest > 0);
266+
267+
nxt_mem_munmap(in, in_size);
268+
msync(out, out_size, MS_ASYNC);
269+
nxt_mem_munmap(out, out_size);
270+
271+
ret = ftruncate(tfile.fd, *out_total);
272+
if (nxt_slow_path(ret == -1)) {
273+
nxt_alert(task, "ftruncate(%d<%s>, %uz) failed %E",
274+
tfile.fd, tmp_path, *out_total, nxt_errno);
275+
nxt_file_close(task, &tfile);
276+
return NXT_ERROR;
277+
}
278+
279+
nxt_file_close(task, *f);
280+
281+
**f = tfile;
282+
283+
return NXT_OK;
284+
}
285+
286+
184287
bool
185288
nxt_http_comp_wants_compression(void)
186289
{

src/nxt_http_compression.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ extern const nxt_http_comp_operations_t nxt_comp_brotli_ops;
9191
#endif
9292

9393

94+
extern nxt_int_t nxt_http_comp_compress_static_response(nxt_task_t *task,
95+
nxt_file_t **f, nxt_file_info_t *fi, size_t static_buf_len,
96+
size_t *out_total);
9497
extern bool nxt_http_comp_wants_compression(void);
9598
extern bool nxt_http_comp_compressor_is_valid(const nxt_str_t *token);
9699
extern nxt_int_t nxt_http_comp_check_compression(nxt_task_t *task,

src/nxt_http_static.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <nxt_router.h>
77
#include <nxt_http.h>
8+
#include <nxt_http_compression.h>
89

910

1011
typedef struct {
@@ -326,6 +327,8 @@ nxt_http_static_send(nxt_task_t *task, nxt_http_request_t *r,
326327
nxt_work_handler_t body_handler;
327328
nxt_http_static_conf_t *conf;
328329

330+
printf("%s: \n", __func__);
331+
329332
action = ctx->action;
330333
conf = action->u.conf;
331334
rtcf = r->conf->socket_conf->router_conf;
@@ -576,7 +579,34 @@ nxt_http_static_send(nxt_task_t *task, nxt_http_request_t *r,
576579
field->value_length = mtype->length;
577580
}
578581

582+
r->resp.mime_type = mtype;
583+
579584
if (ctx->need_body && nxt_file_size(&fi) > 0) {
585+
ret = nxt_http_comp_check_compression(task, r);
586+
if (ret != NXT_OK) {
587+
goto fail;
588+
}
589+
590+
if (nxt_http_comp_wants_compression()) {
591+
size_t out_total;
592+
nxt_int_t ret;
593+
594+
ret = nxt_http_comp_compress_static_response(
595+
task, &f, &fi,
596+
NXT_HTTP_STATIC_BUF_SIZE,
597+
&out_total);
598+
if (ret == NXT_ERROR) {
599+
goto fail;
600+
}
601+
602+
ret = nxt_file_info(f, &fi);
603+
if (nxt_slow_path(ret != NXT_OK)) {
604+
goto fail;
605+
}
606+
607+
r->resp.content_length_n = out_total;
608+
}
609+
580610
fb = nxt_mp_zget(r->mem_pool, NXT_BUF_FILE_SIZE);
581611
if (nxt_slow_path(fb == NULL)) {
582612
goto fail;
@@ -793,6 +823,8 @@ nxt_http_static_body_handler(nxt_task_t *task, void *obj, void *data)
793823
nxt_work_queue_t *wq;
794824
nxt_http_request_t *r;
795825

826+
printf("%s: \n", __func__);
827+
796828
r = obj;
797829
fb = r->out;
798830

@@ -853,6 +885,8 @@ nxt_http_static_buf_completion(nxt_task_t *task, void *obj, void *data)
853885
nxt_off_t rest;
854886
nxt_http_request_t *r;
855887

888+
printf("%s: \n", __func__);
889+
856890
b = obj;
857891
r = data;
858892

0 commit comments

Comments
 (0)