From 92153ec691e8d9a086bc2ea4e3fb689c14a1a8b6 Mon Sep 17 00:00:00 2001 From: Aldur Date: Fri, 24 Oct 2014 14:13:29 +0200 Subject: [PATCH 1/5] fix mountpoint / scriptname management If the mountpoint is /foo or /foo/ then the following URIs should be managed: * /foo * /foo/ * /foo/anything And, on the other side, should be ignored: * /fooanything * etc. --- core/protocol.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/core/protocol.c b/core/protocol.c index 5e650afb..b1c83e24 100644 --- a/core/protocol.c +++ b/core/protocol.c @@ -736,23 +736,34 @@ next: } for (i = 0; i < uwsgi_apps_cnt; i++) { + char* mountpoint = uwsgi_apps[i].mountpoint; + int mountpoint_len = uwsgi_apps[i].mountpoint_len; + + // Ignore trailing mountpoint slashes + if (mountpoint[mountpoint_len - 1] == '/') { + mountpoint_len -= 1; + } + //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; + if (orig_path_info_len >= mountpoint_len) { + if (!uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) + && mountpoint_len > best_found) { + if (!(orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) { + 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->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; + 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); + 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 +1067,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 +1134,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; } From a89e8d2b5378963def761f41d711dae971625b0c Mon Sep 17 00:00:00 2001 From: Aldur Date: Fri, 24 Oct 2014 14:15:44 +0200 Subject: [PATCH 2/5] add manage_script_name tests --- .../manage_script_name_test.ini | 13 ++++ .../test_manage_script_name.py | 59 +++++++++++++++++++ t/python/manage_script_name/useless_app.py | 3 + 3 files changed, 75 insertions(+) create mode 100644 t/python/manage_script_name/manage_script_name_test.ini create mode 100644 t/python/manage_script_name/test_manage_script_name.py create mode 100644 t/python/manage_script_name/useless_app.py 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'] From f1de54562309645f6215acf28f9814416d6edad1 Mon Sep 17 00:00:00 2001 From: Aldur Date: Fri, 24 Oct 2014 14:53:12 +0200 Subject: [PATCH 3/5] refactor manage_script_name mountpoint selection (readability) --- core/protocol.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/core/protocol.c b/core/protocol.c index b1c83e24..f0e27b5f 100644 --- a/core/protocol.c +++ b/core/protocol.c @@ -744,28 +744,31 @@ next: mountpoint_len -= 1; } - //uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint); - if (orig_path_info_len >= mountpoint_len) { - if (!uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) - && mountpoint_len > best_found) { - if (!(orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) { - 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 - } - } + // 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; } + + //uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint); + 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 } } } From 59da3211ab1a51e4d91ab85038e836b38539a160 Mon Sep 17 00:00:00 2001 From: Aldur Date: Fri, 24 Oct 2014 15:35:51 +0200 Subject: [PATCH 4/5] faboulous positioning of logic operators --- core/protocol.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/protocol.c b/core/protocol.c index f0e27b5f..36b1820e 100644 --- a/core/protocol.c +++ b/core/protocol.c @@ -744,17 +744,18 @@ next: 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 + 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) + uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) || // and should not be "misleading" - || (orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) { + (orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) { continue; } - //uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint); best_found = mountpoint_len; wsgi_req->script_name = uwsgi_apps[i].mountpoint; wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len; From c6d85b9dc2f62ffb018c1ec789687c75f8a28cd0 Mon Sep 17 00:00:00 2001 From: Aldur Date: Fri, 24 Oct 2014 16:36:07 +0200 Subject: [PATCH 5/5] avoid bad memory access if mountpoint_len equal to 0 --- core/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/protocol.c b/core/protocol.c index 36b1820e..1211085e 100644 --- a/core/protocol.c +++ b/core/protocol.c @@ -740,7 +740,7 @@ next: int mountpoint_len = uwsgi_apps[i].mountpoint_len; // Ignore trailing mountpoint slashes - if (mountpoint[mountpoint_len - 1] == '/') { + if (mountpoint_len > 0 && mountpoint[mountpoint_len - 1] == '/') { mountpoint_len -= 1; }