diff --git a/core/protocol.c b/core/protocol.c index a50b75c3..b4710b5a 100644 --- a/core/protocol.c +++ b/core/protocol.c @@ -578,7 +578,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) { ptrbuf = buffer; bufferend = ptrbuf + wsgi_req->uh->pktsize; int i; - + /* set an HTTP 500 status as default */ wsgi_req->status = 500; @@ -588,12 +588,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) { // has the protocol already parsed the request ? if (wsgi_req->uri_len > 0) { + wsgi_req->parsed = 1; i = uwsgi_simple_parse_vars(wsgi_req, ptrbuf, bufferend); if (i == 0) goto next; return i; } + wsgi_req->parsed = 1; wsgi_req->script_name_pos = -1; wsgi_req->path_info_pos = -1; @@ -669,14 +671,8 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) { } } - // do not continue, we are still routing - if (wsgi_req->is_routing) return 0; - next: - // we can be here one time for request - wsgi_req->parsed = 1; - // manage post buffering (if needed as post_file could be created before) if (uwsgi.post_buffering > 0 && !wsgi_req->post_file) { // read to disk if post_cl > post_buffering (it will eventually do upload progress...) @@ -1003,3 +999,57 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen return ptr; } + +int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *index, uint16_t index_len) { + uint8_t need_slash = 0; + if (wsgi_req->path_info_len > 0) { + if (wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') { + need_slash = 1; + } + } + + wsgi_req->path_info_len += need_slash + index_len; + + // 2 + 9 + 2 + if ((wsgi_req->uh->pktsize + (13 + wsgi_req->path_info_len)) > uwsgi.buffer_size) { + uwsgi_log("not enough buffer space to transform the PATH_INFO variable, consider increasing it with the --buffer-size option\n"); + return -1; + } + + if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) { + uwsgi_log("max vec size reached for PATH_INFO + index. skip this request.\n"); + return -1; + } + + uint16_t keylen = 9; + char *ptr = wsgi_req->buffer + wsgi_req->uh->pktsize; + *ptr++ = (uint8_t) (keylen & 0xff); + *ptr++ = (uint8_t) ((keylen >> 8) & 0xff); + + memcpy(ptr, "PATH_INFO", keylen); + wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr; + wsgi_req->hvec[wsgi_req->var_cnt].iov_len = keylen; + wsgi_req->var_cnt++; + ptr += keylen; + + *ptr++ = (uint8_t) (wsgi_req->path_info_len & 0xff); + *ptr++ = (uint8_t) ((wsgi_req->path_info_len >> 8) & 0xff); + + char *new_path_info = ptr; + + memcpy(ptr, wsgi_req->path_info, wsgi_req->path_info_len - (need_slash + index_len)); + ptr+=wsgi_req->path_info_len - (need_slash + index_len); + if (need_slash) { + *ptr ++= '/'; + } + memcpy(ptr, index, index_len); + + wsgi_req->hvec[wsgi_req->var_cnt].iov_base = new_path_info; + wsgi_req->hvec[wsgi_req->var_cnt].iov_len = wsgi_req->path_info_len; + wsgi_req->var_cnt++; + + wsgi_req->uh->pktsize += 13 + wsgi_req->path_info_len; + wsgi_req->path_info = new_path_info; + + return 0; +} diff --git a/core/routing.c b/core/routing.c index fd28da6e..8ac52e66 100644 --- a/core/routing.c +++ b/core/routing.c @@ -85,7 +85,7 @@ error: return NULL; } -static int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) { +int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) { struct uwsgi_route *routes = uwsgi.routes; void *goon_func = NULL; @@ -165,12 +165,10 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) { if (wsgi_req->is_routing) return UWSGI_ROUTE_CONTINUE; - wsgi_req->is_routing = 1; if (uwsgi_parse_vars(wsgi_req)) { wsgi_req->is_routing = 0; return UWSGI_ROUTE_BREAK; } - wsgi_req->is_routing = 0; return uwsgi_apply_routes_do(wsgi_req, NULL, 0); } diff --git a/core/static.c b/core/static.c index ec2119ee..12b8c92f 100644 --- a/core/static.c +++ b/core/static.c @@ -393,7 +393,7 @@ ssize_t uwsgi_append_static_path(char *dir, size_t dir_len, char *file, size_t f return len; } -int uwsgi_static_stat(char *filename, size_t *filename_len, struct stat *st) { +static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st, struct uwsgi_string_list **index) { int ret = stat(filename, st); // if non-existant return -1 @@ -412,7 +412,8 @@ int uwsgi_static_stat(char *filename, size_t *filename_len, struct stat *st) { #ifdef UWSGI_DEBUG uwsgi_log("checking for %s\n", filename); #endif - if (!uwsgi_static_stat(filename, filename_len, st)) { + if (uwsgi_is_file2(filename, st)) { + *index = usl; *filename_len = new_len; return 0; } @@ -521,6 +522,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_ char *filename = NULL; size_t filename_len = 0; + struct uwsgi_string_list *index = NULL; if (!is_a_file) { filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len); @@ -580,27 +582,28 @@ found: safe: - if (!uwsgi_static_stat(real_filename, &real_filename_len, &st)) { + if (!uwsgi_static_stat(wsgi_req, real_filename, &real_filename_len, &st, &index)) { + + if (index) { + // if we are here the PATH_INFO need to be changed, so ensure some rule does not apply to it + if (uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) { + return 0; + } + if (uwsgi_req_append_path_info_with_index(wsgi_req, index->value, index->len)) { + return -1; + } + } // skip methods other than GET and HEAD if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) { -#ifdef UWSGI_ROUTING - if (uwsgi_apply_routes_fast(wsgi_req, real_filename, real_filename_len) == UWSGI_ROUTE_BREAK) - return 0; -#endif return -1; } - // check for skippable ext struct uwsgi_string_list *sse = uwsgi.static_skip_ext; while (sse) { if (real_filename_len >= sse->len) { if (!uwsgi_strncmp(real_filename + (real_filename_len - sse->len), sse->len, sse->value, sse->len)) { -#ifdef UWSGI_ROUTING - if (uwsgi_apply_routes_fast(wsgi_req, real_filename, real_filename_len) == UWSGI_ROUTE_BREAK) - return 0; -#endif return -1; } } diff --git a/core/utils.c b/core/utils.c index 8809a8e2..f1263672 100644 --- a/core/utils.c +++ b/core/utils.c @@ -1248,6 +1248,16 @@ int uwsgi_is_file(char *filename) { return 0; } +int uwsgi_is_file2(char *filename, struct stat *st) { + if (stat(filename, st)) { + return 0; + } + if (S_ISREG(st->st_mode)) + return 1; + return 0; +} + + int uwsgi_is_dir(char *filename) { struct stat st; if (stat(filename, &st)) { diff --git a/uwsgi.h b/uwsgi.h index 1cd4265d..55fad046 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -2764,8 +2764,8 @@ void uwsgi_rpc_init(void); char *magic_sub(char *, size_t, size_t *, char *[]); void init_magic_table(char *[]); - char *uwsgi_req_append(struct wsgi_request *, char *, uint16_t, char *, uint16_t); - +char *uwsgi_req_append(struct wsgi_request *, char *, uint16_t, char *, uint16_t); +int uwsgi_req_append_path_info_with_index(struct wsgi_request *, char *, uint16_t); int is_unix(char *, int); int is_a_number(char *); @@ -3309,6 +3309,7 @@ struct uwsgi_router *uwsgi_register_router(char *, int (*)(struct uwsgi_route *, void uwsgi_opt_add_route(char *, char *, void *); int uwsgi_apply_routes(struct wsgi_request *); int uwsgi_apply_routes_fast(struct wsgi_request *, char *, uint16_t); +int uwsgi_apply_routes_do(struct wsgi_request *, char *, uint16_t); void uwsgi_register_embedded_routers(void); void uwsgi_routing_dump(); struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *, struct uwsgi_route *, char *, uint16_t, char *, size_t); @@ -3363,6 +3364,7 @@ void uwsgi_reload(char **); uint64_t uwsgi_micros(void); int uwsgi_is_file(char *); +int uwsgi_is_file2(char *, struct stat *); int uwsgi_is_dir(char *); int uwsgi_is_link(char *);