Skip to content

Commit adaecb6

Browse files
committed
http: Compress static responses
Signed-off-by: Andrew Clayton <[email protected]>
1 parent 523d422 commit adaecb6

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

src/nxt_http_compression.c

+99
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,105 @@ nxt_http_comp_bound(size_t size)
166166
}
167167

168168

169+
nxt_int_t
170+
nxt_http_comp_compress_static_response(nxt_task_t *task, nxt_file_t **f,
171+
nxt_file_info_t *fi,
172+
size_t static_buf_len,
173+
size_t *out_total)
174+
{
175+
char tmp_path[NXT_MAX_PATH_LEN];
176+
size_t in_size, out_size, rest;
177+
u_char *p;
178+
uint8_t *in, *out;
179+
nxt_int_t ret;
180+
nxt_file_t tfile;
181+
nxt_runtime_t *rt = task->thread->runtime;
182+
183+
static const char *template = "unit-compr-XXXXXX";
184+
185+
*out_total = 0;
186+
187+
if (nxt_slow_path(strlen(rt->tmp) + 1 + strlen(template) + 1
188+
> NXT_MAX_PATH_LEN))
189+
{
190+
return NXT_ERROR;
191+
}
192+
193+
p = nxt_cpymem(tmp_path, rt->tmp, strlen(rt->tmp));
194+
*p++ = '/';
195+
p = nxt_cpymem(p, template, strlen(template));
196+
*p = '\0';
197+
198+
tfile.fd = mkstemp(tmp_path);
199+
if (nxt_slow_path(tfile.fd == -1)) {
200+
nxt_alert(task, "mkstemp(%s) failed %E", tmp_path, nxt_errno);
201+
return NXT_ERROR;
202+
}
203+
unlink(tmp_path);
204+
205+
in_size = nxt_file_size(fi);
206+
out_size = nxt_http_comp_bound(in_size);
207+
208+
ret = ftruncate(tfile.fd, out_size);
209+
if (nxt_slow_path(ret == -1)) {
210+
nxt_alert(task, "ftruncate(%d<%s>, %uz) failed %E",
211+
tfile.fd, tmp_path, out_size, nxt_errno);
212+
nxt_file_close(task, &tfile);
213+
return NXT_ERROR;
214+
}
215+
216+
in = nxt_mem_mmap(NULL, in_size, PROT_READ, MAP_SHARED, (*f)->fd, 0);
217+
if (nxt_slow_path(in == MAP_FAILED)) {
218+
nxt_file_close(task, &tfile);
219+
return NXT_ERROR;
220+
}
221+
222+
out = nxt_mem_mmap(NULL, out_size, PROT_READ|PROT_WRITE, MAP_SHARED,
223+
tfile.fd, 0);
224+
if (nxt_slow_path(out == MAP_FAILED)) {
225+
nxt_mem_munmap(in, in_size);
226+
nxt_file_close(task, &tfile);
227+
return NXT_ERROR;
228+
}
229+
230+
rest = in_size;
231+
232+
do {
233+
bool last;
234+
size_t n;
235+
ssize_t cbytes;
236+
237+
n = nxt_min(rest, static_buf_len);
238+
239+
last = n == rest;
240+
241+
cbytes = nxt_http_comp_compress(out + *out_total, out_size - *out_total,
242+
in + in_size - rest, n, last);
243+
244+
*out_total += cbytes;
245+
rest -= n;
246+
} while (rest > 0);
247+
248+
nxt_mem_munmap(in, in_size);
249+
msync(out, out_size, MS_ASYNC);
250+
nxt_mem_munmap(out, out_size);
251+
252+
ret = ftruncate(tfile.fd, *out_total);
253+
if (nxt_slow_path(ret == -1)) {
254+
nxt_alert(task, "ftruncate(%d<%s>, %uz) failed %E",
255+
tfile.fd, tmp_path, *out_total, nxt_errno);
256+
nxt_file_close(task, &tfile);
257+
return NXT_ERROR;
258+
}
259+
260+
nxt_file_close(task, *f);
261+
262+
**f = tfile;
263+
264+
return NXT_OK;
265+
}
266+
267+
169268
bool
170269
nxt_http_comp_wants_compression(void)
171270
{

src/nxt_http_compression.h

+3
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ extern const nxt_http_comp_operations_t nxt_http_comp_brotli_ops;
9090
#endif
9191

9292

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

src/nxt_http_static.c

+31
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 {
@@ -576,7 +577,37 @@ nxt_http_static_send(nxt_task_t *task, nxt_http_request_t *r,
576577
field->value_length = mtype->length;
577578
}
578579

580+
r->resp.mime_type = mtype;
581+
579582
if (ctx->need_body && nxt_file_size(&fi) > 0) {
583+
ret = nxt_http_comp_check_compression(task, r);
584+
if (ret == NXT_HTTP_NOT_ACCEPTABLE) {
585+
nxt_http_request_error(task, r, NXT_HTTP_NOT_ACCEPTABLE);
586+
return;
587+
} else if (ret != NXT_OK) {
588+
goto fail;
589+
}
590+
591+
if (nxt_http_comp_wants_compression()) {
592+
size_t out_total;
593+
nxt_int_t ret;
594+
595+
ret = nxt_http_comp_compress_static_response(
596+
task, &f, &fi,
597+
NXT_HTTP_STATIC_BUF_SIZE,
598+
&out_total);
599+
if (ret == NXT_ERROR) {
600+
goto fail;
601+
}
602+
603+
ret = nxt_file_info(f, &fi);
604+
if (nxt_slow_path(ret != NXT_OK)) {
605+
goto fail;
606+
}
607+
608+
r->resp.content_length_n = out_total;
609+
}
610+
580611
fb = nxt_mp_zget(r->mem_pool, NXT_BUF_FILE_SIZE);
581612
if (nxt_slow_path(fb == NULL)) {
582613
goto fail;

0 commit comments

Comments
 (0)