Problem/Motivation

If your Drupal site is installed on a shared hosting environment, you need to somehow tell the server that Drupal's web root is (normally) in the /web subdirectory and not /home/my_user/public_html. If you do redirect, you might get an error.

As a front-end user, I have downloaded D8 RC3 locally and installed Drupal no problems.

  • Create an article (a simple "about us" page)
  • SAVE
  • Message returned on blank screen "Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it."

Yes, I can then back track and the page is saved but any new Save or Resave returns the same message.
I did a little searching and found the appropriate file under the core folders "TrustedRedirectResponse.php" but being a front end user, what needs to be changed to bypass this message? Much of the responses are technical for those at that level, but I (and probably others) need a simple solution please.

I have tried inserting http://localhost..... into various spots with no result (the http seems valid but anything after that is greyed out).

I am not a PHP developer. Is there something I need/can do to make this message 'go away"? Is this on the 'to-do' list to be fixed?
Thank you in advance!

Steps to reproduce

Use shared hosting and find it difficult to serve Drupal from a relocated web root such as /web. Do the redirect, and get an error until some lines are added in settings.php.

Proposed resolution

Until it has been fixed, we can document in Relocated web root on shared hosting how to serve Drupal from /web:

  • Redirect internally to /web folder with a .htaccess file
  • Update settings.php to handle LocalRedirectResponse to pass base_url validation

See also #3569379: Add support for setting web root to /web under Basic site settings.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Comments

miniwebs2 created an issue. See original summary.

tim.plunkett’s picture

Can you explain the "http://localhost" part more?
Is there a ?destination= in the URL at any point during article creation?

miniwebs2’s picture

The localhost bit is just the destination on my local server eg http://localhost:8888/drupal8/node/1/edit.
When I hit "save and keep published" (and msg comes up as above) that's the URL and when I go back a page in my browser it also has the same URL but the content has been saved.
My URL Path settings are "/about-us" (I gather D8 uses a forward slash now.)
And no, there is no ? in destination URL so clean URLS are working.
I even just did a time zone configuration change and when Saving that - same message.

tim.plunkett’s picture

If you could help debug this, I'd appreciate it. I understand that you're not a developer, but if you could try the following, that'd be great:

In the file core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php, around line 90, insert this line:
debug($response->getTargetUrl());

This can be anywhere after that large docblock on line 83, as long as its before the " $safe_response = new Response($message, 400);" part on line 91.

Ideally you should see an external URL in a little message at the top of your screen the next time you submit an article.

If that doesn't work, try $message = $response->getTargetUrl(); right before the trigger_error() line.

$response->getTargetUrl() will show us the offending redirect URL that is giving you trouble.

miniwebs2’s picture

2nd method worked: Message shown now (after an edit and 'save and keep published') as "http://localhost:8888/drupal8/about-us"
Create a new article and Save: Message how reads: "http://localhost:8888/drupal8/node/7"
Are we any further ahead?? :)
Seems the offending redirect URL is the actual url I'm working on.

tim.plunkett’s picture

Title: Saving a Drupal 8 article returns a message containing "Drupal\Core\Routing\TrustedRedirectResponse" » Redirects being built as http://localhost:8888/drupal8 and not considered safe by RedirectResponseSubscriber
Version: 8.0.0-rc3 » 8.0.x-dev
Category: Support request » Bug report

So the http:://localhost:8888/drupal8 part is not being recognized as being the same trusted site, when checked during the redirects. I've definitely installed D8 in a subdir before, so it could be either the localhost or the :8888 part throwing things off.

Short term, can you install to a named URL? Like "drupal8.dev" instead? That would let you progress while we fix the bug.

miniwebs2’s picture

Okay - here's a thing - have just run up another site EXACTLY the same configuration etc on exactly the same server the same day, the same user login details, same 2 pages on the site, etc - and it's good.
I can save and edit pages no problems.
Trying to recreate the issue but can't .... mmmmm...... if I do re-create the issue, I'll get back to here and repost but some sort of weird glitch in the install???
Actually now that I think that - a couple of my toolbar icons were greyed out as well when I went to insert an image - the image icon I found by hovering over the greyed out icon. But in general there was nothing wrong when installing and all went as it should have.

tim.plunkett’s picture

Well I'm glad to hear things are working. I'm going to leave this open for a bit though, please comment here if it happens again.

miniwebs2’s picture

Appreciate your assistance here Tim - I had noticed a couple of other issues similar in other threads from a while back so maybe there is something amiss?
Leave it with you for now - I'm only testing D8 anyway and trying to get my head around all the new stuff.

