1
|
|
|
from flask.globals import _app_ctx_stack, _request_ctx_stack |
2
|
|
|
from werkzeug.urls import url_parse |
3
|
|
|
from werkzeug.exceptions import NotFound |
4
|
|
|
from .errors import ValidationError |
5
|
|
|
import re |
6
|
|
|
|
7
|
|
|
|
8
|
|
|
url_regex = re.compile( |
9
|
|
|
r'^(?:http|ftp)s?://|' # http:// or https:// |
10
|
|
|
r'(?:[^:@]+?:[^:@]*?@|)' # basic auth |
11
|
|
|
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+' |
12
|
|
|
r'(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... |
13
|
|
|
r'localhost|' # localhost... |
14
|
|
|
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|' # ...or ipv4 |
15
|
|
|
r'\[?[A-F0-9]*:[A-F0-9:]+\]?)' # ...or ipv6 |
16
|
|
|
r'(?::\d+)?' # optional port |
17
|
|
|
r'(?:/?|[/?]\S+)$', re.IGNORECASE) |
18
|
|
|
|
19
|
|
|
|
20
|
|
|
def match_url(url, method=None): # pragma: no cover |
21
|
|
|
appctx = _app_ctx_stack.top |
22
|
|
|
reqctx = _request_ctx_stack.top |
23
|
|
|
if appctx is None: |
24
|
|
|
raise RuntimeError('Attempted to match a URL without the ' |
25
|
|
|
'application context being pushed. This has to be ' |
26
|
|
|
'executed when application context is available.') |
27
|
|
|
|
28
|
|
|
if reqctx is not None: |
29
|
|
|
url_adapter = reqctx.url_adapter |
30
|
|
|
else: |
31
|
|
|
url_adapter = appctx.url_adapter |
32
|
|
|
if url_adapter is None: |
33
|
|
|
raise RuntimeError('Application was not able to create a URL ' |
34
|
|
|
'adapter for request independent URL matching. ' |
35
|
|
|
'You might be able to fix this by setting ' |
36
|
|
|
'the SERVER_NAME config variable.') |
37
|
|
|
parsed_url = url_parse(url) |
38
|
|
|
if parsed_url.netloc is not '' and parsed_url.netloc != url_adapter.server_name: |
39
|
|
|
raise NotFound() |
40
|
|
|
return url_adapter.match(parsed_url.path, method) |
41
|
|
|
|
42
|
|
|
|
43
|
|
|
def args_from_url(url, endpoint): # pragma: no cover |
44
|
|
|
r = match_url(url, 'GET') |
45
|
|
|
if r[0] != endpoint: |
46
|
|
|
return NotFound() |
47
|
|
|
return r[1] |
48
|
|
|
|
49
|
|
|
|
50
|
|
|
def convert_url(url): |
51
|
|
|
if url_regex.search(url): |
52
|
|
|
if 'http' not in url: |
53
|
|
|
url = 'http://'+url |
54
|
|
|
else: |
55
|
|
|
raise ValidationError('Invalid url: bad type ' + str(url)) |
56
|
|
|
return url |
57
|
|
|
|