mirror of
https://github.com/cesanta/mongoose.git
synced 2025-08-06 13:37:34 +08:00
Merge pull request #2166 from cesanta/gzip
Fix #1927: respect Accept-Encoding when serving .gz files
This commit is contained in:
commit
4593332204
32
mongoose.c
32
mongoose.c
@ -1683,28 +1683,30 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
||||
const struct mg_http_serve_opts *opts) {
|
||||
char etag[64], tmp[MG_PATH_MAX];
|
||||
struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
|
||||
struct mg_fd *fd = path == NULL ? NULL : mg_fs_open(fs, path, MG_FS_READ);
|
||||
struct mg_fd *fd = NULL;
|
||||
size_t size = 0;
|
||||
time_t mtime = 0;
|
||||
struct mg_str *inm = NULL;
|
||||
struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
|
||||
bool gzip = false;
|
||||
|
||||
// If file does not exist, we try to open file PATH.gz - and if such
|
||||
// pre-compressed .gz file exists, serve it with the Content-Encoding: gzip
|
||||
// Note - we ignore Accept-Encoding, cause we don't have a choice
|
||||
if (fd == NULL) {
|
||||
MG_DEBUG(("NULL [%s]", path));
|
||||
mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
|
||||
if ((fd = mg_fs_open(fs, tmp, MG_FS_READ)) != NULL) {
|
||||
gzip = true;
|
||||
path = tmp;
|
||||
} else if (opts->page404 != NULL) {
|
||||
// No precompressed file, serve 404
|
||||
fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
|
||||
mime = guess_content_type(mg_str(path), opts->mime_types);
|
||||
path = opts->page404;
|
||||
if (path != NULL) {
|
||||
// If a browser sends us "Accept-Encoding: gzip", try to open .gz first
|
||||
struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
|
||||
if (ae != NULL && mg_strstr(*ae, mg_str("gzip")) != NULL) {
|
||||
mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
|
||||
fd = mg_fs_open(fs, tmp, MG_FS_READ);
|
||||
if (fd != NULL) gzip = true, path = tmp;
|
||||
}
|
||||
// No luck opening .gz? Open what we've told to open
|
||||
if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
|
||||
}
|
||||
|
||||
// Failed to open, and page404 is configured? Open it, then
|
||||
if (fd == NULL && opts->page404 != NULL) {
|
||||
fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
|
||||
mime = guess_content_type(mg_str(path), opts->mime_types);
|
||||
path = opts->page404;
|
||||
}
|
||||
|
||||
if (fd == NULL || fs->st(path, &size, &mtime) == 0) {
|
||||
|
32
src/http.c
32
src/http.c
@ -453,28 +453,30 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
||||
const struct mg_http_serve_opts *opts) {
|
||||
char etag[64], tmp[MG_PATH_MAX];
|
||||
struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
|
||||
struct mg_fd *fd = path == NULL ? NULL : mg_fs_open(fs, path, MG_FS_READ);
|
||||
struct mg_fd *fd = NULL;
|
||||
size_t size = 0;
|
||||
time_t mtime = 0;
|
||||
struct mg_str *inm = NULL;
|
||||
struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
|
||||
bool gzip = false;
|
||||
|
||||
// If file does not exist, we try to open file PATH.gz - and if such
|
||||
// pre-compressed .gz file exists, serve it with the Content-Encoding: gzip
|
||||
// Note - we ignore Accept-Encoding, cause we don't have a choice
|
||||
if (fd == NULL) {
|
||||
MG_DEBUG(("NULL [%s]", path));
|
||||
mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
|
||||
if ((fd = mg_fs_open(fs, tmp, MG_FS_READ)) != NULL) {
|
||||
gzip = true;
|
||||
path = tmp;
|
||||
} else if (opts->page404 != NULL) {
|
||||
// No precompressed file, serve 404
|
||||
fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
|
||||
mime = guess_content_type(mg_str(path), opts->mime_types);
|
||||
path = opts->page404;
|
||||
if (path != NULL) {
|
||||
// If a browser sends us "Accept-Encoding: gzip", try to open .gz first
|
||||
struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
|
||||
if (ae != NULL && mg_strstr(*ae, mg_str("gzip")) != NULL) {
|
||||
mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
|
||||
fd = mg_fs_open(fs, tmp, MG_FS_READ);
|
||||
if (fd != NULL) gzip = true, path = tmp;
|
||||
}
|
||||
// No luck opening .gz? Open what we've told to open
|
||||
if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
|
||||
}
|
||||
|
||||
// Failed to open, and page404 is configured? Open it, then
|
||||
if (fd == NULL && opts->page404 != NULL) {
|
||||
fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
|
||||
mime = guess_content_type(mg_str(path), opts->mime_types);
|
||||
path = opts->page404;
|
||||
}
|
||||
|
||||
if (fd == NULL || fs->st(path, &size, &mtime) == 0) {
|
||||
|
1
test/data/gzip.txt
Normal file
1
test/data/gzip.txt
Normal file
@ -0,0 +1 @@
|
||||
hi
|
BIN
test/data/gzip.txt.gz
Normal file
BIN
test/data/gzip.txt.gz
Normal file
Binary file not shown.
@ -635,21 +635,25 @@ static int fetch(struct mg_mgr *mgr, char *buf, const char *url,
|
||||
return fd.code;
|
||||
}
|
||||
|
||||
static int cmpbody(const char *buf, const char *str) {
|
||||
static struct mg_http_message gethm(const char *buf) {
|
||||
struct mg_http_message hm;
|
||||
memset(&hm, 0, sizeof(hm));
|
||||
mg_http_parse(buf, strlen(buf), &hm);
|
||||
return hm;
|
||||
}
|
||||
|
||||
static int cmpbody(const char *buf, const char *str) {
|
||||
struct mg_str s = mg_str(str);
|
||||
struct mg_http_message hm = gethm(buf);
|
||||
size_t len = strlen(buf);
|
||||
mg_http_parse(buf, len, &hm);
|
||||
if (hm.body.len > len) hm.body.len = len - (size_t)(hm.body.ptr - buf);
|
||||
if (hm.body.len > len) hm.body.len = len - (size_t) (hm.body.ptr - buf);
|
||||
return mg_strcmp(hm.body, s);
|
||||
}
|
||||
|
||||
static bool cmpheader(const char *buf, const char *name, const char *value) {
|
||||
struct mg_http_message hm;
|
||||
struct mg_str *h;
|
||||
size_t len = strlen(buf);
|
||||
mg_http_parse(buf, len, &hm);
|
||||
h = mg_http_get_header(&hm, name);
|
||||
struct mg_http_message hm = gethm(buf);
|
||||
struct mg_str *h = mg_http_get_header(&hm, name);
|
||||
return h != NULL && mg_strcmp(*h, mg_str(value)) == 0;
|
||||
}
|
||||
|
||||
@ -765,10 +769,24 @@ static void test_http_server(void) {
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /dredir/ HTTP/1.0\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, "hi\n") == 0);
|
||||
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /dredirgz/ HTTP/1.0\n\n") == 200);
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"GET /dredirgz/ HTTP/1.0\n"
|
||||
"Accept-Encoding: gzip\n\n") == 200);
|
||||
ASSERT(cmpheader(buf, "Content-Type", "text/html; charset=utf-8"));
|
||||
ASSERT(cmpheader(buf, "Content-Encoding", "gzip"));
|
||||
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /gzip.txt HTTP/1.0\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, "hi\n") == 0);
|
||||
ASSERT(gethm(buf).body.len == 3);
|
||||
ASSERT(cmpheader(buf, "Content-Encoding", "gzip") == false);
|
||||
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"GET /gzip.txt HTTP/1.0\n"
|
||||
"Accept-Encoding: foo,gzip\n\n") == 200);
|
||||
mg_hexdump(buf, strlen(buf));
|
||||
ASSERT(cmpheader(buf, "Content-Encoding", "gzip") == true);
|
||||
ASSERT(gethm(buf).body.len == 23);
|
||||
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /..ddot HTTP/1.0\n\n") == 301);
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /..ddot/ HTTP/1.0\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, "hi\n") == 0);
|
||||
@ -937,7 +955,9 @@ static void test_http_server(void) {
|
||||
// Pre-compressed files
|
||||
{
|
||||
struct mg_http_message hm;
|
||||
ASSERT(fetch(&mgr, buf, url, "HEAD /hello.txt HTTP/1.0\n\n") == 200);
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"HEAD /hello.txt HTTP/1.0\n"
|
||||
"Accept-Encoding: gzip\n\n") == 200);
|
||||
mg_http_parse(buf, strlen(buf), &hm);
|
||||
ASSERT(mg_http_get_header(&hm, "Content-Encoding") != NULL);
|
||||
ASSERT(mg_strcmp(*mg_http_get_header(&hm, "Content-Encoding"),
|
||||
@ -1381,9 +1401,7 @@ static void test_http_range(void) {
|
||||
ASSERT(mgr.conns == NULL);
|
||||
}
|
||||
|
||||
static void f1(void *arg) {
|
||||
(*(int *) arg)++;
|
||||
}
|
||||
static void f1(void *arg) { (*(int *) arg)++; }
|
||||
|
||||
static void test_timer(void) {
|
||||
int v1 = 0, v2 = 0, v3 = 0;
|
||||
@ -2841,9 +2859,7 @@ static void start_thread(void (*f)(void *), void *p) {
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
#else
|
||||
static void start_thread(void (*f)(void *), void *p) {
|
||||
(void) f, (void) p;
|
||||
}
|
||||
static void start_thread(void (*f)(void *), void *p) { (void) f, (void) p; }
|
||||
#endif
|
||||
|
||||
static void test_queue(void) {
|
||||
|
Loading…
Reference in New Issue
Block a user