dawehner’s picture

So yeah one thing which certainly exists is that our caching is not host / base URL / port aware, so if you have rendered the page one using for example d8.dev vs. localhost/d8, you have some really weird issues, so better clear all caches before doing anything.

miniwebs2’s picture

Update:
There's now an RC 4 version of Drupal out so trashed all previous RC 3 versions, ran up another local install using RC4.
Install ran fine (except that OPCache needed to be reset in php.ini as it did before but haven't previously mentioned that one!)
Running PHP 5.6.1 on MAMP.

What I did: Changed the Article Content Type to non front page and no user info shown - SAVE, next screen same as per issues above:
"Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it."

'SAVE" seems to trigger the above message, if I go back a browser page, the info has actually saved correctly and I can carry on until I want to SAVE or SAVE and PUBLISH something again - same error message.

This is why I'm not liking Drupal 8 yet! Can't get past these glitches.

miniwebs2’s picture

Have now installed locally the first release of Drupal 8 - same issue.
Just keeping you updated on my concerns here .... :)
Have also just installed on a remote server - no problems there so this issue only affects local installs for me.

miniwebs2’s picture

Version: 8.0.x-dev » 8.0.0

Drupal 8.0.0
Local install still creates the issue message.
Remote install works fine.

tim.plunkett’s picture

Version: 8.0.0 » 8.0.x-dev

Seems like an environment specific bug. Not sure what the exact factor is.

Max Scott’s picture

I have a similar issue. Often, when I have inputted data, I get the message, "Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it."

As indicated above, this message is generated by core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php when an InvalidArgumentException is caught in line 83. It appears that the exception is generated by the statement in line 79
$safe_response = LocalRedirectResponse::createFromRedirectResponse($response);

This method of Drupal/Core/Routing/LocalRedirectResponse.php is inherited from Drupal/Component/HttpFoundation/SecuredRedirectResponse.php.

In the class SecuredRedirectResponse, the code for this method creates a new LocalDirectResponse instance by the statement
$safe_response = new static($response->getTargetUrl(), $response->getStatusCode(), $response->headers->allPreserveCase());
However, the class LocalDirectResponse does not contain or inherit a constructor with these arguments.

Could this be the source of the problem?

Max Scott’s picture

The explanation given in my previous comment is not correct. Drupal\Core\Routing\LocalRedirectResponse indirectly extends Symfony\Component\HttpFoundation\RedirectResponse which contains a constructor with those arguments.

Issue

However, I have installed Drupal 8.0.1 in a subdirectory 'drupal' of my web root directory. I have modified the .htaccess file in the web root directory by adding the following lines of code, so that I can remove references to the 'drupal' directory in my URLs:

# Serve Drupal 8 from sub directory in web root
RewriteRule ^$ drupal/index.php [L]
RewriteCond %{DOCUMENT_ROOT}/drupal%{REQUEST_URI} -f
RewriteRule .* drupal/$0 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* drupal/index.php?q=$0 [QSA]

Whenever I add data (for example, by way of editing a page, etc.) I get a screen with just the line, "Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it."

Current workaround

I have modified the class Drupal\Core\EventSubscriber\RedirectResponseSubscriber by replacing the occurrences of LocalRedirectResponse with TrustedRedirectResponse as the following patch shows.

--- a/<html>RedirectResponseSubscriber.php (<b>Today 6:47:33 AM</b>)</html>
+++ b/<html><b>Current File</b></html>
@@ -9,7 +9,7 @@
 use Drupal\Component\HttpFoundation\SecuredRedirectResponse;
 use Drupal\Component\Utility\UrlHelper;
-use Drupal\Core\Routing\LocalRedirectResponse;
+use Drupal\Core\Routing\TrustedRedirectResponse;
 use Drupal\Core\Routing\RequestContext;
 use Drupal\Core\Utility\UnroutedUrlAssemblerInterface;
@@ -76,7 +76,7 @@
           // concrete implementation. Default to LocalRedirectResponse, which
           // considers only redirects to within the same site as safe.
-          $safe_response = LocalRedirectResponse::createFromRedirectResponse($response);
+          $safe_response = TrustedRedirectResponse::createFromRedirectResponse($response);
           $safe_response->setRequestContext($this->requestContext);
         }

So far this has solved the issue, but I am not sure whether or not this might have security implications.

Max Scott’s picture

The above explanation is incorrect. Drupal\Core\Routing\LocalRedirectResponse class indirectly extends Symfony\Component\HttpFoundation\RedirectResponse which has a constructor with those arguments.

