diff --git a/core/protocol.c b/core/protocol.c index 5e650afb..1211085e 100644 --- a/core/protocol.c +++ b/core/protocol.c @@ -736,25 +736,40 @@ next: } for (i = 0; i < uwsgi_apps_cnt; i++) { - //uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint); - if (orig_path_info_len >= uwsgi_apps[i].mountpoint_len) { - if (!uwsgi_startswith(orig_path_info, uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len) && uwsgi_apps[i].mountpoint_len > best_found) { - best_found = uwsgi_apps[i].mountpoint_len; - wsgi_req->script_name = uwsgi_apps[i].mountpoint; - wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len; - wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len; - wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len; + char* mountpoint = uwsgi_apps[i].mountpoint; + int mountpoint_len = uwsgi_apps[i].mountpoint_len; - wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name; - wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len; - - wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info; - wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len; -#ifdef UWSGI_DEBUG - uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info); -#endif - } + // Ignore trailing mountpoint slashes + if (mountpoint_len > 0 && mountpoint[mountpoint_len - 1] == '/') { + mountpoint_len -= 1; } + + //uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint); + + // Check if mountpoint could be a possible candidate + if (orig_path_info_len < mountpoint_len || // it should be shorter than or equal to path_info + mountpoint_len <= best_found || // it should be better than the previous found + // should have the same prefix of path_info + uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) || + // and should not be "misleading" + (orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) { + continue; + } + + best_found = mountpoint_len; + wsgi_req->script_name = uwsgi_apps[i].mountpoint; + wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len; + wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len; + wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len; + + wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name; + wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len; + + wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info; + wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len; +#ifdef UWSGI_DEBUG + uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info); +#endif } } } @@ -1056,7 +1071,7 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen wsgi_req->var_cnt++; ptr += keylen; - + *ptr++ = (uint8_t) (vallen & 0xff); *ptr++ = (uint8_t) ((vallen >> 8) & 0xff); @@ -1123,13 +1138,13 @@ int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *i *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->len += 13 + wsgi_req->path_info_len; wsgi_req->path_info = new_path_info; - + return 0; } diff --git a/t/python/manage_script_name/manage_script_name_test.ini b/t/python/manage_script_name/manage_script_name_test.ini new file mode 100644 index 00000000..f2287768 --- /dev/null +++ b/t/python/manage_script_name/manage_script_name_test.ini @@ -0,0 +1,13 @@ +[uwsgi] +http-socket = :8080 + +master = 1 + +; Three apps on three mountpoints +wsgi-file = %d/useless_app.py + +mount = /foo=%d/useless_app.py +mount = /foobis/=%d/useless_app.py +mount = /footris/=%d/useless_app.py + +manage-script-name = 1 diff --git a/t/python/manage_script_name/test_manage_script_name.py b/t/python/manage_script_name/test_manage_script_name.py new file mode 100644 index 00000000..0908b0fc --- /dev/null +++ b/t/python/manage_script_name/test_manage_script_name.py @@ -0,0 +1,59 @@ +#! /usr/bin/env python3 +# coding = utf-8 +# author = Adriano Di Luzio + +# I require requests! + +""" +First run: + $ ./uwsgi t/python/manage_script_name/manage_script_name_test.ini + +Then run me! +""" + +import unittest +import requests + +HOST = "http://127.0.0.1:8080" + + +class ManageScriptNameTest(unittest.TestCase): + + def test_classic_mountpoints(self): + mps = { + "/foo", + "/foobis/", + "/footris/" + } + + for mp in mps: + # Requests to /foo should kick-in the managed script name. + r = requests.get(HOST + mp) + self.assertEqual(r.text, mp) + + ends = mp.endswith("/") + + # And equally requests to /foo/ + r = requests.get( + HOST + mp + "/") if not ends else requests.get(HOST + mp[:-1]) + self.assertEqual(r.text, mp) + + # Or correct requests (/foo/resource) + r = requests.get( + HOST + mp + "/" + "resource") if not ends else requests.get(HOST + mp + "resource") + self.assertEqual(r.text, mp) + + def test_intriguing_mountpoints(self): + mps = { + "/fooanything", + "/foobisis/", + "/foofighters", + } + + for mp in mps: + r = requests.get(HOST + mp) + self.assertEqual(r.text, "") + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/t/python/manage_script_name/useless_app.py b/t/python/manage_script_name/useless_app.py new file mode 100644 index 00000000..b19c0810 --- /dev/null +++ b/t/python/manage_script_name/useless_app.py @@ -0,0 +1,3 @@ +def application(env, start_response): + start_response('200 OK', [('Content-Type', 'text/html')]) + return env['SCRIPT_NAME']