Change list of valid URI schemes in Drupal 8

Posted by patrick on Tue, 06/06/2017 - 13:12

If you need to support obscure URI schemes in your Drupal 8 instance and you're getting error messages about invalid URI schemes, this post is for you.

Suppose a customer asks you to add a WhatsApp Share Link somewhere. It might look something like this:

use \Drupal\Core\Url;
 
Url:fromUri('whatsapp://send', [
  'query' => [
    'text' => 'Some text',
  ],
])->toString();

This should work, since the URI is perfectly valid per the specification. But instead of the desired link, we'll get this error message, that results in a white page:

InvalidArgumentException: The URI 'whatsapp://send' is invalid. You must use a valid URI scheme. Use base: for a path, e.g., to a Drupal file that needs the base path. Do not use this for internal paths controlled by Drupal. in Drupal\Core\Utility\UnroutedUrlAssembler->assemble() (line 64 of core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php).

What happened here? Drupal 8 actually maintains a list of valid URI schemes, that are allowed to be used during URL generation. If a scheme is not in this list of protocols, it will result in this error message. whatsapp is not included in this list by default, so Drupal considers the URI to be invalid.

This is actually a nice security feature, but what if we just need to support schemes other than the default? It's easy and quickly done, as long as you know where to look. The allowed protocols are specified as a parameter to the services container. The parameter in question is called filter_protocols. The default parameters for the services container are set in a file called default.services.yml in the sites/default directory of your Drupal installation. You could also use a development.services.yml file just for development and more. If you want to change any of the settings, copy the default.services.yml file to services.yml and change the settings there as needed. To support e.g. the whatsapp protocol, we would need to add that to the list defined by the filtered_protocols parameter. Now rebuild your container (e.g. by calling drush cr on the command line) and the error message should be gone.

# Allowed protocols for URL generation.
parameters:
  filter_protocols:
    - http
    - https
    - ftp
    - news
    - nntp
    - tel
    - telnet
    - mailto
    - irc
    - ssh
    - sftp
    - webcal
    - rtsp
    - whatsapp

Of course you could also remove any schemes you don't need, e.g. telnet for increased security ;).

Systems
Drupal 8