Skip to content

Commit

Permalink
Merge pull request #245 from joe733/workshop
Browse files Browse the repository at this point in the history
maint: improves `url` module
  • Loading branch information
yozachar committed Mar 18, 2023
2 parents bbf4600 + c43826c commit 084d085
Show file tree
Hide file tree
Showing 3 changed files with 356 additions and 280 deletions.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

::: validators.slug

<!-- ::: validators.url -->
::: validators.url

::: validators.uuid

Expand Down
314 changes: 168 additions & 146 deletions tests/test_url.py
Original file line number Diff line number Diff line change
@@ -1,153 +1,175 @@
"""Test URL."""
# -*- coding: utf-8 -*-
import pytest

from validators import url, ValidationFailure


@pytest.mark.parametrize('address', [
u'http://foobar.dk',
u'http://foobar.museum/foobar',
u'http://fo.com',
u'http://FOO.com',
u'http://foo.com/blah_blah',
u'http://foo.com/blah_blah/',
u'http://foo.com/blah_blah_(wikipedia)',
u'http://foo.com/blah_blah_(wikipedia)_(again)',
u'http://www.example.com/wpstyle/?p=364',
u'https://www.example.com/foo/?bar=baz&inga=42&quux',
u'https://www.example.com?bar=baz',
u'http://✪df.ws/123',
u'http://userid:password@example.com:8080',
u'http://userid:password@example.com:8080/',
u'http://userid@example.com',
u'http://userid@example.com/',
u'http://userid@example.com:8080',
u'http://userid@example.com:8080/',
u'http://userid:password@example.com',
u'http://userid:password@example.com/',
u'http://142.42.1.1/',
u'http://142.42.1.1:8080/',
u'http://➡.ws/䨹',
u'http://⌘.ws',
u'http://⌘.ws/',
u'http://foo.com/blah_(wikipedia)#cite-1',
u'http://foo.com/blah_(wikipedia)_blah#cite-1',
u'http://foo.com/unicode_(✪)_in_parens',
u'http://foo.com/(something)?after=parens',
u'http://☺.damowmow.com/',
u'http://code.google.com/events/#&product=browser',
u'http://j.mp',
u'ftp://foo.bar/baz',
u'http://foo.bar/?q=Test%20URL-encoded%20stuff',
u'http://مثال.إختبار',
u'http://例子.测试',
u'http://उदाहरण.परीक्षा',
u'http://www.😉.com',
u'http://😉.com/😁',
u'http://উদাহরণ.বাংলা',
u'http://xn--d5b6ci4b4b3a.xn--54b7fta0cc',
u'http://дом-м.рф/1/asdf',
u'http://xn----gtbybh.xn--p1ai/1/asdf',
u'http://-.~_!$&\'()*+,;=:%40:80%2f::::::@example.com',
u'http://1337.net',
u'http://a.b-c.de',
u'http://223.255.255.254',
u'http://10.1.1.0',
u'http://10.1.1.1',
u'http://10.1.1.254',
u'http://10.1.1.255',
u'http://127.0.0.1:8080',
u'http://127.0.10.150',
u'http://localhost',
u'http://localhost:8000',
u'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',
u'http://[1080:0:0:0:8:800:200C:417A]/index.html',
u'http://[3ffe:2a00:100:7031::1]',
u'http://[1080::8:800:200C:417A]/foo',
u'http://[::192.9.5.5]/ipng',
u'http://[::FFFF:129.144.52.38]:80/index.html',
u'http://[2010:836B:4179::836B:4179]',
])
def test_returns_true_on_valid_url(address):
assert url(address)


@pytest.mark.parametrize('address, public', [
(u'http://foo.bar', True),
(u'http://username:password@example.com:4010/', False),
(u'http://username:password@112.168.10.10:4010/', True),
(u'http://username:password@192.168.10.10:4010/', False),
(u'http://10.0.10.1', False),
(u'http://127.0.0.1', False),
])
def test_returns_true_on_valid_public_url(address, public):
assert url(address, public=public)
# external
import pytest

# local
from validators import ValidationFailure, url

