Skip to content

Commit 084d085

Browse files
authored
Merge pull request #245 from joe733/workshop
maint: improves `url` module
2 parents bbf4600 + c43826c commit 084d085

File tree

3 files changed

+356
-280
lines changed

3 files changed

+356
-280
lines changed

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
::: validators.slug
2626

27-
<!-- ::: validators.url -->
27+
::: validators.url
2828

2929
::: validators.uuid
3030

tests/test_url.py

Lines changed: 168 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,175 @@
1+
"""Test URL."""
12
# -*- coding: utf-8 -*-
2-
import pytest
3-
4-
from validators import url, ValidationFailure
5-
63

7-
@pytest.mark.parametrize('address', [
8-
u'http://foobar.dk',
9-
u'http://foobar.museum/foobar',
10-
u'http://fo.com',
11-
u'http://FOO.com',
12-
u'http://foo.com/blah_blah',
13-
u'http://foo.com/blah_blah/',
14-
u'http://foo.com/blah_blah_(wikipedia)',
15-
u'http://foo.com/blah_blah_(wikipedia)_(again)',
16-
u'http://www.example.com/wpstyle/?p=364',
17-
u'https://www.example.com/foo/?bar=baz&inga=42&quux',
18-
u'https://www.example.com?bar=baz',
19-
u'http://✪df.ws/123',
20-
u'http://userid:password@example.com:8080',
21-
u'http://userid:password@example.com:8080/',
22-
u'http://userid@example.com',
23-
u'http://userid@example.com/',
24-
u'http://userid@example.com:8080',
25-
u'http://userid@example.com:8080/',
26-
u'http://userid:password@example.com',
27-
u'http://userid:password@example.com/',
28-
u'http://142.42.1.1/',
29-
u'http://142.42.1.1:8080/',
30-
u'http://➡.ws/䨹',
31-
u'http://⌘.ws',
32-
u'http://⌘.ws/',
33-
u'http://foo.com/blah_(wikipedia)#cite-1',
34-
u'http://foo.com/blah_(wikipedia)_blah#cite-1',
35-
u'http://foo.com/unicode_(✪)_in_parens',
36-
u'http://foo.com/(something)?after=parens',
37-
u'http://☺.damowmow.com/',
38-
u'http://code.google.com/events/#&product=browser',
39-
u'http://j.mp',
40-
u'ftp://foo.bar/baz',
41-
u'http://foo.bar/?q=Test%20URL-encoded%20stuff',
42-
u'http://مثال.إختبار',
43-
u'http://例子.测试',
44-
u'http://उदाहरण.परीक्षा',
45-
u'http://www.😉.com',
46-
u'http://😉.com/😁',
47-
u'http://উদাহরণ.বাংলা',
48-
u'http://xn--d5b6ci4b4b3a.xn--54b7fta0cc',
49-
u'http://дом-м.рф/1/asdf',
50-
u'http://xn----gtbybh.xn--p1ai/1/asdf',
51-
u'http://-.~_!$&\'()*+,;=:%40:80%2f::::::@example.com',
52-
u'http://1337.net',
53-
u'http://a.b-c.de',
54-
u'http://223.255.255.254',
55-
u'http://10.1.1.0',
56-
u'http://10.1.1.1',
57-
u'http://10.1.1.254',
58-
u'http://10.1.1.255',
59-
u'http://127.0.0.1:8080',
60-
u'http://127.0.10.150',
61-
u'http://localhost',
62-
u'http://localhost:8000',
63-
u'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',
64-
u'http://[1080:0:0:0:8:800:200C:417A]/index.html',
65-
u'http://[3ffe:2a00:100:7031::1]',
66-
u'http://[1080::8:800:200C:417A]/foo',
67-
u'http://[::192.9.5.5]/ipng',
68-
u'http://[::FFFF:129.144.52.38]:80/index.html',
69-
u'http://[2010:836B:4179::836B:4179]',
70-
])
71-
def test_returns_true_on_valid_url(address):
72-
assert url(address)
73-
74-
75-
@pytest.mark.parametrize('address, public', [
76-
(u'http://foo.bar', True),
77-
(u'http://username:password@example.com:4010/', False),
78-
(u'http://username:password@112.168.10.10:4010/', True),
79-
(u'http://username:password@192.168.10.10:4010/', False),
80-
(u'http://10.0.10.1', False),
81-
(u'http://127.0.0.1', False),
82-
])
83-
def test_returns_true_on_valid_public_url(address, public):
84-
assert url(address, public=public)
4+
# external
5+
import pytest
856

7+
# local
8+
from validators import ValidationFailure, url
869

