Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to specify the allowed URL schemes #288

Merged
merged 11 commits into from
Jul 2, 2024
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
- [Custom Database Connection](#custom-database-connection)
- [Specifying the Key Generator](#specifying-the-key-generator)
- [Specifying the User Agent Parser](#specifying-the-user-agent-parser)
- [Specifying the Allowed URL Schemes](#specifying-the-allowed-url-schemes)
- [Helper Methods](#helper-methods)
- [Visits](#visits)
- [Find by URL Key](#find-by-url-key)
Expand Down Expand Up @@ -632,6 +633,23 @@ To do this, you can define the class to be used in the `short-url.php` config fi

You'll just need to ensure that your custom user agent parser class implements the `AshAllenDesign\ShortURL\Interfaces\UserAgentDriver` interface.

#### Specifying the Allowed URL Schemes

By default, Short URL will allow you to create a shortened URL for any URLs beginning with `http://` or `https://`.

However, you may want to change this list of allowed URL schemes. For example, this may be to restrict the creation to only `https://` URLs. Or, it may be to allow URLs to be created using other schemes such as `mailto://` or even custom schemes for your own applications.

To change the list of allowed URL schemes, you can define the list using the `allowed_url_schemes` field in your `short-url.php` config file like so:

```php
'allowed_url_schemes' => [
'http://',
'https://',
'mailto://',
'myapp://',
],
```

### Helper Methods
#### Visits
The ShortURL model includes a relationship (that you can use just like any other Laravel model relation) for getting the
Expand Down
14 changes: 14 additions & 0 deletions config/short-url.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@
*/
'enforce_https' => true,

/*
|--------------------------------------------------------------------------
| Allowed URL Schemes
|--------------------------------------------------------------------------
|
| Here you may specify the allowed URL schemes to shorten. For example:
| 'mailto://', 'whatsapp://', 'yourapp://'.
|
*/
'allowed_url_schemes' => [
'http://',
'https://',
],

/*
|--------------------------------------------------------------------------
| URL Length
Expand Down
6 changes: 4 additions & 2 deletions src/Classes/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,10 @@ public function routes(): void
*/
public function destinationUrl(string $url): self
{
if (! Str::startsWith($url, ['http://', 'https://'])) {
throw new ShortURLException('The destination URL must begin with http:// or https://');
$allowedPrefixes = config('short-url.allowed_url_schemes');

if (! Str::startsWith($url, config('short-url.allowed_url_schemes'))) {
throw new ShortURLException('The destination URL must begin with an allowed prefix: '.implode(', ', $allowedPrefixes));
}

$this->destinationUrl = $url;
Expand Down
1 change: 1 addition & 0 deletions src/Classes/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public function validateConfig(): bool
Rule::make('enforce_https')->rules(['required', 'boolean']),
Rule::make('forward_query_params')->rules(['required', 'boolean']),
Rule::make('default_url')->rules(['nullable', 'string']),
Rule::make('allowed_url_schemes')->rules(['required', 'array']),
],
]);

Expand Down
26 changes: 25 additions & 1 deletion tests/Unit/Classes/BuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function exception_is_thrown_in_the_constructor_if_the_config_variables_a
public function exception_is_thrown_if_the_destination_url_does_not_begin_with_http_or_https(): void
{
$this->expectException(ShortURLException::class);
$this->expectExceptionMessage('The destination URL must begin with http:// or https://');
$this->expectExceptionMessage('The destination URL must begin with an allowed prefix: http://, https://');

$builder = app(Builder::class);
$builder->destinationUrl('INVALID');
Expand Down Expand Up @@ -609,4 +609,28 @@ public function builder_works_when_the_date_facade_is_set_to_use_carbon_immutabl

Date::useDefault();
}

#[Test]
public function custom_url_schemes_allowed_if_configured(): void
{
Config::set('short-url.allowed_url_schemes', ['http://', 'https://', 'whatsapp://']);

$shortUrl = app(Builder::class)
->destinationUrl('whatsapp://callMe')
->make();

$this->assertSame('whatsapp://callMe', $shortUrl->destination_url);
}

#[Test]
public function exception_is_thrown_if_invalid_scheme(): void
{
Config::set('short-url.allowed_url_schemes', ['https://', 'whatsapp://']);

$this->expectException(ShortURLException::class);
$this->expectExceptionMessage('The destination URL must begin with an allowed prefix: https://, whatsapp://');

$builder = app(Builder::class);
$builder->destinationUrl('phpstorm://');
}
}
12 changes: 12 additions & 0 deletions tests/Unit/Classes/ValidationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,16 @@ public function exception_is_thrown_if_the_default_url_is_not_a_string(): void
$validation = new Validation();
$validation->validateConfig();
}

#[Test]
public function exception_is_thrown_if_the_allowed_url_schemes_is_not_an_array(): void
{
$this->expectException(ValidationException::class);
$this->expectExceptionMessage('The short-url.allowed_url_schemes field must be an array.');

Config::set('short-url.allowed_url_schemes', 'INVALID');

$validation = new Validation();
$validation->validateConfig();
}
}
Loading