Issue

I have installed Drupal 8.0.1 in a sub directory, 'drupal', of my web root directory, and have altered the .htaccess file in the web root directory so that I can access Drupal without referencing the 'drupal' directory in my URLs. The changes are as follows:

# Serve Drupal 8 from sub directory in web root
RewriteRule ^$ drupal/index.php [L]
RewriteCond %{DOCUMENT_ROOT}/drupal%{REQUEST_URI} -f
RewriteRule .* drupal/$0 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* drupal/index.php?q=$0 [QSA]

Whenever I add data to the website (for example by editing a node) I get just the line "Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it." on an otherwise blank page.

Work around

I have modified the Drupal\Core\EventSubscriber\RedirectResponseSubscriber class by changing LocalRedirectResponse to TrustedRedirectResponse as the following patch indicates.

--- a/<html>RedirectResponseSubscriber.php (<b>Today 6:47:33 AM</b>)</html>
+++ b/<html><b>Current File</b></html>
@@ -9,7 +9,7 @@
 use Drupal\Component\Utility\UrlHelper;
-use Drupal\Core\Routing\LocalRedirectResponse;
+use Drupal\Core\Routing\TrustedRedirectResponse;
 use Drupal\Core\Routing\RequestContext;
@@ -76,7 +76,7 @@
           // considers only redirects to within the same site as safe.
-          $safe_response = LocalRedirectResponse::createFromRedirectResponse($response);
+          $safe_response = TrustedRedirectResponse::createFromRedirectResponse($response);
           $safe_response->setRequestContext($this->requestContext);

This seems to have solved the issue, but I do wonder whether or not this change might have security implications.

gábor hojtsy’s picture

shotsy247’s picture

I am receiving this error as well.

I have set up a multisite version of D8 within a subdirectory.

For example it is installed at root/public_html/drupal/

I have an htaccess file pointing all traffic to the drupal directory.

When I access my site at www.example.com I do see the site and all content just fine.

But when I attempt to log in I am given the error:

Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it.

If I add drupal to the url I am allowed to log in, for example www.example.com/drupal/

I attempted the workaround suggested in #17, which removes the error, but now says my user1 is denied access.

UPDATE: The access denied error was actually a result of stored cookies on my browser. Attempting the same log in via a new browser resulted in success. Now hopefully these changes will not result in security issues.

_t

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

stephen Piscura’s picture

I have an identical setup to Max Scott (Drupal in a subdirectory in a shared hosting environment) and his patch in #17 eliminated the behavior. Cheers to you Max Scott!

As you say though, i too am curious about the security implications.

vayu’s picture

I also have the message on various pages when I run drupal (8.1.1) in a subdirectory:
"Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it."

I applied the patch from comment #17 and it seems to have eliminated it. I'm worried though because I don't want to play with core. If not just because I don't want to remember what I've done, let alone security. Any other ideas or news on this issue? What's the preferred way to run Drupal 8 in a subdirectory?

* Update, adding the lines given in #30 below to settings.php works for me (and of course feel a lot better than messing with core).

justinlevi’s picture

Here's an actual patch file for #17 above so I can include this in my composer.json file.

justinlevi’s picture

StatusFileSize
new1.1 KB

sorry, adding again as a .patch file.

dave.mikolaj’s picture

StatusFileSize
new1.47 KB

Hi All,

New to Drupal, and came across this issue as well on our local development/uat boxes - the issue is that the URLs aren't always external - if you access the instance via a PathAlias or on a different domain, this error will occur.

Post 17 by Max fixed this issue for us, however there didn't seem to be a patch file made for it, so I've made the changes as described, tested it and this has fixed our issue. Thanks to all who helped with this issue.

brianV’s picture

Status: Active » Needs review

Moving to CNR due to the patch.

Status: Needs review » Needs work

The last submitted patch, 25: core-use-trustedredirect-2612160-17-d8.patch, failed testing.

The last submitted patch, 25: core-use-trustedredirect-2612160-17-d8.patch, failed testing.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andrej galuf’s picture

This is a very, very bad idea. There's a good reason why all user input data is handled by LocalRedirectResponse. Replacing it with a TrustedRedirect response is like blowing up the front door to ensure the burglar won't break through them.

The problem actually originates in the .htaccess redirect itself. The redirect forwards all calls to a subdirectory, but in so doing changes the $base_url to domain.com/subdirectory. LocalRedirectResponse then tries to validate the base_url, using \Drupal\Component\Utility\UrlHelper::externalIsLocal(), which in turn checks whether either the base_url's path is / (that's no longer the case due to redirect) or the first path is equal to expected url (again, it is not, as the /subdirectory is new).

