source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/tests/test_routes.py

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 18.6 KB
Line 
1# -*- coding: utf-8 -*-
2
3"""Unit tests for rewrite.py regex routing option"""
4
5import os
6import tempfile
7import unittest
8import shutil
9
10from gluon.rewrite import load, filter_url, filter_err, regex_filter_out
11from gluon.html import URL
12from gluon.settings import global_settings
13from gluon.http import HTTP
14from gluon.storage import Storage
15from gluon._compat import to_bytes
16
17
18old_root = root = None
19
20def setUpModule():
21    def make_apptree(root):
22        "build a temporary applications tree"
23        # applications/
24        os.mkdir(os.path.join(root, 'applications'))
25        # applications/app/
26        for app in ('admin', 'examples', 'welcome'):
27            os.mkdir(os.path.join(root, 'applications', app))
28            #  applications/app/(controllers, static)
29            for subdir in ('controllers', 'static'):
30                os.mkdir(os.path.join(root, 'applications', app, subdir))
31        # applications/admin/controllers/*.py
32        base = os.path.join(root, 'applications', 'admin', 'controllers')
33        for ctr in ('appadmin', 'default', 'gae', 'mercurial', 'shell', 'wizard'):
34            open(os.path.join(base, '%s.py' % ctr), 'w').close()
35        # applications/examples/controllers/*.py
36        base = os.path.join(root, 'applications', 'examples', 'controllers')
37        for ctr in ('ajax_examples', 'appadmin', 'default', 'global', 'spreadsheet'):
38            open(os.path.join(base, '%s.py' % ctr), 'w').close()
39        # applications/welcome/controllers/*.py
40        base = os.path.join(root, 'applications', 'welcome', 'controllers')
41        for ctr in ('appadmin', 'default'):
42            open(os.path.join(base, '%s.py' % ctr), 'w').close()
43        # create an app-specific routes.py for examples app
44        routes = os.path.join(root, 'applications', 'examples', 'routes.py')
45        with open(routes, 'w') as r:
46            r.write("default_function='exdef'\n")
47
48    global old_root, root
49    if old_root is None:  # do this only once
50        old_root = global_settings.applications_parent
51        root = global_settings.applications_parent = tempfile.mkdtemp()
52        make_apptree(root)
53
54
55def tearDownModule():
56    if old_root is not None:
57        global_settings.applications_parent = old_root
58        shutil.rmtree(root)
59
60
61def norm_root(root):
62    return root.replace('/', os.sep)
63
64
65class TestRoutes(unittest.TestCase):
66    """ Tests the regex routing logic from gluon.rewrite """
67
68    def test_routes_null(self):
69        """ Tests a null routes table """
70        load(data='')
71        # incoming
72        self.assertEqual(
73            filter_url('http://domain.com'), '/init/default/index')
74        self.assertEqual(
75            filter_url('http://domain.com/'), '/init/default/index')
76        self.assertEqual(
77            filter_url('http://domain.com/abc'), '/abc/default/index')
78        self.assertEqual(
79            filter_url('http://domain.com/abc/'), '/abc/default/index')
80        self.assertEqual(
81            filter_url('http://domain.com/abc/def'), "/abc/def/index")
82        self.assertEqual(
83            filter_url('http://domain.com/abc/def/'), "/abc/def/index")
84        self.assertEqual(
85            filter_url('http://domain.com/abc/def/ghi'), "/abc/def/ghi")
86        self.assertEqual(
87            filter_url('http://domain.com/abc/def/ghi/'), "/abc/def/ghi")
88        self.assertEqual(filter_url(
89            'http://domain.com/abc/def/ghi/jkl'), "/abc/def/ghi ['jkl']")
90        self.assertEqual(filter_url(
91            'http://domain.com/abc/def/ghi/j%20kl'), "/abc/def/ghi ['j_kl']")
92        self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static'),
93            norm_root("%s/applications/welcome/static/path/to/static" % root))
94        # no more necessary since explcit check for directory traversal attacks
95        """
96        self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/to/st~tic')
97        try:
98            # 2.7+ only
99            self.assertRaisesRegexp(HTTP, "400.*BAD REQUEST \[invalid path\]", filter_url, 'http://domain.com/welcome/static/bad/path/to/st~tic')
100        except AttributeError:
101            pass
102        """
103        # outgoing
104        self.assertEqual(filter_url('http://domain.com/init/default/index',
105                         out=True), '/init/default/index')
106        self.assertEqual(filter_url('http://domain.com/init/default/index/arg1', out=True), '/init/default/index/arg1')
107        self.assertEqual(filter_url('http://domain.com/init/default/abc',
108                         out=True), '/init/default/abc')
109
110    def test_routes_query(self):
111        """ Test query appending """
112        data = r'''
113routes_in = (
114 ('/service/$model/create', '/app/default/call/json/create?model=$model'),
115)
116'''
117        load(data=data)
118        self.assertEqual(filter_url('http://localhost:8000/service/person/create'), "/app/default/call ['json', 'create'] ?model=person")
119        self.assertEqual(filter_url('http://localhost:8000/service/person/create?var1=val1'), "/app/default/call ['json', 'create'] ?model=person&var1=val1")
120
121    def test_routes_specific(self):
122        """
123        Test app-specific routes.py
124
125        Note that make_apptree above created applications/examples/routes.py with a default_function.
126        """
127        data = r'''
128routes_app = [
129    (r'/(?P<app>welcome|admin|examples)\b.*', r'\g<app>'),
130    (r'$anything', r'welcome'),
131    (r'/?$anything', r'welcome'),
132]
133'''
134        load(data=data)
135        self.assertEqual(
136            filter_url('http://domain.com/welcome'), '/welcome/default/index')
137        self.assertEqual(filter_url(
138            'http://domain.com/examples'), '/examples/default/exdef')
139
140    def test_routes_defapp(self):
141        """ Test the default-application function """
142        data = r'''
143default_application = 'defapp'
144'''
145        load(data=data)
146        # incoming
147        self.assertEqual(
148            filter_url('http://domain.com'), '/defapp/default/index')
149        self.assertEqual(
150            filter_url('http://domain.com/'), '/defapp/default/index')
151        self.assertEqual(
152            filter_url('http://domain.com/welcome'), '/welcome/default/index')
153        self.assertEqual(
154            filter_url('http://domain.com/app'), '/app/default/index')
155        self.assertEqual(filter_url('http://domain.com/welcome/default/index/abc'), "/welcome/default/index ['abc']")
156        self.assertEqual(filter_url('http://domain.com/welcome/static/abc'),
157                         norm_root('%s/applications/welcome/static/abc' % root))
158        self.assertEqual(filter_url('http://domain.com/defapp/static/path/to/static'),
159            norm_root("%s/applications/defapp/static/path/to/static" % root))
160
161    def test_routes_raise(self):
162        '''
163        Test URLs that raise exceptions
164        '''
165        # test non-exception variants
166        load(data='')
167        self.assertEqual(
168            filter_url('http://domain.com/init'), "/init/default/index")
169        self.assertEqual(filter_url(
170            'http://domain.com/init/default'), "/init/default/index")
171        self.assertEqual(filter_url('http://domain.com/init/default/fcn.ext'),
172                         "/init/default/fcn.ext")
173        self.assertEqual(filter_url('http://domain.com/init/default/fcn/arg'),
174                         "/init/default/fcn ['arg']")
175        # now raise-HTTP variants
176        self.assertRaises(HTTP, filter_url, 'http://domain.com/bad!ctl')
177        self.assertRaises(HTTP, filter_url, 'http://domain.com/ctl/bad!fcn')
178        self.assertRaises(
179            HTTP, filter_url, 'http://domain.com/ctl/fcn.bad!ext')
180        #self.assertRaises(
181        #    HTTP, filter_url, 'http://domain.com/ctl/fcn/bad!arg')
182        #try:
183        #    # 2.7+ only
184        #    self.assertRaisesRegexp(HTTP, '400 BAD REQUEST \[invalid path\]', filter_url, 'http://domain.com/init/bad!ctl')
185        #    self.assertRaisesRegexp(HTTP, '400 BAD REQUEST \[invalid path\]', filter_url, 'http://domain.com/init/ctlr/bad!fcn')
186        #    self.assertRaisesRegexp(HTTP, '400 BAD REQUEST \[invalid path\]', filter_url, 'http://domain.com/init/ctlr/fcn.bad!ext')
187        #    self.assertRaisesRegexp(HTTP, '400 BAD REQUEST \[invalid path\]', filter_url, 'http://domain.com/appc/init/fcn/bad!arg')
188        #except AttributeError:
189        #    pass
190
191        self.assertEqual(filter_url('http://domain.com/welcome/default/fcn_1'),
192                         "/welcome/default/fcn_1")
193        #self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/default/fcn-1')
194        #try:
195        #    # 2.7+ only
196        #    self.assertRaisesRegexp(HTTP, '400 BAD REQUEST \[invalid path\]', filter_url, 'http://domain.com/welcome/default/fcn-1')
197        #except AttributeError:
198        #    pass
199
200    def test_routes_error(self):
201        '''
202        Test rewrite of HTTP errors
203        '''
204        router_err = dict()
205        load(rdict=router_err)
206        self.assertEqual(filter_err(200), 200)
207        self.assertEqual(filter_err(399), 399)
208        self.assertEqual(filter_err(400), 400)
209
210    def test_routes_args(self):
211        '''
212        Test URL args parsing/generation
213        '''
214        data = r'''routes_in = [
215    ('/robots.txt', '/welcome/static/robots.txt'),
216    ('/favicon.ico', '/welcome/static/favicon.ico'),
217    ('/admin$anything', '/admin$anything'),
218    ('.*:https?://(.*\\.)?domain1.com:$method /', '/app1/default'),
219    ('.*:https?://(.*\\.)?domain1.com:$method /static/$anything',
220     '/app1/static/$anything'),
221    ('.*:https?://(.*\\.)?domain1.com:$method /appadmin/$anything',
222     '/app1/appadmin/$anything'),
223    ('.*:https?://(.*\\.)?domain1.com:$method /$anything',
224     '/app1/default/$anything'),
225    ('.*:https?://(.*\\.)?domain2.com:$method /', '/app2/default'),
226    ('.*:https?://(.*\\.)?domain2.com:$method /static/$anything',
227     '/app2/static/$anything'),
228    ('.*:https?://(.*\\.)?domain2.com:$method /appadmin/$anything',
229     '/app2/appadmin/$anything'),
230    ('.*:https?://(.*\\.)?domain2.com:$method /$anything',
231     '/app2/default/$anything'),
232    ('.*:https?://(.*\\.)?domain3.com:$method /', '/app3/defcon3'),
233    ('.*:https?://(.*\\.)?domain3.com:$method /static/$anything',
234     '/app3/static/$anything'),
235    ('.*:https?://(.*\\.)?domain3.com:$method /appadmin/$anything',
236     '/app3/appadmin/$anything'),
237    ('.*:https?://(.*\\.)?domain3.com:$method /$anything',
238     '/app3/defcon3/$anything'),
239    ('/', '/welcome/default'),
240    ('/welcome/default/$anything', '/welcome/default/$anything'),
241    ('/welcome/$anything', '/welcome/default/$anything'),
242    ('/static/$anything', '/welcome/static/$anything'),
243    ('/appadmin/$anything', '/welcome/appadmin/$anything'),
244    ('/$anything', '/welcome/default/$anything'),
245    ]
246routes_out = [
247    ('/welcome/static/$anything', '/static/$anything'),
248    ('/welcome/appadmin/$anything', '/appadmin/$anything'),
249    ('/welcome/default/$anything', '/$anything'),
250    ('/app1/static/$anything', '/static/$anything'),
251    ('/app1/appadmin/$anything', '/appadmin/$anything'),
252    ('/app1/default/$anything', '/$anything'),
253    ('/app2/static/$anything', '/static/$anything'),
254    ('/app2/appadmin/$anything', '/appadmin/$anything'),
255    ('/app2/default/$anything', '/$anything'),
256    ('/app3/static/$anything', '/static/$anything'),
257    ('/app3/appadmin/$anything', '/appadmin/$anything'),
258    ('/app3/defcon3/$anything', '/$anything')
259    ]
260'''
261        load(data=data)
262        self.assertEqual(
263            filter_url('http://domain.com/welcome/default/f/arg1'),
264            "/welcome/default/f ['arg1']")
265        self.assertEqual(
266            filter_url('http://domain.com/welcome/default/f/arg1/'),
267            "/welcome/default/f ['arg1']")
268        self.assertEqual(
269            filter_url('http://domain.com/welcome/default/f/arg1//'),
270            "/welcome/default/f ['arg1', '']")
271        self.assertEqual(
272            filter_url('http://domain.com/welcome/default/f//arg1'),
273            "/welcome/default/f ['', 'arg1']")
274        self.assertEqual(
275            filter_url('http://domain.com/welcome/default/f/arg1/arg2'),
276            "/welcome/default/f ['arg1', 'arg2']")
277        self.assertEqual(
278            filter_url('http://domain.com/welcome/default/f/arg1//arg2'),
279            "/welcome/default/f ['arg1', '', 'arg2']")
280        self.assertEqual(
281            filter_url('http://domain.com/welcome/default/f/arg1//arg3/'),
282            "/welcome/default/f ['arg1', '', 'arg3']")
283        self.assertEqual(
284            filter_url('http://domain.com/welcome/default/f/arg1//arg3//'),
285            "/welcome/default/f ['arg1', '', 'arg3', '']")
286
287        self.assertEqual(
288            filter_url('http://domain.com/welcome/default/f', out=True), "/f")
289        self.assertEqual(regex_filter_out('/welcome/default/f'), "/f")
290        self.assertEqual(
291            str(URL(a='welcome', c='default', f='f', args=None)), "/f")
292        self.assertEqual(str(
293            URL(a='welcome', c='default', f='f', args=['arg1'])), "/f/arg1")
294        self.assertEqual(str(URL(
295            a='welcome', c='default', f='f', args=['arg1', ''])), "/f/arg1//")
296        self.assertEqual(str(URL(a='welcome', c='default', f='f',
297                         args=['arg1', '', 'arg3'])), "/f/arg1//arg3")
298        self.assertEqual(str(
299            URL(a='welcome', c='default', f='f', args=['ar g'])), "/f/ar%20g")
300        self.assertEqual(str(URL(
301            a='welcome', c='default', f='f', args=['årg'])), "/f/%C3%A5rg")
302        self.assertEqual(
303            URL(a='welcome', c='default', f='fünc'), "/fünc")
304        self.assertEqual(
305            to_bytes(URL(a='welcome', c='default', f='fünc')), b"/f\xc3\xbcnc")
306
307    def test_routes_anchor(self):
308        '''
309        Test URL with anchor
310        '''
311        self.assertEqual(
312            str(URL(a='a', c='c', f='f', anchor='anchor')), "/a/c/f#anchor")
313        load(data='')
314        self.assertEqual(
315            str(URL(a='a', c='c', f='f', anchor='anchor')), "/a/c/f#anchor")
316        args = ['a1', 'a2']
317        self.assertEqual(
318            str(URL(a='a', c='c', f='f', args=args, anchor='anchor')),
319            "/a/c/f/a1/a2#anchor")
320        vars = dict(v1=1, v2=2)
321        self.assertEqual(
322            str(URL(a='a', c='c', f='f', vars=vars, anchor='anchor')),
323            "/a/c/f?v1=1&v2=2#anchor")
324        self.assertEqual(
325            str(URL(
326                a='a', c='c', f='f', args=args, vars=vars, anchor='anchor')),
327            "/a/c/f/a1/a2?v1=1&v2=2#anchor")
328
329        data = r'''routes_out = [
330            ('/init/default/index', '/'),
331        ]'''
332        load(data=data)
333        self.assertEqual(str(URL(a='init', c='default', f='index')),
334                         "/")
335        self.assertEqual(
336            str(URL(a='init', c='default', f='index', anchor='anchor')),
337            "/init/default/index#anchor")
338
339        data = r'''routes_out = [
340            (r'/init/default/index(?P<anchor>(#.*)?)', r'/\g<anchor>'),
341        ]'''
342        load(data=data)
343        self.assertEqual(str(URL(a='init', c='default', f='index')),
344                         "/")
345        self.assertEqual(
346            str(URL(a='init', c='default', f='index', anchor='anchor')),
347            "/#anchor")
348
349        data = r'''routes_out = [
350            (r'/init/default/index(?P<qa>([?#].*)?)', r'/\g<qa>'),
351        ]'''
352        load(data=data)
353        self.assertEqual(str(URL(a='init', c='default', f='index')),
354                         "/")
355        self.assertEqual(
356            str(URL(a='init', c='default', f='index', anchor='anchor')),
357            "/#anchor")
358        query = dict(var='abc')
359        self.assertEqual(
360            str(URL(a='init', c='default', f='index', vars=query)),
361            "/?var=abc")
362        self.assertEqual(
363            str(URL(a='init', c='default', f='index',
364                vars=query, anchor='anchor')),
365            "/?var=abc#anchor")
366
367    def test_routes_absolute(self):
368        '''
369        Test absolute URL
370        '''
371        load(data='')
372        r = Storage()
373        r.env = Storage()
374        r.env.http_host = 'domain.com'
375        r.env.wsgi_url_scheme = 'httpx'  # distinguish incoming scheme
376        self.assertEqual(str(URL(r=r, a='a', c='c', f='f')), "/a/c/f")
377        self.assertEqual(str(URL(r=r, a='a', c='c', f='f', host=True)),
378                         "httpx://domain.com/a/c/f")
379        self.assertEqual(str(URL(r=r, a='a', c='c', f='f', host='host.com')),
380                         "httpx://host.com/a/c/f")
381        self.assertEqual(str(URL(r=r, a='a', c='c', f='f', scheme=True)),
382                         "httpx://domain.com/a/c/f")
383        self.assertEqual(str(URL(r=r, a='a', c='c', f='f', scheme=False)),
384                         "/a/c/f")
385        self.assertEqual(str(URL(r=r, a='a', c='c', f='f', scheme='https')),
386                         "https://domain.com/a/c/f")
387        self.assertEqual(str(URL(r=r, a='a', c='c', f='f', scheme='wss')),
388                         "wss://domain.com/a/c/f")
389        self.assertEqual(
390            str(URL(r=r, a='a', c='c', f='f', scheme=True, host=True)),
391            "httpx://domain.com/a/c/f")
392        self.assertEqual(
393            str(URL(r=r, a='a', c='c', f='f', scheme='https', host=True)),
394            "https://domain.com/a/c/f")
395        self.assertEqual(
396            str(URL(r=r, a='a', c='c', f='f', scheme=False, host=True)),
397            "httpx://domain.com/a/c/f")
398        self.assertEqual(
399            str(URL(r=r, a='a', c='c', f='f', scheme=True, host='host.com')),
400            "httpx://host.com/a/c/f")
401        self.assertEqual(
402            str(URL(r=r, a='a', c='c', f='f', scheme=False, host='host.com')),
403            "httpx://host.com/a/c/f")
404        self.assertEqual(str(URL(r=r, a='a', c='c', f='f', port=1234)),
405                         "httpx://domain.com:1234/a/c/f")
406        self.assertEqual(
407            str(URL(r=r, a='a', c='c', f='f', scheme=True, port=1234)),
408            "httpx://domain.com:1234/a/c/f")
409        self.assertEqual(
410            str(URL(r=r, a='a', c='c', f='f', host='host.com', port=1234)),
411            "httpx://host.com:1234/a/c/f")
412        self.assertEqual(
413            str(URL(r=r, a='a', c='c', f='f', scheme='wss',
414                host='host.com', port=1234)),
415            "wss://host.com:1234/a/c/f")
416
417    def test_request_uri(self):
418        '''
419        Test REQUEST_URI in env
420        '''
421        data = r'''routes_in = [
422    ('/abc', '/init/default/abc'),
423    ('/index/$anything', '/init/default/index/$anything'),
424    ]
425'''
426        load(data=data)
427        self.assertEqual(
428            filter_url('http://domain.com/abc', env=True).request_uri,
429            '/init/default/abc')
430        self.assertEqual(
431            filter_url('http://domain.com/abc?def', env=True).request_uri,
432            '/init/default/abc?def')
433        self.assertEqual(
434            filter_url('http://domain.com/index/abc', env=True).request_uri,
435            "/init/default/index/abc")
436        self.assertEqual(
437            filter_url('http://domain.com/index/a%20bc', env=True).request_uri,
438            "/init/default/index/a bc")
Note: See TracBrowser for help on using the repository browser.