mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-01 11:15:57 +00:00
--static-map mountpoint=documentroot option
This commit is contained in:
+90
-30
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user