This single method is the reason we have a failing test here and this single method is also the reason why we do not want to blow up the door.

So let's trail back a bit and look at the big picture:
Our expected domain is at domain.com. Drupal sends the request to itself there, the request is forwarded to Drupal because it's not located where Drupal expects itself to be and as a result fails validation. Simplest solution?

Add the following snippet to settings.php:

if (isset($GLOBALS['request']) and
'/subdirectory/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
$GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

Replace subdirectory with your subdirectory name. What does this do? It basically tells Drupal to throw out the subfolder directory in the request, which makes it pass the base_url validation again.

There, done and the doors are still whole.

JoshOrndorff’s picture

@Andrej Galuf,

Thanks for your helpful info on why the path in #17 is a bad idea. I've used your code in #30 instead and found that it works as I had hoped.

Note to anyone else who is trying it be sure to clear your local browser cookies while setting this up. I'm not exactly sure what session info gets stored there, but this fix didn't work for me until I had cleared my drupal caches and local browser caches. In all honesty it took a few clears for me, but that's probably because I did things in the wrong order or missed things.

Thanks,
-Josh Orndorff

stephen Piscura’s picture

Bravo @Andrej Galuf! I've made the changes you mentioned (and undone the hack i previously applied to RedirectResponseSubscriber.php) and everything seems to be working flawlessly! I'll report if i experience otherwise. Thanks again!

afinnarn’s picture

As of Drupal 8.2.4, I now no longer have an issue with Drupal 8 installed in a subdirectory. Previously, with the same Apache setup and no change to the .htaccess file, I did have issues, but they don't happen anymore. Does anyone else still have issues?

JoshOrndorff’s picture

Just did a fresh install of Drupal 8.2.4 on my server (a shared host running CentOS). I had the same issue as before, and the same fix from #30 still worked.

I only experience the issue when .htaccess is setup to redirect to the subdirectory. At first I was happy to just type example.com/subdirectory and had no problems. But once I set up .htaccess and type example.com the issue appears and the fix works.

JoshOrndorff’s picture

Reporting back one more time to point out a problem with the fix from #30.

I'm now getting the drupal access denied page when trying to install a theme or module through the web interfaces at /admin/theme/install and /admin/modules/install .

Removing the patches conceivably fixes the problem, but of course leaves me back with the redirect error.

Rob T’s picture

I am also experiencing the same issue as Josh in #35.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

stephen Piscura’s picture

I've been using @Andrej Galuf's fix in #30 for months with no problems at all. But now i can no longer log in to my site. At mysite.com/user/login the page just refreshes when i enter the username and password, and yet i remain logged out. Is anyone experiencing anything similar? I don't know if it's related to this issue.

stephen Piscura’s picture

Eh, i removed the fix to test without it, and i still can't login. Must be something else. Web development is the worst.

David_Rothstein’s picture

Stephen, a possible tip: The issue you described can sometimes happen due to an incorrect cookie domain (i.e. if the login cookie gets set on a different domain than the one that's in the browser address bar). At least, that's when I've seen it occur in the past. As you said, it is possibly unrelated to this issue.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

karolus’s picture

@Andrej Galuf, I just launched a new site using Drupal 8.3.x, and still had the issue. Without your solution in #30, it would have been very frustrating, indeed.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

pepemty’s picture

@Andrej Galuf I just installed distro Thunder with D8.5, and your snippet doesn't work.

Thing is, I have used it before, even with Thunder, older version of course, and it works like a charm.

Has anybody ran across this...?
Can anybody point me in the right direction...?

Thanks in advance.

Warm regards from sunny México...!

Jose
-----------------
Edit:
This is what I did to fix this issue:

In our public_html folder we create a .htaccess with following content

RewriteRule ^$ web/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ web/$1 [L]

Change "web" with your correct subdirectories.
------------

Then in the .htaccess in our/web folder (~user/public_html/web) we edited the rewritebase so that it looked like following

# Modify the RewriteBase if you are using Drupal in a subdirectory or in a
# VirtualDocumentRoot and the rewrite rules are not working properly.
# For example if your site is at http://example.com/drupal uncomment and
# modify the following line:
RewriteBase /web

Again, change /web with your right subdirectories.

-------------

Then in our settings.php (~/user/public_html/web/sites/default/settings.php)

we added this code at the bottom

if (isset($GLOBALS['request']) and
'/subdirectory/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
$GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

And once again, change /subdirectory/ with your correct path.

pepemty’s picture

New issue:
I'm also experiencing issue #35, but when I ty to update a couple of modules that somehow escaped Composer's gaze.

Did anybody found asolution here...?

Warm regards.

JimBehr’s picture

I followed #46 and it appears to be working now. Thank you!

Some notes:

  • The site files are installed on a shared hosting server, Drupal 8.5.4, in a subdirectory ("public_html/d8t9_2018_07_05").
  • That subdirectory is mapped (to "public_html/d8t9_2018_07_05") as a subdomain so the URL can be referenced like: subdomain2.example.com
  • The lines added to the "public_html/d8t9_2018_07_05/web/sites/default/settings.php" are:
if (isset($GLOBALS['request']) and '/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {  
  $GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}
sunja’s picture

Well the above fixes do work after the site and browser caches are cleared (thanks!) but subDirectory installs really need to be supported officially with well documented install instructions.

unstatu’s picture

#48 also worked for me.

My situations is:
- Drupal is installed in a shared hosting server
- The hosting only allows to point Apache's document root to: /home/myweb/www
- Drupal is installed inside /home/myweb/www with composer. So the index.php file is locate inside /home/myweb/www/web
- In order to redirect the requests to the correct folder, I have the following .htaccess file in /home/myweb/

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/web/
RewriteCond %{HTTP_HOST} ^(www\.)?myweb\.
RewriteRule ^(.*)$ /web/$1 [L]

bas123’s picture

Issue summary: View changes

I am trying to understand the above and assimilate it into what I believe is the same issue but different circumstances:

Drupal 8.5.6

Recently moved from a development Subdomain that pointed to /home/myusername/dev/site/.

There was never a problem with the site running in this version.

However now moved into Production, the site (duplicate with copied database) runs in /home/myusername/public_html/site.

So the URL in the browser is: ‘https://mywebsite.net/site/

So to remove the '/site"I created a .htaccess file and placed it into the ‘home/username/public_html/’ with:

#
# Apache/PHP/Drupal settings:
#
# Redirect to Drupal site (Added 8-10-18).

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !^/site/
# Rewrites all URLS [Replace "example" with the actual domain, without the TLD (.com, .net, .biz, etc)]
RewriteCond %{HTTP_HOST} ^(www\.)?mywebsite\.
# Rewrite all those to insert /folder
RewriteRule ^(.*)$ /site/$1 [L]

The settings.php is set as:

  $settings['trusted_host_patterns'] = array(
    '^mywebsite\.net$',
    '^.+\.mywebsite\.net$',
    '^xx\.xx\.xxx\.x$',
  );

When I enter ‘https:mywebsite.net’ into the browser, it now resolves to the /site/index.php (home page) with no issues (meaning that the "/site" is excluded), except from there two things occur.
I lose the authentication I had when the browser is pointed to the ‘site’ directory
And if I try to login from there, the login page renders:
Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it.

More detailed error:

Drupal\Core\EventSubscriber\RedirectResponseSubscriber->checkRedirectUrl(Object, 'kernel.response', Object)
call_user_func(Array, Object, 'kernel.response', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.response', Object) (Line: 191)
Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object, Object, 1) (Line: 260)
Symfony\Component\HttpKernel\HttpKernel->handleException(Object, Object, 1) (Line: 79)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 666)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Also, any navigation beyond that in ‘https:mywebsite.net’ seems to resolve back to: ‘https:mywebsite.net/site/*.*

Navigation is hit and miss from the site folder and back to the redirect. Meaning that if I am at:
https://mywebsite.net/site/some_page_alias
My Authentication is in place and the page appears as it should, however, if I manually remove the '/site' so the browser is pointed to:
https://mywebsite.net/some_page_alias
The Authentication dissappears, but the page still opens in the browser just the same.
BUT if I then try to login at:
https://mywebsite/user/login
The error shows up:
Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it.

Bottom line, the site will run all day with the '/site' folder shown in the browser, but without it authentication and user functions are lost.

Also, if I am on https://mywebsite.net/any_page_url, the respective page is displayed but when a menu or internal page link is clicked any content link from a node switches to show the 'site/ directory (ie: https://mywebsite.net/site/clicked_page_url), but a "Basic Page" will not necessarily react needing the 'site/' (ie: https://mywebsite.net/clicked_page_url)!!!

The main thing that doesn't make any sense to me is that all of this involves the same base URL, none is an "External" URL as the error would suggest!

I would like to add:

I just logged into the site under:

https://mywebsite.net/site/user/login

as User 302 (Example "Username 4")

and then logged in using the same open browser session under:

https://mywebsite.net/user/login

as User 345 (Example "Username 7")

And the authentication switches between URL's

https://mywebsite.net/site/user/login as "Username 4" and https://mywebsite.net/site/login as "Username 7"..

Clearly this MUST BE FIXED!!!

Any thoughts?

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

cannandev’s picture

#48 worked for me. Don't forget to rebuild your cache once you've made the change.

slawomir’s picture

#46 did it for me. Nice that it doesn't hack the core, and lets me access other directories at the web root level.

auxiliaryjoel’s picture

#46 Did it for me. Drupal 8, cPanel shared hosting.

auxiliaryjoel’s picture

Now that I have this working,
I've noticed that my "git push..." no longer works.
It may be a coincidence, or it may be due to this redirect in place?

This is the git command I run:
git push origin2live master
note: this has worked on all other occasions for months,

I received an error.
At first I thought I may have had changes on server, so I tried to override them:
git push -f origin2live master

the error that I'm getting when trying to git push to my live shared hosting server is:

Counting objects: 13, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (13/13), done.
Writing objects: 100% (13/13), 1.21 KiB | 1.21 MiB/s, done.
Total 13 (delta 10), reused 0 (delta 0)
To path/to/my/repo/public_html/.git
! [remote rejected] master -> master (Working directory has unstaged changes)
error: failed to push some refs to 'ssh://path/to/my/repo/public_html/.git'

Has anyone else had experiences with this that relate to the changes as per #46?

etron770’s picture

Drupal commerce kickstart composer installation.
Same problem #46 - #48 worked

jmoruzi’s picture

I have a similar set-up to what's described above, installed using composer in ~user/public_html/web

#46 (and #48) mostly work, with one major issue in my case. If the .htaccess in the web directory file has a redirect (such as the www to non-www version of site) set up, the site redirects but inserts /web in the path again so you get a page not found error at example.com/web

This goes back to the original problem of trying to remove '/web' from the path but with a redirect '/web' is inserted into the path again. This happens with all pages on the site, not just the home page. Anyone have any ideas how to solve this?

arsn’s picture

Hello,

I face an equivalent problem which happens in environments where language.negotiation is set to domains (http://langdomain.example.com).

The lang_dropdown switcher redirects to subdomains URLs which are improperly considered as external and lead to the "Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it." error.

The problem doesn't exist on environments where language.negotiation is set to path_prefix (http://www.example.com/langdomain).

[EDIT] In both environments, the trusted host patterns include the subdomains...

The patch works but introduce a security regression according to #2507831: Harden redirect responses to make external URIs opt in (was SA-CORE-2015-002 foward-port) as explained in #2532212 Redirect to external URLs now requires a special object.

Better documentation on proper implementation could be good since subdomains & ports redirecction seem to be considered as external redirections by design.

Thanks

Greenman77’s picture

Like most people, solution #46 seemed to go the distance until you want to redirect to www instead of a non-www address using the usual methods. What worked for me on a cpanel apache style dedicated server was modifying the base project .htaccess in public_html with an extra redirect rule for the www instead of in the drupal root.

In public_html/.htaccess

RewriteBase /
# extra rule
RewriteCond %{HTTP_HOST} !^www\.sitename\.com\.au$ [NC]
RewriteRule .* https://www.sitename.com.au/$1 [L,R=301]

RewriteRule ^$ web/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ web/$1 [L]

In /web/.htaccess

I make no changes

settings.php

if (isset($GLOBALS['request']) && '/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
$GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

NickHopps’s picture

if (isset($GLOBALS['request']) and '/docroot/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
  $GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

worked for me, but i can't install module from UI now, it just shows "access denied", anyone knows how to fix this?

rickharington’s picture

Hi everyone

This has worked for me on two sites I've now built. The first was in subfolder /docroot/ and the second in /web/

Using /web/ as an example below;

In public_html/.htaccess (you have to create this file)

RewriteEngine on
RewriteRule (.*) web/$1 [L]

In /web/.htaccess

No changes

In settings.php

if (isset($GLOBALS['request']) && '/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
$GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

Replace {web} with whatever your subfolder is.

Hope it helps someone.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

victor.galguera’s picture

#63 worked for me, thanks!

avpaderno’s picture

Assigned: pueckler » Unassigned
andypost’s picture

sankarprakash’s picture

#46 Worked for me. Thanks @PepeMty

jshimota01’s picture

#46 worked for me. thank the maker. Sucks to spend months developing in a local dev environment only to get hosed on the production server!

ddhuri’s picture

#63 Worked for me. Thanks

freddy rodriguez’s picture

#63 is working fine.

OleCode_’s picture

#63 is working for me on my drupal 9.1.2 (local/production) thnx

futuredesignuk’s picture

#63 & #46 also works for me, excellent support here guys.

  • D9.1.4 installed via composer
  • Hosted on Azure Linux App Service
  • Drupal deployed using Git CI/CD to /site/wwwroot/web/
  • The App Service is fixed to serving from wwwroot - AFAIK cannot change it easily

wwwroot .htaccess

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteRule ^$ web/$1 [L]
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ web/$1 [L]
</IfModule>

wwwroot/web .htaccess

This works with or without this line below, left commented out or breaks things on local (DDEV)

# RewriteBase /web

settings.php

if (isset($GLOBALS['request']) and
'/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
$GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

All good, just a few links like 'Back to site' in admin area top nav go to /web/admin instead of /admin and the ones at the end of completing update.php

geufroi’s picture

my god #63 worked marvelously well for me, thanks !

marioangulo’s picture

Does anyone know how this would work if a symlink is used for the folder. So if I had a subdirectory of web but its a symlink of docroot?

nhcyberguy’s picture

Some background on the experience that i had with this issue. Part of this echos #63's solution:

Shared Hosting Environment
Drupal 9 Hosted in subdirectory (~\public_html\FOLDR\web)
Site was only loading from subdirectory suffix (www.exampl e.com/FOLDR/web)

Here is what I did to get it working on my site, no symlinks:

1. Add an .htaccess file to public_html folder - [cd public_html followed by nano .htaccess]
2. Add the following to the .htaccess file:

RewriteRule ^$ /FOLDR/web/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /FOLDR/web/$1 [L] 

3. Save it [CTRL+X, Y, Enter]
4. I didn't need to uncomment or edit the RewriteBase rule in the .htaccess file found under "/public_html/FOLDR/web/.htaccess"
5. Edit your settings.php file [cd FOLDR/web/sites/default followed by nano settings.php]
6. Note that your settings file may be write protected, temporarily chmod 640 file so you can edit it, chmod back to 444 when done. Get current numeric permissions level of file via "stat settings.php" command.
6. At the bottom of settings.php add this:

if (isset($GLOBALS['request']) and
'/FOLDR/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
$GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

7. Clear Drupal cache
8. Clear web browser cache
9. Use site and test fully (i found some links that had to be adjusted with "/" added for proper resolution)

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

yahyaalhamad’s picture

If you want to solve the problem in a somewhat clean approach, you should define a new EventSubscriber and subscribe to the 'response' event. Make sure it runs before the 'checkRedirectUrl' event_handler.


namespace Drupal\subdomains\EventSubscriber;

use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\subdomains\Entity\Subdomain;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Class SubdomainSubscriber.
 */
class SubdomainsSubscriber implements EventSubscriberInterface {
  /**
   * This will make sure that the subdomains redirects are trusted.
   *
   * @param ResponseEvent $event
   * @return void
   */
  public function subdomainsTrustedRedirect(ResponseEvent $event) {
    $response = $event->getResponse();
    if ($this->isSubdomain($response)) {
      $event->setResponse(TrustedRedirectResponse::createFromRedirectResponse($response));
    }
  }

  protected function isSubdomain($response) {
    // Check if the redirect url is a subdomain.
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    // Run before Drupal's event.
    $events[KernelEvents::RESPONSE] = ['subdomainsTrustedRedirect', 1];
    return $events;
  }
}

avpaderno’s picture

Version: 9.2.x-dev » 9.4.x-dev

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

damienmckenna’s picture

I ran into this specific error via a Webform confirmation page redirect. While debugging the error I found that it was trying to load http://example.commyform/confirmation?token=something instead of http://example.com/myform/confirmation?token=something, so somewhere in the system it's loosing the leading slash on the page path.

It turned out this specific problem was caused by incorrect path_alias records that didn't have a leading slash on the "alias" records. I fixed the bug with this hook_post_update_NAME() script:

function MYMODULE_post_update_fix_prefixless_path_aliases() {
  $storage = \Drupal::entityTypeManager()->getStorage('path_alias');

  // Get a list of aliases that do not start with a slash.
  $query = $storage->getQuery();
  $query->condition('alias', '/%', 'NOT LIKE');

  // Update each alias.
  $aliases = $storage->loadMultiple($query->execute());
  foreach ($aliases as $alias) {
    $alias->setAlias('/' . $alias->getAlias());
    $alias->save();
  }

  return t('Fixed %count path aliases that did not have a leading slash.', [
    '%count' => count($aliases),
  ]);
}

Hope that helps someone else.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

myself.csingh’s picture

#46 worked for me.

lubwn’s picture

In my case I was getting error because Drupal is behind reverse proxy. My problem is that it is a bunch of different servers all pointing to different subdirectories, while I do not have an access to the main server where the main website lives.

So in my case I did not need to "remove" the subdirectory but ADD the subdirectory instead. Which worked, but also resulted in TrustedRedirect errors.

My settings.php file is:

$trim_path = '/subdirectory';
if (isset($GLOBALS['request'])) {
  $request = $GLOBALS['request'];
  if ($request->server->get('SCRIPT_NAME') == "/index.php") {
    $request->server->set('SCRIPT_NAME', '/subdirectory/index.php');
	$request_uri = $trim_path . substr($request->server->get('REQUEST_URI'), 1);
	
	$request->server->set('REQUEST_URI', $request_uri);
  }
}

To fix trustedRedirect errors I used rather stupid jquery front-end fix, but it works:

/* Fix trustedRedirectResponse */
$( document ).ajaxComplete(function (event, xhr, settings) {
	
	$("a").each(function() {
		$(this).attr("href", $(this).attr("href").replace("edit?destination=/node/", "edit?destination=/subdirectory/node/"));
	});
	
});

I had trouble in ajaxified views, which lead to wrong redirects but it was all in GET parameter, so this basicly just replaces href attribute with proper URL.

gzveri’s picture

#76 is the only solution, clean and worked perfectly for installing Drupal10 in a subfolder of root folder /public_html for a primary domain on linux deluxe shared account on godaddy.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

selinav’s picture

#76 works for me with Drupal10 with hostinger.

I have adapted the path :

if (isset($GLOBALS['request']) and
'/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
$GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

zuhair_ak’s picture

#76 worked for me

joachim’s picture

Priority: Normal » Major

This is surely a major.

I just moved my blog site to a cPanel-based host, and *NOTHING* worked.

I used the .htaccess redirect from https://www.drupal.org/hosting-support/2021-09-21/unable-to-set-document... to get the document root as /web to work, but then I hit this.

avpaderno’s picture

I am going to restore the issue summary, which was removed from a previous edit.

avpaderno’s picture

Issue summary: View changes
joachim’s picture

The fix in #30 also needs to handle update.php, so in full:

if (isset($GLOBALS['request']) && '/subdirectory/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
  $GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}
elseif (isset($GLOBALS['request']) && '/subdirectory/update.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
  $GLOBALS['request']->server->set('SCRIPT_NAME', '/update.php');
}
bernard63’s picture

#92 is perfect for me
Thank's Joachim

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

ressa’s picture

Title: Redirects being built as http://localhost:8888/drupal8 and not considered safe by RedirectResponseSubscriber » How to run Drupal on shared hosting via /web subfolder
Component: routing system » documentation
Category: Bug report » Task
Issue summary: View changes
Status: Needs work » Active

Thanks everyone for sharing your solutions, I have attempted to document the basics on the doc page Relocated web root on shared hosting with other methods.

I have kept the example very basic, but extra notes for specific use cases could of course be added below, so feel free to check it out, and add extra info.

Since this issue has pivoted from being about a local development bug in 2015 into about documenting how to get a Drupal site to work on shared hosting, I am updating the Issue Summary and title (originally "Redirects being built as http://localhost:8888/drupal8 and not considered safe by RedirectResponseSubscriber").

I created a new issue with a feature request, since having this option would help a lot of users, and make Drupal easier to run on sharing hosting: #3569379: Add support for setting web root to /web under Basic site settings. Or the feature could be worked on here ... what do you think @joachim?

joachim’s picture

I don't understand why this has been changed to a task -- yes, people have been sharing how to get it working, but that's because until this bug is fixed, workarounds are needed, and this issue is where people are going to land when they encounter the problem.

ressa’s picture

Title: How to run Drupal on shared hosting via /web subfolder » Redirects being built as http://localhost:8888/drupal8 and not considered safe by RedirectResponseSubscriber
Component: documentation » routing system
Category: Task » Bug report
Issue summary: View changes
Status: Active » Needs work

All right, I have changed it back to a bug report. Maybe you can update the Issue Summary to clarify what needs to be done?

Thanks!