Optimize code and fix gzip encoding
Signed-off-by: zhaojh329 <zhaojh329@gmail.com>main
parent
87a209c3b8
commit
28c8146740
|
@ -36,16 +36,18 @@ static const char *index_page = "index.html";
|
||||||
static void on_request(struct uh_connection *conn)
|
static void on_request(struct uh_connection *conn)
|
||||||
{
|
{
|
||||||
if (!serve_file) {
|
if (!serve_file) {
|
||||||
int body_len;
|
const struct uh_str path = conn->get_path(conn);
|
||||||
const char *body = conn->get_body(conn, &body_len);
|
const struct uh_str query = conn->get_query(conn);
|
||||||
|
const struct uh_str ua = conn->get_header(conn, "User-Agent");
|
||||||
|
const struct uh_str body = conn->get_body(conn);
|
||||||
|
|
||||||
conn->send_head(conn, HTTP_STATUS_OK, -1, NULL);
|
conn->send_head(conn, HTTP_STATUS_OK, -1, NULL);
|
||||||
conn->chunk_printf(conn, "I'm Libuhttpd: %s\n", UHTTPD_VERSION_STRING);
|
conn->chunk_printf(conn, "I'm Libuhttpd: %s\n", UHTTPD_VERSION_STRING);
|
||||||
conn->chunk_printf(conn, "Method: %s\n", conn->get_method_str(conn));
|
conn->chunk_printf(conn, "Method: %s\n", conn->get_method_str(conn));
|
||||||
conn->chunk_printf(conn, "Path: %s\n", conn->get_path(conn));
|
conn->chunk_printf(conn, "Path: %.*s\n", path.len ,path.p);
|
||||||
conn->chunk_printf(conn, "Query: %s\n", conn->get_query(conn));
|
conn->chunk_printf(conn, "Query: %.*s\n", query.len, query.p);
|
||||||
conn->chunk_printf(conn, "User-Agent: %s\n", conn->get_header(conn, "User-Agent"));
|
conn->chunk_printf(conn, "User-Agent: %.*s\n", ua.len, ua.p);
|
||||||
conn->chunk_printf(conn, "Body: %.*s\n", body_len, body);
|
conn->chunk_printf(conn, "Body: %.*s\n", body.len, body.p);
|
||||||
conn->chunk_end(conn);
|
conn->chunk_end(conn);
|
||||||
} else {
|
} else {
|
||||||
conn->serve_file(conn, docroot, index_page);
|
conn->serve_file(conn, docroot, index_page);
|
||||||
|
|
113
src/connection.c
113
src/connection.c
|
@ -169,75 +169,58 @@ static const char *conn_get_method_str(struct uh_connection *conn)
|
||||||
return http_method_str(conn->parser.method);
|
return http_method_str(conn->parser.method);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* offset of the request field */
|
static const struct uh_str conn_get_path(struct uh_connection *conn)
|
||||||
#define ROF(c, a) (a - (const char *)c->rb.data)
|
|
||||||
|
|
||||||
/* data of the request field */
|
|
||||||
#define O2D(c, o) ((const char *)c->rb.data + o)
|
|
||||||
|
|
||||||
static const char *conn_get_path(struct uh_connection *conn)
|
|
||||||
{
|
{
|
||||||
struct http_parser_url *u = &conn->url_parser;
|
struct http_parser_url *u = &conn->url_parser;
|
||||||
struct uh_request *req = &conn->req;
|
struct uh_request *req = &conn->req;
|
||||||
|
struct uh_str path;
|
||||||
|
|
||||||
if (!req->url.path)
|
path.p = req->url.p + u->field_data[UF_PATH].off;
|
||||||
req->url.path = strndup(O2D(conn, u->field_data[UF_PATH].off) + req->url.offset, u->field_data[UF_PATH].len);
|
path.len = u->field_data[UF_PATH].len;
|
||||||
return req->url.path;
|
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *conn_get_query(struct uh_connection *conn)
|
static const struct uh_str conn_get_query(struct uh_connection *conn)
|
||||||
{
|
{
|
||||||
struct http_parser_url *u = &conn->url_parser;
|
struct http_parser_url *u = &conn->url_parser;
|
||||||
struct uh_request *req = &conn->req;
|
struct uh_request *req = &conn->req;
|
||||||
|
struct uh_str query = {};
|
||||||
|
|
||||||
if (!(u->field_set & (1 << UF_QUERY)))
|
if (!(u->field_set & (1 << UF_QUERY)))
|
||||||
return "";
|
return query;
|
||||||
|
|
||||||
if (!req->url.query)
|
query.p = req->url.p + u->field_data[UF_QUERY].off;
|
||||||
req->url.query = strndup(O2D(conn, u->field_data[UF_QUERY].off) + req->url.offset, u->field_data[UF_QUERY].len);
|
query.len = u->field_data[UF_QUERY].len;
|
||||||
|
|
||||||
return req->url.query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *conn_get_header(struct uh_connection *conn, const char *name)
|
static const struct uh_str conn_get_header(struct uh_connection *conn, const char *name)
|
||||||
{
|
{
|
||||||
struct uh_request *req = &conn->req;
|
struct uh_request *req = &conn->req;
|
||||||
int name_len = strlen(name);
|
int name_len = strlen(name);
|
||||||
int i, j;
|
struct uh_str *field;
|
||||||
|
struct uh_str value = {};
|
||||||
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < UHTTPD_MAX_HEADER_NUM; i++) {
|
for (i = 0; i < UHTTPD_MAX_HEADER_NUM; i++) {
|
||||||
if (!req->headers[i].name)
|
field = &req->headers[i].field;
|
||||||
break;
|
if (!field->p)
|
||||||
if (!strcasecmp(req->headers[i].name, name))
|
return value;
|
||||||
return req->headers[i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == UHTTPD_MAX_HEADER_NUM)
|
if (name_len == field->len && !strncasecmp(field->p, name, name_len)) {
|
||||||
return NULL;
|
value.p = req->headers[i].value.p;
|
||||||
|
value.len = req->headers[i].value.len;
|
||||||
for (j = 0; j < UHTTPD_MAX_HEADER_NUM; j++) {
|
|
||||||
if (req->headers_info[j].name_offset > 0) {
|
|
||||||
const char *p = O2D(conn, req->headers_info[j].name_offset);
|
|
||||||
if (name_len == req->headers_info[j].name_len && !strncasecmp(p, name, req->headers_info[j].name_len)) {
|
|
||||||
req->headers[i].name = strndup(p, req->headers_info[j].name_len);
|
|
||||||
req->headers[i].value = strndup(O2D(conn, req->headers_info[j].value_offset), req->headers_info[j].value_len);
|
|
||||||
req->headers_info[j].name_len = 0;
|
|
||||||
return req->headers[i].value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *conn_get_body(struct uh_connection *conn, int *len)
|
static const struct uh_str conn_get_body(struct uh_connection *conn)
|
||||||
{
|
{
|
||||||
struct uh_request *req = &conn->req;
|
return conn->req.body;
|
||||||
const char *at = O2D(conn, req->body.offset);
|
|
||||||
|
|
||||||
*len = req->body.len;
|
|
||||||
|
|
||||||
return at;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_message_begin_cb(struct http_parser *parser)
|
static int on_message_begin_cb(struct http_parser *parser)
|
||||||
|
@ -247,20 +230,19 @@ static int on_message_begin_cb(struct http_parser *parser)
|
||||||
|
|
||||||
req->last_was_header_value = true;
|
req->last_was_header_value = true;
|
||||||
|
|
||||||
|
http_parser_url_init(&conn->url_parser);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_url_cb(struct http_parser *parser, const char *at, size_t length)
|
static int on_url_cb(struct http_parser *parser, const char *at, size_t length)
|
||||||
{
|
{
|
||||||
struct uh_connection *conn = (struct uh_connection *)parser->data;
|
struct uh_connection *conn = (struct uh_connection *)parser->data;
|
||||||
struct uh_request *req = &conn->req;
|
struct uh_str *url = &conn->req.url;
|
||||||
|
|
||||||
if (req->url.offset == 0) {
|
if (!url->p)
|
||||||
req->url.offset = ROF(conn, at);
|
url->p = at;
|
||||||
http_parser_url_init(&conn->url_parser);
|
url->len += length;
|
||||||
}
|
|
||||||
|
|
||||||
req->url.length += length;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -279,10 +261,10 @@ static int on_header_field_cb(struct http_parser *parser, const char *at, size_t
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->headers_info[req->header_num - 1].name_offset = ROF(conn, at);
|
req->headers[req->header_num - 1].field.p = at;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->headers_info[req->header_num - 1].name_len += length;
|
req->headers[req->header_num - 1].field.len += length;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -294,10 +276,10 @@ static int on_header_value_cb(struct http_parser *parser, const char *at, size_t
|
||||||
|
|
||||||
if (!req->last_was_header_value) {
|
if (!req->last_was_header_value) {
|
||||||
req->last_was_header_value = true;
|
req->last_was_header_value = true;
|
||||||
req->headers_info[req->header_num - 1].value_offset = ROF(conn, at);
|
req->headers[req->header_num - 1].value.p = at;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->headers_info[req->header_num - 1].value_len += length;
|
req->headers[req->header_num - 1].value.len += length;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -307,8 +289,8 @@ static int on_body_cb(struct http_parser *parser, const char *at, size_t length)
|
||||||
struct uh_connection *conn = (struct uh_connection *)parser->data;
|
struct uh_connection *conn = (struct uh_connection *)parser->data;
|
||||||
struct uh_request *req = &conn->req;
|
struct uh_request *req = &conn->req;
|
||||||
|
|
||||||
if (req->body.offset == 0)
|
if (!req->body.p)
|
||||||
req->body.offset = ROF(conn, at);
|
req->body.p = at;
|
||||||
req->body.len += length;
|
req->body.len += length;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -317,9 +299,10 @@ static int on_body_cb(struct http_parser *parser, const char *at, size_t length)
|
||||||
static bool run_plugins(struct uh_connection *conn)
|
static bool run_plugins(struct uh_connection *conn)
|
||||||
{
|
{
|
||||||
struct uh_plugin *p = conn->srv->plugins;
|
struct uh_plugin *p = conn->srv->plugins;
|
||||||
|
struct uh_str path = conn->get_path(conn);
|
||||||
|
|
||||||
while (p) {
|
while (p) {
|
||||||
if (!strcmp(conn->get_path(conn), p->path)) {
|
if (strlen(p->path) == path.len && !strncmp(path.p, p->path, path.len)) {
|
||||||
p->handler(conn);
|
p->handler(conn);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -332,9 +315,8 @@ static int on_message_complete_cb(struct http_parser *parser)
|
||||||
{
|
{
|
||||||
struct uh_connection *conn = (struct uh_connection *)parser->data;
|
struct uh_connection *conn = (struct uh_connection *)parser->data;
|
||||||
struct uh_request *req = &conn->req;
|
struct uh_request *req = &conn->req;
|
||||||
int i;
|
|
||||||
|
|
||||||
http_parser_parse_url(O2D(conn, req->url.offset), req->url.length, false, &conn->url_parser);
|
http_parser_parse_url(req->url.p, req->url.len, false, &conn->url_parser);
|
||||||
|
|
||||||
if (!run_plugins(conn)) {
|
if (!run_plugins(conn)) {
|
||||||
if (conn->srv->on_request)
|
if (conn->srv->on_request)
|
||||||
|
@ -345,19 +327,6 @@ static int on_message_complete_cb(struct http_parser *parser)
|
||||||
|
|
||||||
buffer_pull(&conn->rb, NULL, buffer_length(&conn->rb));
|
buffer_pull(&conn->rb, NULL, buffer_length(&conn->rb));
|
||||||
|
|
||||||
if (req->url.path)
|
|
||||||
free(req->url.path);
|
|
||||||
|
|
||||||
if (req->url.query)
|
|
||||||
free(req->url.query);
|
|
||||||
|
|
||||||
for (i = 0; i < UHTTPD_MAX_HEADER_NUM; i++) {
|
|
||||||
if (req->headers[i].name)
|
|
||||||
free(req->headers[i].name);
|
|
||||||
if (req->headers[i].value)
|
|
||||||
free(req->headers[i].value);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(req, 0, sizeof(struct uh_request));
|
memset(req, 0, sizeof(struct uh_request));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -441,7 +410,7 @@ static void conn_write_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||||
|
|
||||||
if (buffer_length(&conn->wb) == 0) {
|
if (buffer_length(&conn->wb) == 0) {
|
||||||
if (conn->file.fd > 0) {
|
if (conn->file.fd > 0) {
|
||||||
ssize_t ret = sendfile(w->fd, conn->file.fd, NULL, conn->file.size);
|
ret = sendfile(w->fd, conn->file.fd, NULL, conn->file.size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
uh_log_err("write error: %s\n", strerror(errno));
|
uh_log_err("write error: %s\n", strerror(errno));
|
||||||
|
|
|
@ -41,31 +41,22 @@
|
||||||
|
|
||||||
struct uh_server;
|
struct uh_server;
|
||||||
|
|
||||||
struct uh_request {
|
struct uh_str {
|
||||||
struct {
|
const char *p;
|
||||||
int length;
|
size_t len;
|
||||||
int offset;
|
};
|
||||||
char *path;
|
|
||||||
char *query;
|
struct uh_request {
|
||||||
} url;
|
struct uh_str url;
|
||||||
|
|
||||||
struct {
|
|
||||||
int name_offset;
|
|
||||||
int name_len;
|
|
||||||
int value_offset;
|
|
||||||
int value_len;
|
|
||||||
} headers_info[UHTTPD_MAX_HEADER_NUM];
|
|
||||||
int header_num;
|
int header_num;
|
||||||
bool last_was_header_value;
|
bool last_was_header_value;
|
||||||
struct {
|
struct {
|
||||||
char *name;
|
struct uh_str field;
|
||||||
char *value;
|
struct uh_str value;
|
||||||
} headers[UHTTPD_MAX_HEADER_NUM];
|
} headers[UHTTPD_MAX_HEADER_NUM];
|
||||||
|
|
||||||
struct {
|
struct uh_str body;
|
||||||
int offset;
|
|
||||||
int len;
|
|
||||||
} body;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uh_connection {
|
struct uh_connection {
|
||||||
|
@ -107,10 +98,10 @@ struct uh_connection {
|
||||||
void (*chunk_end)(struct uh_connection *conn);
|
void (*chunk_end)(struct uh_connection *conn);
|
||||||
enum http_method (*get_method)(struct uh_connection *conn);
|
enum http_method (*get_method)(struct uh_connection *conn);
|
||||||
const char *(*get_method_str)(struct uh_connection *conn);
|
const char *(*get_method_str)(struct uh_connection *conn);
|
||||||
const char *(*get_path)(struct uh_connection *conn);
|
const struct uh_str (*get_path)(struct uh_connection *conn);
|
||||||
const char *(*get_query)(struct uh_connection *conn);
|
const struct uh_str (*get_query)(struct uh_connection *conn);
|
||||||
const char *(*get_header)(struct uh_connection *conn, const char *name);
|
const struct uh_str (*get_header)(struct uh_connection *conn, const char *name);
|
||||||
const char *(*get_body)(struct uh_connection *conn, int *len);
|
const struct uh_str (*get_body)(struct uh_connection *conn);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uh_connection *uh_new_connection(struct uh_server *srv, int sock, struct sockaddr_in *addr);
|
struct uh_connection *uh_new_connection(struct uh_server *srv, int sock, struct sockaddr_in *addr);
|
||||||
|
|
64
src/file.c
64
src/file.c
|
@ -32,11 +32,12 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "mimetypes.h"
|
#include "mimetypes.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static const char *file_mktag(struct stat *s, char *buf, int len)
|
static const char *file_mktag(struct stat *s, char *buf, int len)
|
||||||
{
|
{
|
||||||
|
@ -55,13 +56,16 @@ static char *unix2date(time_t ts, char *buf, int len)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static time_t date2unix(const char *date)
|
static time_t date2unix(const struct uh_str date)
|
||||||
{
|
{
|
||||||
struct tm t;
|
struct tm t;
|
||||||
|
char buf[128] = "";
|
||||||
|
|
||||||
memset(&t, 0, sizeof(t));
|
memset(&t, 0, sizeof(t));
|
||||||
|
|
||||||
if (strptime(date, "%a, %d %b %Y %H:%M:%S %Z", &t) != NULL)
|
strncpy(buf, date.p, date.len);
|
||||||
|
|
||||||
|
if (strptime(buf, "%a, %d %b %Y %H:%M:%S %Z", &t) != NULL)
|
||||||
return timegm(&t);
|
return timegm(&t);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -88,8 +92,8 @@ static void file_response_304(struct uh_connection *conn, struct stat *s)
|
||||||
|
|
||||||
static bool file_if_modified_since(struct uh_connection *conn, struct stat *s)
|
static bool file_if_modified_since(struct uh_connection *conn, struct stat *s)
|
||||||
{
|
{
|
||||||
const char *hdr = conn->get_header(conn, "If-Modified-Since");
|
const struct uh_str hdr = conn->get_header(conn, "If-Modified-Since");
|
||||||
if (!hdr)
|
if (!hdr.p)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (date2unix(hdr) >= s->st_mtime) {
|
if (date2unix(hdr) >= s->st_mtime) {
|
||||||
|
@ -102,7 +106,8 @@ static bool file_if_modified_since(struct uh_connection *conn, struct stat *s)
|
||||||
|
|
||||||
static bool file_if_range(struct uh_connection *conn, struct stat *s)
|
static bool file_if_range(struct uh_connection *conn, struct stat *s)
|
||||||
{
|
{
|
||||||
if (conn->get_header(conn, "If-Range")) {
|
const struct uh_str hdr = conn->get_header(conn, "If-Range");
|
||||||
|
if (hdr.p) {
|
||||||
conn->error(conn, HTTP_STATUS_PRECONDITION_FAILED, NULL);
|
conn->error(conn, HTTP_STATUS_PRECONDITION_FAILED, NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -112,8 +117,8 @@ static bool file_if_range(struct uh_connection *conn, struct stat *s)
|
||||||
|
|
||||||
static bool file_if_unmodified_since(struct uh_connection *conn, struct stat *s)
|
static bool file_if_unmodified_since(struct uh_connection *conn, struct stat *s)
|
||||||
{
|
{
|
||||||
const char *hdr = conn->get_header(conn, "If-Modified-Since");
|
const struct uh_str hdr = conn->get_header(conn, "If-Modified-Since");
|
||||||
if (hdr && date2unix(hdr) <= s->st_mtime) {
|
if (hdr.p && date2unix(hdr) <= s->st_mtime) {
|
||||||
conn->error(conn, HTTP_STATUS_PRECONDITION_FAILED, NULL);
|
conn->error(conn, HTTP_STATUS_PRECONDITION_FAILED, NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -121,22 +126,37 @@ static bool file_if_unmodified_since(struct uh_connection *conn, struct stat *s)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_if_gzip(struct uh_connection *conn, const char *path)
|
static void file_if_gzip(struct uh_connection *conn, const char *path, const char *mime)
|
||||||
{
|
{
|
||||||
const char *hdr = conn->get_header(conn, "Accept-Encoding");
|
const struct uh_str hdr = conn->get_header(conn, "Accept-Encoding");
|
||||||
const char *extn = rindex(path, '.');
|
uint8_t magic[2] = {};
|
||||||
|
int fd;
|
||||||
|
|
||||||
if (!hdr || !strstr(hdr, "gzip"))
|
if (!hdr.p || !memmem(hdr.p, hdr.len, "gzip", 4))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (extn && !strcmp(extn, ".gz"))
|
if (strcmp(mime, "text/css") && strcmp(mime, "text/javascript") && strcmp(mime, "text/html"))
|
||||||
conn->printf(conn, "Content-Encoding: gzip\r\n");
|
return;
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (read(fd, magic, 2) != 2) {
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
/* gzip magic */
|
||||||
|
if (magic[0] != 0x1f || magic[1] != 0x8b)
|
||||||
|
return;
|
||||||
|
|
||||||
|
conn->printf(conn, "Content-Encoding: gzip\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void serve_file(struct uh_connection *conn, const char *docroot, const char *index_page)
|
void serve_file(struct uh_connection *conn, const char *docroot, const char *index_page)
|
||||||
{
|
{
|
||||||
const char *path = conn->get_path(conn);
|
const struct uh_str path = conn->get_path(conn);
|
||||||
static char fullpath[512];
|
static char fullpath[512];
|
||||||
|
const char *mime;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (!docroot || !docroot[0])
|
if (!docroot || !docroot[0])
|
||||||
|
@ -147,12 +167,12 @@ void serve_file(struct uh_connection *conn, const char *docroot, const char *ind
|
||||||
|
|
||||||
strcpy(fullpath, docroot);
|
strcpy(fullpath, docroot);
|
||||||
|
|
||||||
if (!strcmp(path, "/")) {
|
if (!strncmp(path.p, "/", path.len)) {
|
||||||
strcat(fullpath, "/");
|
strcat(fullpath, "/");
|
||||||
path = index_page;
|
strcat(fullpath, index_page);
|
||||||
|
} else {
|
||||||
|
strncat(fullpath, path.p, path.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat(fullpath, path);
|
|
||||||
|
|
||||||
if (stat(fullpath, &st) < 0) {
|
if (stat(fullpath, &st) < 0) {
|
||||||
int code;
|
int code;
|
||||||
|
@ -196,10 +216,12 @@ void serve_file(struct uh_connection *conn, const char *docroot, const char *ind
|
||||||
conn->send_status_line(conn, HTTP_STATUS_OK, NULL);
|
conn->send_status_line(conn, HTTP_STATUS_OK, NULL);
|
||||||
file_response_ok_hdrs(conn, &st);
|
file_response_ok_hdrs(conn, &st);
|
||||||
|
|
||||||
conn->printf(conn, "Content-Type: %s\r\n", file_mime_lookup(path));
|
mime = file_mime_lookup(fullpath);
|
||||||
|
|
||||||
|
conn->printf(conn, "Content-Type: %s\r\n", mime);
|
||||||
conn->printf(conn, "Content-Length: %" PRIu64 "\r\n", st.st_size);
|
conn->printf(conn, "Content-Length: %" PRIu64 "\r\n", st.st_size);
|
||||||
|
|
||||||
file_if_gzip(conn, path);
|
file_if_gzip(conn, fullpath, mime);
|
||||||
|
|
||||||
conn->printf(conn, "\r\n");
|
conn->printf(conn, "\r\n");
|
||||||
|
|
||||||
|
|
|
@ -102,8 +102,8 @@ const char *file_mime_lookup(const char *path)
|
||||||
while (m->extn) {
|
while (m->extn) {
|
||||||
e = &path[strlen(path)-1];
|
e = &path[strlen(path)-1];
|
||||||
|
|
||||||
while (e >= path) {
|
while (e >= path && *e != '/') {
|
||||||
if ((*e == '.' || *e == '/') && !strcasecmp(&e[1], m->extn))
|
if (*e == '.' && !strcasecmp(&e[1], m->extn))
|
||||||
return m->mime;
|
return m->mime;
|
||||||
|
|
||||||
e--;
|
e--;
|
||||||
|
|
Loading…
Reference in New Issue