@pytest.mark.parametrize('address', [
'http://foobar',
'foobar.dk',
'http://127.0.0/asdf',
'http://foobar.d',
'http://foobar.12',
'http://foobar',
'htp://foobar.com',
'http://foobar..com',
'http://fo..com',
'http://',
'http://.',
'http://..',
'http://../',
'http://?',
'http://??',
'http://??/',
'http://#',
'http://##',
'http://##/',
'http://foo.bar?q=Spaces should be encoded',
'//',
'//a',
'///a',
'///',
'http:///a',
'foo.com',
'rdar://1234',
'h://test',
'http:// shouldfail.com',
':// should fail',
'http://foo.bar/foo(bar)baz quux',
'ftps://foo.bar/',
'http://-error-.invalid/',
'http://a.b--c.de/',
'http://-a.b.co',
'http://a.b-.co',
'http://0.0.0.0',
'http://224.1.1.1',
'http://1.1.1.1.1',
'http://123.123.123',
'http://3628126748',
'http://.www.foo.bar/',
'http://www.foo.bar./',
'http://.www.foo.bar./',
'http://127.12.0.260',
'http://example.com/">user@example.com',
'http://[2010:836B:4179::836B:4179',
'http://2010:836B:4179::836B:4179',
'http://2010:836B:4179::836B:4179:80/index.html',
])
def test_returns_failed_validation_on_invalid_url(address):
assert isinstance(url(address), ValidationFailure)

@pytest.mark.parametrize(
"value",
[
"http://foobar.dk",
"http://foobar.museum/foobar",
"http://fo.com",
"http://FOO.com",
"http://foo.com/blah_blah",
"http://foo.com/blah_blah/",
"http://foo.com/blah_blah_(wikipedia)",
"http://foo.com/blah_blah_(wikipedia)_(again)",
"http://www.example.com/wpstyle/?p=364",
"https://www.example.com/foo/?bar=baz&inga=42&quux",
"https://www.example.com?bar=baz",
"http://✪df.ws/123",
"http://userid:password@example.com:8080",
"http://userid:password@example.com:8080/",
"http://userid@example.com",
"http://userid@example.com/",
"http://userid@example.com:8080",
"http://userid@example.com:8080/",
"http://userid:password@example.com",
"http://userid:password@example.com/",
"http://142.42.1.1/",
"http://142.42.1.1:8080/",
"http://➡.ws/䨹",
"http://⌘.ws",
"http://⌘.ws/",
"http://foo.com/blah_(wikipedia)#cite-1",
"http://foo.com/blah_(wikipedia)_blah#cite-1",
"http://foo.com/unicode_(✪)_in_parens",
"http://foo.com/(something)?after=parens",
"http://☺.damowmow.com/",
"http://code.google.com/events/#&product=browser",
"http://j.mp",
"ftp://foo.bar/baz",
"http://foo.bar/?q=Test%20URL-encoded%20stuff",
"http://مثال.إختبار",
"http://例子.测试",
"http://उदाहरण.परीक्षा",
"http://www.😉.com",
"http://😉.com/😁",
"http://উদাহরণ.বাংলা",
"http://xn--d5b6ci4b4b3a.xn--54b7fta0cc",
"http://дом-м.рф/1/asdf",
"http://xn----gtbybh.xn--p1ai/1/asdf",
"http://1337.net",
"http://a.b-c.de",
"http://a.b--c.de/",
"http://0.0.0.0",
"http://224.1.1.1",
"http://223.255.255.254",
"http://10.1.1.0",
"http://10.1.1.1",
"http://10.1.1.254",
"http://10.1.1.255",
"http://127.0.0.1:8080",
"http://127.0.10.150",
"http://47.96.118.255:2333/",
"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html",
"http://[1080:0:0:0:8:800:200C:417A]/index.html",
"http://[3ffe:2a00:100:7031::1]",
"http://[1080::8:800:200C:417A]/foo",
"http://[::192.9.5.5]/ipng",
"http://[::FFFF:129.144.52.38]:80/index.html",
"http://[2010:836B:4179::836B:4179]",
"http://foo.bar",
"http://google.com:9/test",
"http://5.196.190.0/",
"http://username:password@example.com:4010/",
"http://username:password@112.168.10.10:4010/",
"http://base-test-site.local",
"http://президент.рф/",
"http://10.24.90.255:83/",
"https://travel-usa.com/wisconsin/旅行/",
# when simple_host=True
# "http://localhost",
# "http://localhost:8000",
# "http://pc:8081/",
# "http://3628126748",
# "http://foobar",
],
)
def test_returns_true_on_valid_url(value: str):
"""Test returns true on valid url."""
assert url(value)

