Skip to content

Commit 65f1ae9

Browse files
authored
Merge pull request #30 from rakit/enhance-url-validation
Enhance URL validation by also checking it's scheme
2 parents 8a56e73 + ea58b03 commit 65f1ae9

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,25 @@ Value size calculated in same way like `min` and `max` rule.
444444
#### url
445445

446446
The field under this rule must be valid url format.
447+
By default it check common URL scheme format like `any_scheme://...`.
448+
But you can specify URL schemes if you want.
449+
450+
For example:
451+
452+
```php
453+
$validation = $validator->validate($inputs, [
454+
'random_url' => 'url', // value can be `any_scheme://...`
455+
'https_url' => 'url:http', // value must be started with `https://`
456+
'http_url' => 'url:http,https', // value must be started with `http://` or `https://`
457+
'ftp_url' => 'url:ftp', // value must be started with `ftp://`
458+
'custom_url' => 'url:custom', // value must be started with `custom://`
459+
'mailto_url' => 'url:mailto', // value must conatin valid mailto URL scheme like `mailto:[email protected],[email protected]`
460+
'jdbc_url' => 'url:jdbc', // value must contain valid jdbc URL scheme like `jdbc:mysql://localhost/dbname`
461+
]);
462+
```
463+
464+
> For commmon URL scheme and mailto, we combine `FILTER_VALIDATE_URL` to validate URL format and `preg_match` to validate it's scheme.
465+
Except for JDBC URL, currently it just check a valid JDBC scheme.
447466

448467
<a id="rule-ip"></a>
449468
#### ip

src/Rules/Url.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,64 @@ class Url extends Rule
99

1010
protected $message = "The :attribute is not valid url";
1111

12+
public function fillParameters(array $params)
13+
{
14+
if (count($params) == 1 AND is_array($params[0])) {
15+
$params = $params[0];
16+
}
17+
return $this->forScheme($params);
18+
}
19+
20+
public function forScheme($schemes)
21+
{
22+
$this->params['schemes'] = (array) $schemes;
23+
return $this;
24+
}
25+
1226
public function check($value)
27+
{
28+
$schemes = $this->parameter('schemes');
29+
30+
if (!$schemes) {
31+
return $this->validateCommonScheme($value);
32+
} else {
33+
foreach ($schemes as $scheme) {
34+
$method = 'validate' . ucfirst($scheme) .'Scheme';
35+
if (method_exists($this, $method)) {
36+
if ($this->{$method}($value)) {
37+
return true;
38+
}
39+
} elseif($this->validateCommonScheme($value, $scheme)) {
40+
return true;
41+
}
42+
}
43+
44+
return false;
45+
}
46+
}
47+
48+
public function validateBasic($value)
1349
{
1450
return filter_var($value, FILTER_VALIDATE_URL) !== false;
1551
}
1652

53+
public function validateCommonScheme($value, $scheme = null)
54+
{
55+
if (!$scheme) {
56+
return $this->validateBasic($value) && (bool) preg_match("/^\w+:\/\//i", $value);
57+
} else {
58+
return $this->validateBasic($value) && (bool) preg_match("/^{$scheme}:\/\//", $value);
59+
}
60+
}
61+
62+
public function validateMailtoScheme($value)
63+
{
64+
return $this->validateBasic($value) && preg_match("/^mailto:/", $value);
65+
}
66+
67+
public function validateJdbcScheme($value)
68+
{
69+
return (bool) preg_match("/^jdbc:\w+:\/\//", $value);
70+
}
71+
1772
}

tests/Rules/UrlTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,40 @@ public function setUp()
1212

1313
public function testValids()
1414
{
15+
// Without specific schemes
1516
$this->assertTrue($this->rule->check('ftp://foobar.com'));
17+
$this->assertTrue($this->rule->check('any://foobar.com'));
1618
$this->assertTrue($this->rule->check('http://foobar.com'));
1719
$this->assertTrue($this->rule->check('https://foobar.com'));
1820
$this->assertTrue($this->rule->check('https://foobar.com/path?a=123&b=blah'));
21+
22+
// Using specific schemes
23+
$this->assertTrue($this->rule->fillParameters(['ftp'])->check('ftp://foobar.com'));
24+
$this->assertTrue($this->rule->fillParameters(['any'])->check('any://foobar.com'));
25+
$this->assertTrue($this->rule->fillParameters(['http'])->check('http://foobar.com'));
26+
$this->assertTrue($this->rule->fillParameters(['https'])->check('https://foobar.com'));
27+
$this->assertTrue($this->rule->fillParameters(['http', 'https'])->check('https://foobar.com'));
28+
$this->assertTrue($this->rule->fillParameters(['foo', 'bar'])->check('bar://foobar.com'));
29+
$this->assertTrue($this->rule->fillParameters(['mailto'])->check('mailto:[email protected]'));
30+
$this->assertTrue($this->rule->fillParameters(['jdbc'])->check('jdbc:mysql://localhost/dbname'));
31+
32+
// Using forScheme
33+
$this->assertTrue($this->rule->forScheme('ftp')->check('ftp://foobar.com'));
34+
$this->assertTrue($this->rule->forScheme('http')->check('http://foobar.com'));
35+
$this->assertTrue($this->rule->forScheme('https')->check('https://foobar.com'));
36+
$this->assertTrue($this->rule->forScheme(['http', 'https'])->check('https://foobar.com'));
37+
$this->assertTrue($this->rule->forScheme('mailto')->check('mailto:[email protected]'));
38+
$this->assertTrue($this->rule->forScheme('jdbc')->check('jdbc:mysql://localhost/dbname'));
1939
}
2040

2141
public function testInvalids()
2242
{
2343
$this->assertFalse($this->rule->check('foo:'));
44+
$this->assertFalse($this->rule->check('mailto:[email protected]'));
45+
$this->assertFalse($this->rule->forScheme('mailto')->check('http://www.foobar.com'));
46+
$this->assertFalse($this->rule->forScheme('ftp')->check('http://www.foobar.com'));
47+
$this->assertFalse($this->rule->forScheme('jdbc')->check('http://www.foobar.com'));
48+
$this->assertFalse($this->rule->forScheme(['http', 'https'])->check('any://www.foobar.com'));
2449
}
2550

2651
}

0 commit comments

Comments
 (0)