--static-map mountpoint=documentroot option

This commit is contained in:
roberto@natty32
2011-04-04 08:31:17 +02:00
parent a26579fcf5
commit b326500913
4 changed files with 168 additions and 30 deletions
+90 -30
View File
@@ -779,42 +779,25 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
}
}
// check i fa file name uwsgi.check_static+env['PATH_INFO'] exists
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
if (uwsgi.check_static && wsgi_req->path_info_len > 1) {
struct stat st;
char *filename = uwsgi_concat2n(uwsgi.check_static, uwsgi.check_static_len, wsgi_req->path_info, wsgi_req->path_info_len);
if (!uwsgi_file_serve(wsgi_req, uwsgi.check_static, uwsgi.check_static_len, wsgi_req->path_info, wsgi_req->path_info_len)) {
return -1;
}
}
// check static-map
struct uwsgi_static_map *usm = uwsgi.static_maps;
while(usm) {
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %s\n", filename);
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, usm->mountpoint_len, usm->mountpoint);
#endif
if (!stat(filename, &st)) {
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st.st_mtime <= ims) {
wsgi_req->status = 304;
wsgi_req->headers_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " 304 Not Modified\r\n\r\n", 21);
return -1;
}
}
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
char http_last_modified[49];
#ifdef UWSGI_DEBUG
uwsgi_log("file %s found\n", filename);
#endif
// no need to set content-type/content-length, they will be fixed by the http server/router
wsgi_req->sendfile_fd = open(filename, O_RDONLY);
wsgi_req->headers_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " 200 OK\r\n", 9);
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
wsgi_req->header_cnt = 1;
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
wsgi_req->status = 200;
free(filename);
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, usm->mountpoint, usm->mountpoint_len)) {
if (!uwsgi_file_serve(wsgi_req, usm->document_root, usm->document_root_len, wsgi_req->path_info+usm->mountpoint_len, wsgi_req->path_info_len-usm->mountpoint_len)) {
return -1;
}
}
free(filename);
usm = usm->next;
}
return 0;
@@ -1317,3 +1300,80 @@ int uwsgi_simple_send_string(char *socket_name, uint8_t modifier1, uint8_t modif
return 0;
}
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len) {
struct stat st;
char real_filename[PATH_MAX];
char *filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %s\n", filename);
#endif
if (!realpath(filename, real_filename)) {
#ifdef UWSGI_DEBUG
uwsgi_log("unable to get realpath() of the static file\n");
#endif
free(filename);
return -1;
}
free(filename);
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
uwsgi_log("security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
return -1;
}
if (!stat(real_filename, &st)) {
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st.st_mtime <= ims) {
wsgi_req->status = 304;
wsgi_req->headers_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " 304 Not Modified\r\n\r\n", 21);
return 0;
}
}
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
char http_last_modified[49];
#ifdef UWSGI_DEBUG
uwsgi_log("file %s found\n", real_filename);
#endif
// no need to set content-type/content-length, they will be fixed by the http server/router
wsgi_req->headers_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " 200 OK\r\n", 9);
if (uwsgi.file_serve_mode == 1) {
wsgi_req->header_cnt = 2;
wsgi_req->headers_size += write(wsgi_req->poll.fd, "X-Accel-Redirect: ", 18);
wsgi_req->headers_size += write(wsgi_req->poll.fd, path_info, path_info_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
}
else if (uwsgi.file_serve_mode == 2) {
wsgi_req->header_cnt = 2;
wsgi_req->headers_size += write(wsgi_req->poll.fd, "X-Sendfile: ", 12);
wsgi_req->headers_size += write(wsgi_req->poll.fd, real_filename, strlen(real_filename));
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
}
else {
wsgi_req->header_cnt = 1;
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
wsgi_req->sendfile_fd = open(real_filename, O_RDONLY);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
}
wsgi_req->status = 200;
return 0;
}
}
return -1;
}
+7
View File
@@ -718,6 +718,13 @@ inline int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
}
inline int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
if (slen < dlen) return -1;
return memcmp(src, dst, dlen);
}
inline int uwsgi_startswith(char *src, char *what, int wlen) {
int i;
+52
View File
@@ -156,6 +156,8 @@ static struct option long_base_options[] = {
{"routing", no_argument, &uwsgi.routing, 1},
#endif
{"check-static", required_argument, 0, LONG_ARGS_CHECK_STATIC},
{"static-map", required_argument, 0, LONG_ARGS_STATIC_MAP},
{"file-serve-mode", required_argument, 0, LONG_ARGS_FILE_SERVE_MODE},
{"check-cache", no_argument, &uwsgi.check_cache, 1},
{"close-on-exec", no_argument, &uwsgi.close_on_exec, 1},
{"mode", required_argument, 0, LONG_ARGS_MODE},
@@ -2266,6 +2268,7 @@ end:
static int manage_base_opt(int i, char *optarg) {
char *p;
struct uwsgi_static_map *usm;
switch (i) {
@@ -2434,6 +2437,55 @@ end:
uwsgi.check_static = optarg;
uwsgi.check_static_len = strlen(uwsgi.check_static);
return 1;
case LONG_ARGS_FILE_SERVE_MODE:
if (!strcasecmp("x-sendfile", optarg)) {
uwsgi.file_serve_mode = 2;
}
else if (!strcasecmp("xsendfile", optarg)) {
uwsgi.file_serve_mode = 2;
}
else if (!strcasecmp("x-accel-redirect", optarg)) {
uwsgi.file_serve_mode = 1;
}
else if (!strcasecmp("xaccelredirect", optarg)) {
uwsgi.file_serve_mode = 1;
}
else if (!strcasecmp("nginx", optarg)) {
uwsgi.file_serve_mode = 1;
}
return 1;
case LONG_ARGS_STATIC_MAP:
usm = uwsgi.static_maps;
if (!usm) {
usm = uwsgi_malloc(sizeof(struct uwsgi_static_map));
uwsgi.static_maps = usm;
}
else {
while(usm->next) {
if (!usm->next) {
usm->next = uwsgi_malloc(sizeof(struct uwsgi_static_map));
usm = usm->next;
break;
}
}
}
char *docroot = strchr(optarg, '=');
if (!docroot) {
uwsgi_log("invalid document root in static map\n");
exit(1);
}
usm->mountpoint = optarg;
usm->mountpoint_len = docroot-usm->mountpoint;
usm->document_root = docroot+1;
usm->document_root_len = strlen(usm->document_root);
uwsgi_log("static-mapped %.*s to %.*s\n", usm->mountpoint_len, usm->mountpoint, usm->document_root_len, usm->document_root);
usm->next = NULL;
return 1;
case LONG_ARGS_ATTACH_DAEMON:
if (uwsgi.startup_daemons_cnt < MAX_DAEMONS) {
uwsgi.startup_daemons[uwsgi.startup_daemons_cnt] = optarg;
+19
View File
@@ -216,6 +216,17 @@ struct uwsgi_help_item {
char *value;
};
struct uwsgi_static_map {
char *mountpoint;
int mountpoint_len;
char *document_root;
int document_root_len;
struct uwsgi_static_map *next;
};
union uwsgi_sockaddr {
struct sockaddr sa;
@@ -380,6 +391,8 @@ struct uwsgi_opt {
#define LONG_ARGS_PIDFILE2 17088
#define LONG_ARGS_MAP_SOCKET 17089
#define LONG_ARGS_SHARED_SOCKET 17090
#define LONG_ARGS_STATIC_MAP 17091
#define LONG_ARGS_FILE_SERVE_MODE 17092
#define UWSGI_OK 0
@@ -807,6 +820,9 @@ struct uwsgi_server {
int log_syslog;
char *check_static;
size_t check_static_len;
int file_serve_mode;
struct uwsgi_static_map *static_maps;
char *logfile;
int logfile_chown;
@@ -1710,3 +1726,6 @@ int uwsgi_netlink_del(char *);
int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *);
char *uwsgi_amqp_consume(int, uint64_t *, char **);
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
inline int uwsgi_starts_with(char *, int, char *, int);