87-
@pytest.mark.parametrize('address', [
88-
'http://foobar',
89-
'foobar.dk',
90-
'http://127.0.0/asdf',
91-
'http://foobar.d',
92-
'http://foobar.12',
93-
'http://foobar',
94-
'htp://foobar.com',
95-
'http://foobar..com',
96-
'http://fo..com',
97-
'http://',
98-
'http://.',
99-
'http://..',
100-
'http://../',
101-
'http://?',
102-
'http://??',
103-
'http://??/',
104-
'http://#',
105-
'http://##',
106-
'http://##/',
107-
'http://foo.bar?q=Spaces should be encoded',
108-
'//',
109-
'//a',
110-
'///a',
111-
'///',
112-
'http:///a',
113-
'foo.com',
114-
'rdar://1234',
115-
'h://test',
116-
'http:// shouldfail.com',
117-
':// should fail',
118-
'http://foo.bar/foo(bar)baz quux',
119-
'ftps://foo.bar/',
120-
'http://-error-.invalid/',
121-
'http://a.b--c.de/',
122-
'http://-a.b.co',
123-
'http://a.b-.co',
124-
'http://0.0.0.0',
125-
'http://224.1.1.1',
126-
'http://1.1.1.1.1',
127-
'http://123.123.123',
128-
'http://3628126748',
129-
'http://.www.foo.bar/',
130-
'http://www.foo.bar./',
131-
'http://.www.foo.bar./',
132-
'http://127.12.0.260',
133-
'http://example.com/">user@example.com',
134-
'http://[2010:836B:4179::836B:4179',
135-
'http://2010:836B:4179::836B:4179',
136-
'http://2010:836B:4179::836B:4179:80/index.html',
137-
])
138-
def test_returns_failed_validation_on_invalid_url(address):
139-
assert isinstance(url(address), ValidationFailure)
14010

11+
@pytest.mark.parametrize(
12+
"value",
13+
[
14+
"http://foobar.dk",
15+
"http://foobar.museum/foobar",
16+
"http://fo.com",
17+
"http://FOO.com",
18+
"http://foo.com/blah_blah",
19+
"http://foo.com/blah_blah/",
20+
"http://foo.com/blah_blah_(wikipedia)",
21+
"http://foo.com/blah_blah_(wikipedia)_(again)",
22+
"http://www.example.com/wpstyle/?p=364",
23+
"https://www.example.com/foo/?bar=baz&inga=42&quux",
24+
"https://www.example.com?bar=baz",
25+
"http://✪df.ws/123",
26+
"http://userid:password@example.com:8080",
27+
"http://userid:password@example.com:8080/",
28+
"http://userid@example.com",
29+
"http://userid@example.com/",
30+
"http://userid@example.com:8080",
31+
"http://userid@example.com:8080/",
32+
"http://userid:password@example.com",
33+
"http://userid:password@example.com/",
34+
"http://142.42.1.1/",
35+
"http://142.42.1.1:8080/",
36+
"http://➡.ws/䨹",
37+
"http://⌘.ws",
38+
"http://⌘.ws/",
39+
"http://foo.com/blah_(wikipedia)#cite-1",
40+
"http://foo.com/blah_(wikipedia)_blah#cite-1",
41+
"http://foo.com/unicode_(✪)_in_parens",
42+
"http://foo.com/(something)?after=parens",
43+
"http://☺.damowmow.com/",
44+
"http://code.google.com/events/#&product=browser",
45+
"http://j.mp",
46+
"ftp://foo.bar/baz",
47+
"http://foo.bar/?q=Test%20URL-encoded%20stuff",
48+
"http://مثال.إختبار",
49+
"http://例子.测试",
50+
"http://उदाहरण.परीक्षा",
51+
"http://www.😉.com",
52+
"http://😉.com/😁",
53+
"http://উদাহরণ.বাংলা",
54+
"http://xn--d5b6ci4b4b3a.xn--54b7fta0cc",
55+
"http://дом-м.рф/1/asdf",
56+
"http://xn----gtbybh.xn--p1ai/1/asdf",
57+
"http://1337.net",
58+
"http://a.b-c.de",
59+
"http://a.b--c.de/",
60+
"http://0.0.0.0",
61+
"http://224.1.1.1",
62+
"http://223.255.255.254",
63+
"http://10.1.1.0",
64+
"http://10.1.1.1",
65+
"http://10.1.1.254",
66+
"http://10.1.1.255",
67+
"http://127.0.0.1:8080",
68+
"http://127.0.10.150",
69+
"http://47.96.118.255:2333/",
70+
"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html",
71+
"http://[1080:0:0:0:8:800:200C:417A]/index.html",
72+
"http://[3ffe:2a00:100:7031::1]",
73+
"http://[1080::8:800:200C:417A]/foo",
74+
"http://[::192.9.5.5]/ipng",
75+
"http://[::FFFF:129.144.52.38]:80/index.html",
76+
"http://[2010:836B:4179::836B:4179]",
77+
"http://foo.bar",
78+
"http://google.com:9/test",
79+
"http://5.196.190.0/",
80+
"http://username:password@example.com:4010/",
81+
"http://username:password@112.168.10.10:4010/",
82+
"http://base-test-site.local",
83+
"http://президент.рф/",
84+
"http://10.24.90.255:83/",
85+
"https://travel-usa.com/wisconsin/旅行/",
86+
# when simple_host=True
87+
# "http://localhost",
88+
# "http://localhost:8000",
89+
# "http://pc:8081/",
90+
# "http://3628126748",
91+
# "http://foobar",
92+
],
93+
)
94+
def test_returns_true_on_valid_url(value: str):
95+
"""Test returns true on valid url."""
96+
assert url(value)
14197

