summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/nxt_http_compression.c99
-rw-r--r--src/nxt_http_compression.h3
-rw-r--r--src/nxt_http_static.c31
3 files changed, 133 insertions, 0 deletions
diff --git a/src/nxt_http_compression.c b/src/nxt_http_compression.c
index 6bd13fc9..96882307 100644
--- a/src/nxt_http_compression.c
+++ b/src/nxt_http_compression.c
@@ -166,6 +166,105 @@ nxt_http_comp_bound(size_t size)
}
+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)
+{
+ char tmp_path[NXT_MAX_PATH_LEN];
+ size_t in_size, out_size, rest;
+ u_char *p;
+ uint8_t *in, *out;
+ nxt_int_t ret;
+ nxt_file_t tfile;
+ nxt_runtime_t *rt = task->thread->runtime;
+
+ static const char *template = "unit-compr-XXXXXX";
+
+ *out_total = 0;
+
+ if (nxt_slow_path(strlen(rt->tmp) + 1 + strlen(template) + 1
+ > NXT_MAX_PATH_LEN))
+ {
+ return NXT_ERROR;
+ }
+
+ p = nxt_cpymem(tmp_path, rt->tmp, strlen(rt->tmp));
+ *p++ = '/';
+ p = nxt_cpymem(p, template, strlen(template));
+ *p = '\0';
+
+ tfile.fd = mkstemp(tmp_path);
+ if (nxt_slow_path(tfile.fd == -1)) {
+ nxt_alert(task, "mkstemp(%s) failed %E", tmp_path, nxt_errno);
+ return NXT_ERROR;
+ }
+ unlink(tmp_path);
+
+ in_size = nxt_file_size(fi);
+ out_size = nxt_http_comp_bound(in_size);
+
+ ret = ftruncate(tfile.fd, out_size);
+ if (nxt_slow_path(ret == -1)) {
+ nxt_alert(task, "ftruncate(%d<%s>, %uz) failed %E",
+ tfile.fd, tmp_path, out_size, nxt_errno);
+ nxt_file_close(task, &tfile);
+ return NXT_ERROR;
+ }
+
+ in = nxt_mem_mmap(NULL, in_size, PROT_READ, MAP_SHARED, (*f)->fd, 0);
+ if (nxt_slow_path(in == MAP_FAILED)) {
+ nxt_file_close(task, &tfile);
+ return NXT_ERROR;
+ }
+
+ out = nxt_mem_mmap(NULL, out_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ tfile.fd, 0);
+ if (nxt_slow_path(out == MAP_FAILED)) {
+ nxt_mem_munmap(in, in_size);
+ nxt_file_close(task, &tfile);
+ return NXT_ERROR;
+ }
+
+ rest = in_size;
+
+ do {
+ bool last;
+ size_t n;
+ ssize_t cbytes;
+
+ n = nxt_min(rest, static_buf_len);
+
+ last = n == rest;
+
+ cbytes = nxt_http_comp_compress(out + *out_total, out_size - *out_total,
+ in + in_size - rest, n, last);
+
+ *out_total += cbytes;
+ rest -= n;
+ } while (rest > 0);
+
+ nxt_mem_munmap(in, in_size);
+ msync(out, out_size, MS_ASYNC);
+ nxt_mem_munmap(out, out_size);
+
+ ret = ftruncate(tfile.fd, *out_total);
+ if (nxt_slow_path(ret == -1)) {
+ nxt_alert(task, "ftruncate(%d<%s>, %uz) failed %E",
+ tfile.fd, tmp_path, *out_total, nxt_errno);
+ nxt_file_close(task, &tfile);
+ return NXT_ERROR;
+ }
+
+ nxt_file_close(task, *f);
+
+ **f = tfile;
+
+ return NXT_OK;
+}
+
+
bool
nxt_http_comp_wants_compression(void)
{
diff --git a/src/nxt_http_compression.h b/src/nxt_http_compression.h
index c2007f8e..9f3567c1 100644
--- a/src/nxt_http_compression.h
+++ b/src/nxt_http_compression.h
@@ -90,6 +90,9 @@ extern const nxt_http_comp_operations_t nxt_http_comp_brotli_ops;
#endif
+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);
extern bool nxt_http_comp_wants_compression(void);
extern bool nxt_http_comp_compressor_is_valid(const nxt_str_t *token);
extern nxt_int_t nxt_http_comp_check_compression(nxt_task_t *task,
diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c
index d56ec587..78b1f150 100644
--- a/src/nxt_http_static.c
+++ b/src/nxt_http_static.c
@@ -5,6 +5,7 @@
#include <nxt_router.h>
#include <nxt_http.h>
+#include <nxt_http_compression.h>
typedef struct {
@@ -576,7 +577,37 @@ nxt_http_static_send(nxt_task_t *task, nxt_http_request_t *r,
field->value_length = mtype->length;
}
+ r->resp.mime_type = mtype;
+
if (ctx->need_body && nxt_file_size(&fi) > 0) {
+ ret = nxt_http_comp_check_compression(task, r);
+ if (ret == NXT_HTTP_NOT_ACCEPTABLE) {
+ nxt_http_request_error(task, r, NXT_HTTP_NOT_ACCEPTABLE);
+ return;
+ } else if (ret != NXT_OK) {
+ goto fail;
+ }
+
+ if (nxt_http_comp_wants_compression()) {
+ size_t out_total;
+ nxt_int_t ret;
+
+ ret = nxt_http_comp_compress_static_response(
+ task, &f, &fi,
+ NXT_HTTP_STATIC_BUF_SIZE,
+ &out_total);
+ if (ret == NXT_ERROR) {
+ goto fail;
+ }
+
+ ret = nxt_file_info(f, &fi);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
+
+ r->resp.content_length_n = out_total;
+ }
+
fb = nxt_mp_zget(r->mem_pool, NXT_BUF_FILE_SIZE);
if (nxt_slow_path(fb == NULL)) {
goto fail;