I'm trying to get my site to use only relative URLs, like in the question drupal.stackexchange.com/questions/105932

EDIT 3: It seems like Drupal 8.0.3 and beyond will do this by default:


But I've changed the code for Drupal 8 to this by getting rid of the deprecated function:

function custom_file_url_alter(&$uri) {
  global $base_path;

  $scheme = file_uri_scheme($uri);

  if (!$scheme || $scheme == 'public') {
    if (!$scheme) {
      $path = $uri;
    else {
      ////$wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
      $wrapper = \Drupal::service('stream_wrapper_manager')->getViaScheme($scheme);
      $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);

    // Clean up Windows paths.
    $path = str_replace('\\', '/', $path);

    $uri = $base_path . ltrim($path, '/');

The problem is, whenever I add even just an article with an image (or any content type with a file in it) I get an error like this: 'Uncaught PHP Exception InvalidArgumentException: "The URI '/sites/default/files/field/image/h.jpg' is invalid. You must use a valid URI scheme." at /srv/www/example/core/lib/Drupal/Core/Url.php line 301, referer: http://example.com/node/add/article. I'm also getting this error when visiting a page that links to certain uploaded files.

The documentation says that this hook is called whenever the file_create_url method is called, but I don't know enough about Drupal to understand what scenario this method is being called which is causing Url.php to get mad at me. For what reasons does Drupal call file_create_url, and why are almost all scenarios working for me while some are freaking out about no scheme being used?

Any extra information or guidance about this will be appreciated.


Here are some examples of $uri as it comes into the function (1) and as it leaves (2) .

1: 'core/themes/stable/images/core/icons/5181c6/pencil.svg' 2: '/core/themes/stable/images/core/icons/5181c6/pencil.svg' 1: 'public://css/css_Ys2L0rGQLjkWZQC7f9g5LiLUni8xUQvB1HqJHn3TKK4.css' 2: '/sites/default/files/css/css_Ys2L0rGQLjkWZQC7f9g5LiLUni8xUQvB1HqJHn3TKK4.css' 1: 'public://field/image/h_0.jpg' 2: '/sites/default/files/field/image/h_0.jpg'

The h_0 example is one that happened after I created an article with the h.jpg image, which crashed and prevented creation of the article. I've noticed that when I upload the image using the form, the little ajax thing that happens and shows you the preview of the image doesn't work when I use this file_url_alter code. So, something is trying to call file_create_url when saving the image in the first place, and then, since the image is not properly saved, it can't be added as a field of the node.

Also, I've printed a backtrace, and it seems the crash happens after ThemeManager.php's render function calls template_preprocess_file_link(), which, in file.module, tries to do this: $variables['link'] = \Drupal::l($link_text, Url::fromUri($url, $options));

...which caused the error I mentioned in the first place.


I've made this work by modifying one line of core. I changed the last line of template_preprocess_file_link() in file.module from $variables['link'] = \Drupal::l($link_text, Url::fromUri($url, $options)); to $variables['link'] = $url;. This makes all URLs relative without any noticeable issues. Does anyone know how to achieve this without hacking core? Or, does anyone know what negative effects doing this might cause?

  • The resulting URI needs to be public://field/image/h.jpg if that helps
    – Clive
    Commented Dec 2, 2015 at 17:24
  • Thanks, Clive. Since your comment I've tried returning public:// for public files, and this allows me to create nodes with files, but it stops my URLs from being relative. If I could just figure out which scenarios require public:// and which don't... I'll keep experimenting. Commented Dec 2, 2015 at 18:02
  • You should handle that on the Form layer and convert the url to the drupal standard before validation/submission.
    – Eyal
    Commented Dec 2, 2015 at 20:59
  • The form is already correct, actually. The uri that comes into my hook is already formatted correctly, but for absolute URLs. When $uri is saved at the end of my function, it is in relative format, but for some reason this doesn't work in some situations. I believe it's because file_create_url is called in too many unrelated scenarios. I'll update my question with more info. Commented Dec 3, 2015 at 15:24

1 Answer 1


Maybe you can take a look at this function new to Drupal 8 :


Once you pass an uri through file_create_url() you get an absolute url. You can then pass it to file_url_transform_relative() and you'll get the relative path if indeed it's pointed to a local file.

  • 1
    This is the suggested way to obtain it, yes. LinkIt module recently implemented this fix.
    – Kevin
    Commented Mar 30, 2017 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.