142-
@pytest.mark.parametrize('address, public', [
143-
(u'http://username:password@192.168.10.10:4010/', True),
144-
(u'http://10.0.10.1', True),
145-
(u'http://127.0.0.1', True),
146-
(u'foo://127.0.0.1', True),
147-
(u'http://username:password@127.0.0.1:8080', True),
148-
(u'http://localhost', True),
149-
(u'http://localhost:8000', True),
15098

151-
])
152-
def test_returns_failed_validation_on_invalid_public_url(address, public):
153-
assert isinstance(url(address, public=public), ValidationFailure)
99+
@pytest.mark.parametrize(
100+
"value",
101+
[
102+
"foobar.dk",
103+
"http://127.0.0/asdf",
104+
"http://foobar.d",
105+
"http://foobar.12",
106+
"htp://foobar.com",
107+
"http://foobar..com",
108+
"http://fo..com",
109+
"http://",
110+
"http://.",
111+
"http://..",
112+
"http://../",
113+
"http://?",
114+
"http://??",
115+
"http://??/",
116+
"http://#",
117+
"http://##",
118+
"http://##/",
119+
"http://foo.bar?q=Spaces should be encoded",
120+
"//",
121+
"//a",
122+
"///a",
123+
"///",
124+
"http:///a",
125+
"foo.com",
126+
"rdar://1234",
127+
"h://test",
128+
"http:// shouldfail.com",
129+
":// should fail",
130+
"http://foo.bar/foo(bar)baz quux",
131+
"http://-error-.invalid/",
132+
"http://www.\uFFFD.ch",
133+
"http://-a.b.co",
134+
"http://a.b-.co",
135+
"http://1.1.1.1.1",
136+
"http://123.123.123",
137+
"http://.www.foo.bar/",
138+
"http://www.foo.bar./",
139+
"http://.www.foo.bar./",
140+
"http://127.12.0.260",
141+
'http://example.com/">user@example.com',
142+
"http://[2010:836B:4179::836B:4179",
143+
"http://2010:836B:4179::836B:4179",
144+
"http://2010:836B:4179::836B:4179:80/index.html",
145+
"http://0.00.00.00.00.00.00.00.00.00.00.00.00.00.00."
146+
+ "00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00."
147+
+ "00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00."
148+
+ "00.00.00.00.00.00.00.00.00.00.00.00.00.", # ReDoS
149+
"http://172.20.201.135-10.10.10.1656172.20.11.80-10."
150+
+ "10.10.1746172.16.9.13-192.168.17.68610.10.10.226-192."
151+
+ "168.17.64610.10.10.226-192.168.17.63610.10.10.226-192."
152+
+ "168.17.62610.10.10.226-192.168.17.61610.10.10.226-192."
153+
+ "168.17.60610.10.10.226-192.168.17.59610.10.10.226-192."
154+
+ "168.17.58610.10.10.226-192.168.17.57610.10.10.226-192."
155+
+ "168.17.56610.10.10.226-192.168.17.55610.10.10.226-192."
156+
+ "168.17.54610.10.10.226-192.168.17.53610.10.10.226-192."
157+
+ "168.17.52610.10.10.226-192.168.17.51610.10.10.195-10."
158+
+ "10.10.2610.10.10.194-192.168.17.685172.20.11.52-10.10."
159+
+ "10.195510.10.10.226-192.168.17.50510.10.10.186-172.20."
160+
+ "11.1510.10.10.165-198.41.0.54192.168.84.1-192.168.17."
161+
+ "684192.168.222.1-192.168.17.684172.20.11.52-10.10.10."
162+
+ "174410.10.10.232-172.20.201.198410.10.10.228-172.20.201."
163+
+ "1983192.168.17.135-10.10.10.1423192.168.17.135-10.10.10."
164+
+ "122310.10.10.224-172.20.201.198310.10.10.195-172.20.11."
165+
+ "1310.10.10.160-172.20.201.198310.10.10.142-192.168.17."
166+
+ "1352192.168.22.207-10.10.10.2242192.168.17.66-10.10.10."
167+
+ "1122192.168.17.135-10.10.10.1122192.168.17.129-10.10.10."
168+
+ "1122172.20.201.198-10.10.10.2282172.20.201.198-10.10.10."
169+
+ "2242172.20.201.1-10.10.10.1652172.20.11.2-10.10.10.1412172."
170+
+ "16.8.229-12.162.170.196210.10.10.212-192.168.22.133", # ReDoS
171+
],
172+
)
173+
def test_returns_failed_validation_on_invalid_url(value: str):
174+
"""Test returns failed validation on invalid url."""
175+
assert isinstance(url(value), ValidationFailure)

0 commit comments

Comments
 (0)