@pytest.mark.parametrize('address, public', [
(u'http://username:password@192.168.10.10:4010/', True),
(u'http://10.0.10.1', True),
(u'http://127.0.0.1', True),
(u'foo://127.0.0.1', True),
(u'http://username:password@127.0.0.1:8080', True),
(u'http://localhost', True),
(u'http://localhost:8000', True),

])
def test_returns_failed_validation_on_invalid_public_url(address, public):
assert isinstance(url(address, public=public), ValidationFailure)
@pytest.mark.parametrize(
"value",
[
"foobar.dk",
"http://127.0.0/asdf",
"http://foobar.d",
"http://foobar.12",
"htp://foobar.com",
"http://foobar..com",
"http://fo..com",
"http://",
"http://.",
"http://..",
"http://../",
"http://?",
"http://??",
"http://??/",
"http://#",
"http://##",
"http://##/",
"http://foo.bar?q=Spaces should be encoded",
"//",
"//a",
"///a",
"///",
"http:///a",
"foo.com",
"rdar://1234",
"h://test",
"http:// shouldfail.com",
":// should fail",
"http://foo.bar/foo(bar)baz quux",
"http://-error-.invalid/",
"http://www.\uFFFD.ch",
"http://-a.b.co",
"http://a.b-.co",
"http://1.1.1.1.1",
"http://123.123.123",
"http://.www.foo.bar/",
"http://www.foo.bar./",
"http://.www.foo.bar./",
"http://127.12.0.260",
'http://example.com/">user@example.com',
"http://[2010:836B:4179::836B:4179",
"http://2010:836B:4179::836B:4179",
"http://2010:836B:4179::836B:4179:80/index.html",
"http://0.00.00.00.00.00.00.00.00.00.00.00.00.00.00."
+ "00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00."
+ "00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00."
+ "00.00.00.00.00.00.00.00.00.00.00.00.00.", # ReDoS
"http://172.20.201.135-10.10.10.1656172.20.11.80-10."
+ "10.10.1746172.16.9.13-192.168.17.68610.10.10.226-192."
+ "168.17.64610.10.10.226-192.168.17.63610.10.10.226-192."
+ "168.17.62610.10.10.226-192.168.17.61610.10.10.226-192."
+ "168.17.60610.10.10.226-192.168.17.59610.10.10.226-192."
+ "168.17.58610.10.10.226-192.168.17.57610.10.10.226-192."
+ "168.17.56610.10.10.226-192.168.17.55610.10.10.226-192."
+ "168.17.54610.10.10.226-192.168.17.53610.10.10.226-192."
+ "168.17.52610.10.10.226-192.168.17.51610.10.10.195-10."
+ "10.10.2610.10.10.194-192.168.17.685172.20.11.52-10.10."
+ "10.195510.10.10.226-192.168.17.50510.10.10.186-172.20."
+ "11.1510.10.10.165-198.41.0.54192.168.84.1-192.168.17."
+ "684192.168.222.1-192.168.17.684172.20.11.52-10.10.10."
+ "174410.10.10.232-172.20.201.198410.10.10.228-172.20.201."
+ "1983192.168.17.135-10.10.10.1423192.168.17.135-10.10.10."
+ "122310.10.10.224-172.20.201.198310.10.10.195-172.20.11."
+ "1310.10.10.160-172.20.201.198310.10.10.142-192.168.17."
+ "1352192.168.22.207-10.10.10.2242192.168.17.66-10.10.10."
+ "1122192.168.17.135-10.10.10.1122192.168.17.129-10.10.10."
+ "1122172.20.201.198-10.10.10.2282172.20.201.198-10.10.10."
+ "2242172.20.201.1-10.10.10.1652172.20.11.2-10.10.10.1412172."
+ "16.8.229-12.162.170.196210.10.10.212-192.168.22.133", # ReDoS
],
)
def test_returns_failed_validation_on_invalid_url(value: str):
"""Test returns failed validation on invalid url."""
assert isinstance(url(value), ValidationFailure)
Loading

0 comments on commit 084d085

Please sign in to comment.