The steps

  1. Have an .htaccess file that maps your domain name, say 'example.com', into a directory 'eclipse/head' relative to your server root directory
  2. Install Drupal 7.x-dev into eclipse/head. This means eclipse/head contains the index.php file.
  3. Visit example.com. Thus far every thing is fine. However, if you go to an admin page, say structure, you get 'http://example.com/eclipse/head/#overlay=admin/structure' in the address bar because the default base URL is 'http://example.com/eclipse/head'
  4. Change the base URL to 'http://example.com' in settings.php.
  5. Revisit the structure admin page

Expected behavior: You get the admin page with 'http://example.com/#overlay=admin/structure' in the address bar, without the '/eclipse/head'. BTW, using the same settings with D6 you get to the admin page with no problem without the 'eclipse/head'.

Actual behavior: You are redirected to the front page. You cannot access your admin pages anymore. Other functionalities are lost also.

I am not sure it is a bug. Maybe some additional settings are required in D7 to change the base URL.

CommentFileSizeAuthor
#6 757506_more_stable_request_path_allow_htaccess_rule.patch1.45 KBAnonymous (not verified)
#10 757506_more_stable_request_path_allow_htaccess_rule_02.patch2.41 KBAnonymous (not verified)
#12 757506_more_stable_request_path_allow_htaccess_rule_03.patch4.73 KBAnonymous (not verified)
#15 757506_more_stable_request_path_allow_htaccess_rule_04.patch2.39 KBAnonymous (not verified)
#22 bootstrap_7_9.patch1.49 KBTrevorBradley
#24 request-path-bootstrap-757506-22.patch1.62 KBTrevorBradley
#27 request-path-bootstrap-757506-22.patch1.6 KBTrevorBradley
#28 request-path-bootstrap-757506-27.patch1.6 KBTrevorBradley
#44 request-path-bootstrap-757506-43.patch1.52 KBTrevorBradley
#46 request-path-bootstrap-757506-45.patch1.54 KBTrevorBradley
#55 request-path-bootstrap-757506-55.patch2.3 KBm.stenta
#76 request-path-bootstrap-757506-76.patch5.35 KBm.stenta
#76 request-path-bootstrap-757506-76-test.patch3.05 KBm.stenta
#80 request-path-bootstrap-757506-80-complete.patch5.5 KBm.stenta
#80 request-path-bootstrap-757506-80-test.patch3.19 KBm.stenta
#84 request-path-bootstrap-757506-84-complete.patch5.74 KBm.stenta
#84 request-path-bootstrap-757506-84-test.patch3.43 KBm.stenta
#87 request-path-bootstrap-757506-87-complete.patch5.88 KBm.stenta
#87 request-path-bootstrap-757506-87-test.patch3.58 KBm.stenta
#90 request-path-bootstrap-757506-90-test.patch3.58 KBm.stenta
#90 request-path-bootstrap-757506-90-complete.patch7.38 KBm.stenta
#103 drupal-757506-103-by-m.stenta-TrevorBradley-axel.rutz-TEST.patch33.84 KBgeek-merlin
#103 drupal-757506-103-by-m.stenta-TrevorBradley-axel.rutz-FIX.patch37.62 KBgeek-merlin
#107 drupal-757506-107by-m.stenta-TrevorBradley-axel.rutz-req.patch36.8 KBgeek-merlin
#108 drupal-757506-108-request-path-TEST-ONLY.patch4.18 KBgeek-merlin
#108 drupal-757506-108-request-path-TEST+FIX.patch7.17 KBgeek-merlin
#110 interdiff.txt353 bytesgeek-merlin
#110 drupal-757506-110-request-path-TEST+FIX.patch7.2 KBgeek-merlin
#110 drupal-757506-110-request-path-TEST-ONLY.patch4.18 KBgeek-merlin
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Anonymous’s picture

Status: Needs work » Active
Damien Tournoud’s picture

Status: Active » Postponed (maintainer needs more info)

Out of curiosity, could you try to figure out what is the base URL automatically detected by Drupal 6 in that case?

One way of doing that is to click on the RSS icon that most browsers (including Firefox and Safari) are automatically displaying when you visit the front page of your Drupal site. Please report the full URL.

Anonymous’s picture

Status: Active » Postponed (maintainer needs more info)
Anonymous’s picture

Status: Postponed (maintainer needs more info) » Active
Anonymous’s picture

Anonymous’s picture

Status: Active » Needs review
FileSize
1.45 KB
Anonymous’s picture

Damien Tournoud’s picture

Status: Postponed (maintainer needs more info) » Needs work
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.367
diff -u -r1.367 bootstrap.inc
--- includes/bootstrap.inc	26 Mar 2010 17:14:45 -0000	1.367
+++ includes/bootstrap.inc	31 Mar 2010 09:11:51 -0000
@@ -1859,11 +1859,12 @@
   set_error_handler('_drupal_error_handler');
   set_exception_handler('_drupal_exception_handler');
 
+  drupal_settings_initialize();
   drupal_environment_initialize();
   // Start a page timer:
   timer_start('page');
   // Initialize the configuration, including variables from settings.php.
-  drupal_settings_initialize();
+
 }
 
 /**

This is not acceptable. drupal_environment_initialize() *has* to run before everything else (mainly for security reasons).

@@ -2184,7 +2186,13 @@
   elseif (isset($_SERVER['REQUEST_URI'])) {
     // This is a request using a clean URL. Extract the path from REQUEST_URI.
     $request_path = strtok($_SERVER['REQUEST_URI'], '?');
-    $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/'));
+    if ($base_url) {
+      $base_path_len = strlen($base_url)- 7 - strlen($_SERVER['HTTP_HOST']);
+    }
+    else {   
+      $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/'));
+    }    
+    
     // Unescape and strip $base_path prefix, leaving q without a leading slash.
     $path = substr(urldecode($request_path), $base_path_len + 1);
   }

Using the information we gathered from settings.php does make sense here. Could we simply use $base_path?

Anonymous’s picture

Status: Needs review » Needs work
Anonymous’s picture

Status: Needs work » Needs review
FileSize
2.41 KB
Anonymous’s picture

Anonymous’s picture

The last submitted patch, 757506_more_stable_request_path_allow_htaccess_rule_03.patch, failed testing.

Anonymous’s picture

Anonymous’s picture

Anonymous’s picture

Component: other » base system
Anonymous’s picture

Status: Needs review » Closed (duplicate)
Anonymous’s picture

Title: If you set a new base URL in settings.php, which is correctly mapped into the Drupal root directory, the admin pages disappear. » No title
Version: 7.x-dev » 4.0.0
Category: bug » task
Priority: Normal » Minor
Status: Closed (duplicate) » Closed (fixed)
WorldFallz’s picture

Title: No title » If you set a new base URL in settings.php, which is correctly mapped into the Drupal root directory, the admin pages disappear.
magnusk’s picture

Title: If you set a new base URL in settings.php, which is correctly mapped into the Drupal root directory, the admin pages disappear. » request_path incorrectly interprets the path in case of a Rewrite
Version: 4.0.0 » 7.x-dev
Category: task » bug
Priority: Minor » Normal
Status: Closed (fixed) » Active

The patch in #15 solves the problem for me (it looks like this issue got lost when the original author's account was closed?).

Without the patch I would get a page not found on e.g. "user/login". The watchdog reports that "in" is not found, with the hidden path to Drupal being "hq/live"; a number of initial characters in the path are incorrectly trimmed. If the base_path is trimmed to the point of being empty (e.g. "admin"), it looks like the URL just loads the front-page.

My example .htaccess settings:

  RewriteCond %{HTTP_HOST} ^hq\.example\.com$ [NC]
  ReWriteCond %{REQUEST_URI} !/hq/live/
  RewriteRule ^ /hq/live%{REQUEST_URI} [L]

and in settings.php the base url is defined as:

  $base_url = 'http://hq.example.com';

I think this is a regression: the same use of RewriteRule in .htaccess + $base_url in settings.php works fine in Drupal 6.

magnusk’s picture

Title: request_path incorrectly interprets the path in case of a Rewrite » request_path incorrectly interprets the path in case of a RewriteRule in .htaccess and $base_url in settings.php
TrevorBradley’s picture

Status: Active » Needs review
FileSize
1.49 KB

Unfortunately this patch doesn't seem to apply to 7.9 without errors. :(

On the plus side, I've updated it for 7.9 :)

This works without modifying .htaccess and allows me to run batch updates and change the theme without authorization errors!

Status: Needs review » Needs work

The last submitted patch, bootstrap_7_9.patch, failed testing.

TrevorBradley’s picture

Status: Needs work » Needs review
FileSize
1.62 KB

Alright, let's try this again, following procedure and using git....

Status: Needs review » Needs work

The last submitted patch, request-path-bootstrap-757506-22.patch, failed testing.

TrevorBradley’s picture

Sorry folks, this isn't helping me get over my intrinsic hatred of all things git. I'm not sure where to go from here.. Patch works great, Drupal test rejects it. I'm following the procedure here: http://drupal.org/node/707484 ... Any ideas what I'm doing wrong? I'm checking out core through git, making my changes, then running "git diff > request-path-bootstrap-757506-22.patch"

TrevorBradley’s picture

Alright, third time's the charm...

TrevorBradley’s picture

Fourth! Fourth time's the charm.

TrevorBradley’s picture

Status: Needs work » Needs review

And setting up the review... sorry for all the spam here. :(

cvdenzen’s picture

Version: 7.x-dev » 7.10

This patch did not make it in D7.10?
Or was it not meant to be incorporated into the standard Drupal system?

TrevorBradley’s picture

No clue... the idea of submitting a patch to core was terrifying to me, so I thought someone else could take that here. :)

I'm guessing that the change from D6 to D7 was intentional for some other reason and this patch will be rejected.... but determining the reason will bring the problem closer to resolution.

lhugg’s picture

subscribe

legion80’s picture

This patch fixed the issue that I had filed in #885846: drupal 7 does not work with subdirectory installations on a shared host (and was duped to this bug).

sylus’s picture

I can confirm this bug still exists in Drupal 7.12. Is this likely to be committed or at least raised to critical?

TrevorBradley’s picture

Version: 7.10 » 7.x-dev

I'm going to move the version back to 7.x in the hopes that someone sees it and adds it to the queue. I'm loathe to change the priority of the bug to critical... if it were it would have been fixed already. I guess not the core devs aren't working on shared hosts.

Not sure where else to take it from here. Can anyone conform this patch still works in 7.12? It's one of the reasons I've been holding back on my upgrades... having to patch core on each of my installs is a real pain.

TrevorBradley’s picture

Priority: Normal » Major

OK, I'm going to do a slightly evil thing and nudge this bug up to "major" where it will hopefully get seen. It is affecting the subset of Drupal 7 users who use shared hosting with .htaccess rewrites (i.e. multiple Drupal installs in subdirectories, masked with some clever mod_rewrite rules), a trick that many ISPs seem to use to allow users to host multiple sites from one directory. This bug breaks Drupal 7 and makes it unusable for us while Drupal 6 still works great in a similar environment

I'll gladly take the wrist slap if it gets nudged back down to "normal". I'd expect that we'll all be patching for a few months to come though. :(

(I hate pushing this up becase I suspect there's a reason why this was broken between D6 and D7 and that this fix breaks something else. I'm guessing it's the overlay, which this patch seems to leave untouched, but it would be handy if we could get more reports that the patch is working for people)

TrevorBradley’s picture

Just to give some more context, here's the .htaccess file in my root directory my ISP uses to allow multiple sites to be hosted from the same account, without changes to their apache httpd.conf (trimmed for clarity):

Options +FollowSymLinks
ReWriteEngine On
ReWriteBase /
#RULE: www.postfrog.com:www.postfrog.com
ReWriteCond %{HTTP_HOST}  ^www.postfrog.com
ReWriteRule !^www.postfrog.com/   - [C]
ReWriteRule ^(.*)  www.postfrog.com/$1  [L]
#RULE: www.orru.ca:www.orru.ca
ReWriteCond %{HTTP_HOST}  ^www.orru.ca
ReWriteRule !^www.orru.ca/   - [C]
ReWriteRule ^(.*)  www.orru.ca/$1  [L]
#RULE: www.digilynx.ca:drupal
ReWriteCond %{HTTP_HOST}  ^www.digilynx.ca
ReWriteRule !^drupal/   - [C]
ReWriteRule ^(.*)  drupal/$1  [L]
#RULE: www.sfuchoir.ca:drupal
ReWriteCond %{HTTP_HOST}  ^www.sfuchoir.ca
ReWriteRule !^drupal/   - [C]
ReWriteRule ^(.*)  drupal/$1  [L]

Where I have subdirectories called "drupal", "www.postfrog.com", "www.orru.ca", etc off of my web root. To do this, the $base_url needs to be set, and then the URLs while browsing the site become absolutely mangled.

magnusk’s picture

I patch each new release of Drupal 7 on my servers (and re-generate a new patch file).

I am unable to find what other impact the necessary change would have, and I haven't found any evidence of explicit intent in this regression from Drupal 6. There seem to have been a couple of issues that were opened a long time ago for this problem, and then the person who had opened them deleted the text of all of their issues and comments -- and stopped contributing to Drupal?

catch’s picture

Version: 7.x-dev » 8.x-dev
Issue tags: +Needs backport to D7

Bumping version, see http://drupal.org/node/767608

TrevorBradley’s picture

Yup, good call. I saw the backport article before but only now just saw where the tags were set. Thanks catch!

drupalmeister’s picture

Thanks so much TrevorBradley (http://drupal.org/user/770722) for supplying me with a great patch. I have just uploaded it and it works great on d.7.12

Thanks so much

TrevorBradley’s picture

Cool drupalmeister! I'm glad it worked for you. Could you perhaps flag this as "reviewed and tested by the community" if you're feeling good about it?

tim.plunkett’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests
+++ b/includes/bootstrap.incundefined
@@ -2742,7 +2747,14 @@ function request_path() {
-    $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/'));
+    //$base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/'));

Remove it, don't just comment it out.

+++ b/includes/bootstrap.incundefined
@@ -2742,7 +2747,14 @@ function request_path() {
+      $base_path_len = strlen(parse_url($base_url,PHP_URL_PATH));

Missing space after comma.

+++ b/includes/bootstrap.incundefined
@@ -2742,7 +2747,14 @@ function request_path() {
+    else {   ¶
+      $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/'));
+    }      ¶

Trailing whitespace

Also, needs tests.

TrevorBradley’s picture

Status: Needs work » Needs review
FileSize
1.52 KB

OK, here we go. I'm not entirely sure what the "needs tests" tag entails, though it's vaguely mentioned here: http://drupal.org/core-gates

Crossing fingers that I've done this correctly, Patch and I have a bad history.

Status: Needs review » Needs work

The last submitted patch, request-path-bootstrap-757506-43.patch, failed testing.

TrevorBradley’s picture

Alright git - make me hate you less this time... I've followed the instructions here to a tee...

TrevorBradley’s picture

Status: Needs work » Needs review

And review, because of course I'd forget that...

TrevorBradley’s picture

Status: Needs review » Needs work

Yay! Also, figured out Needs Tests.

More patient waiting then... :)

TrevorBradley’s picture

Status: Needs work » Needs review

Ack! Changed to needs work. Drupal.org not being my friend today.. :|

tim.plunkett’s picture

Status: Needs review » Needs work

request_path() has changed pretty drastically in D8.

Is this still reproducible?

TrevorBradley’s picture

Tim, I'm uncertain - I'll have to test this. I'll try to find time this week.

If the changes do fix this bug, is it possible those request_path changes might get backported to D7, or are they so drastic that they're unlikely to be backported? If the latter, I think this should get changed back to a D7 bug.

tim.plunkett’s picture

If it's still a bug in both, it will be fixed first in D8, and then in D7, even if its totally different code.
If it's not reproducible in D8, then it can go straight back to D7.

modctek’s picture

I'm still seeing this bug in 7.14

TrevorBradley’s picture

I'm frankly swamped and likely won't get to look at tim.plunkett's request for at least 2 weeks. Can someone who has this issue grab a copy of 8.x-dev and see if it's still occurring?

m.stenta’s picture

Status: Needs work » Needs review
Issue tags: -Needs manual testing
FileSize
2.3 KB

I noticed this issue when I first started using D7, because many of my D6 sites were installed with Drupal in a subdirectory of the webroot (to keep the webroot clean). Since moving to D7, I've stopped putting Drupal in a subdirectory because it didn't work (same behavior described in this issue's summary). Today I decided to dig deeper into it, and found this issue.

It's unfortunate that the original poster of this issue closed their account, because it removed the content from most of this thread. A lot of helpful information was probably lost. So, I had to figure it out mostly from scratch...

I can confirm that this is only a D7 issue. It does not happen in D8. I'm changing the version of this ticket back to 7.x-dev.

More details on the testing I performed:

I have two local development sites set up: one with the latest D8 repository, and one with the latest D7. I started both with Drupal in the webroot, which worked fine. Then, on both, I performed the following steps:

  1. Moved Drupal into a subdirectory of the webroot called "drupal".
  2. Added a .htaccess file to the webroot that redirects all requests into the "drupal" subdirectory (contents of the file are below).
  3. Added a $base_url declaration to settings.php on both sites, to tell it to hide the subdirectory. In my case, the $base_urls were set to "http://d7.dev" and "http://d8.dev".

Contents of .htaccess:

RewriteEngine on

# Pass requests to drupal
RewriteRule ^$ /drupal/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /drupal/$1 [L]

Results

After performing those steps, the site continued to work as it did before in the D8 version, but it stopped working on the D7.

I then applied the changes in the patch from #44 to the D7 site, and it started working again.

Then I did some more digging to see if I could isolate what's really going on...

Cause

As far as I can tell, the reason this happens is because of changes that were made to the variable bootstrapping between D6 and D7.

In D6, the way Drupal determined the requested path was as follows:

  1. drupal_bootstrap() called conf_init() right from the start.
  2. conf_init() loaded settings.php and set up the $base_url variable.
  3. Later in bootstrap (phase == DRUPAL_BOOTSTRAP_PATH), drupal_init_path() is called, which sets up $_GET['q']
  4. Finally, after bootstrapping, index.php calls menu_execute_active_handler(), which retrieves the path from $_GET['q'].

In D7, on the other hand, this is what happens:

  1. drupal_bootstrap() calls _drupal_bootstrap_configuration(), which first calls drupal_environment_initialize() and then calls drupal_settings_initialize().
  2. drupal_environment_initialize() sets $_GET['q'] = request_path();
  3. request_path() figures out the requested path by measuring the length of the executing script's (index.php) containing directory and trimming that many characters off the front of $_SERVER['REQUEST_URI']. (this logic is what breaks the paths)
  4. Finally, just like in D6, menu_execute_active_handler(), retrieves the path from $_GET['q'].

In D7, with Drupal in a subdirectory, this works fine with clean-urls turned off, because request_path() does something different when $_GET['q'] is already set. But with clean urls turned on, part of the requested path is stripped off the front, so you end up requesting something like "tructure" instead of "admin/structure", based on how long the name of your subdirectory is (in that case, the length of the subdirectory name "drupal/" is 7, which is how many characters are stripped from the path).

Solution

The changes made by the patch in #44 worked to fix the problem, but I'm not sure that it's necessarily the best way to do it. It introduces a redundant loading of settings.php in drupal_environment_initialize(), just so that it can make sure that the $base_url variable is set when it gets to request_path().

Instead, I'm going to propose moving the $_GET['q'] = request_path(); call to the end of the drupal_settings_initialize() function.

Then, in request_path(), we can assume that $base_url is always available (since it is called at the end of drupal_settings_initialize() which creates $base_url no matter what), and use that to figure out if there are other subdirectories that need to be removed from the path before request_path() returns it.

This seems to make sense to me, because the $_GET['q'] = request_path(); call doesn't seem like it NEEDs to be in drupal_environment_initialize(), but maybe I'm overlooking something. It might make more sense that it's in the "environment" initialization than in the "settings" initialization, but that might be bikeshedding, because they are both called from _drupal_bootstrap() back-to-back anyway, so there's no functional difference (again, unless I'm overlooking something).

Let's see what the testbot has to say, and get input from others on the matter...

modctek’s picture

Version: 8.x-dev » 7.x-dev
Status: Needs work » Needs review
Issue tags: -Needs backport to D7

I just tested #55 and it worked like a charm! Thanks - you are a rockstar!

kolacekjan’s picture

#55 works great! Thanks!

TheThumbPuppy’s picture

#55 works ! you're on my christmas list mr m.stenta ! :)

tim.plunkett’s picture

Status: Needs review » Needs work

Fix makes sense, still needs tests.

shadlaws’s picture

@m.stenta - thanks much for the new patch, as well as your great explanation! I agree - your method seems to more clearly isolate and correct the problem. And most importantly, it works!

iva2k’s picture

Status: Needs work » Reviewed & tested by the community

@tim.plunkett >Fix makes sense, still needs tests
Can you elaborate what tests are needed to include that into core?

I encountered that problem right away and had to hack the core to work properly. The proposed solution in #55 is clean and passes the testbot. I also tested it on my setup - patch in #55 works perfectly.

tim.plunkett’s picture

Status: Reviewed & tested by the community » Needs work

It needs automated tests to prove that it's currently broken, to prove that this fix works, and to prevent future regressions.

See http://drupal.org/node/1468170 for more information.

TrevorBradley’s picture

Is it even possible to write a test case for this? Unless a test case can handle reconfiguring apache to have mod_rewrite work in a different way than a standard LAMP setup.

I can't see a way to programatically reproduce the bug as the testing documentation describes. The bug is a result of the environment the code is run in and won't be apparent in the code itself.

EDIT: trying to read through that testing documentation... the first two steps required for a proper test would be "Move entire drupal directory to a subdirectory" and "replace .htaccess with the following file". Is that within the scope of the testing suite?

TrevorBradley’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs tests +Needs manual testing

Flipping this to "Needs manual testing/Reviewed and tested" (and feel like a jerk for doing so, sorry!)... Having reviewed the testing instructions, I don't believe it's possible to create a testing suite for this bug. It's not a part of any core module - the bug is in bootstrap.inc itself and doesn't relate to any subsystem. If a testing suite were to be created, it would involve moving the entire drupal subdirectory while the testing was going on.

If it is possible to write a test suite for this, I think we'd appreciate some guidance as to where to start. The documentation at http://drupal.org/node/1468170 appears inadequate for creating a test case this complex. My best stab at what the test case would need to do:

1) Verify mod_rewrite is installed on the webserver
2) Move the *entire* contents of the web root to a subdirectory (including drupal's root .htaccess)
3) Create a new .htaccess file in the web root
4) Access specific URLs and demonstrate that they don't respond with the correct result.

(4) is the easy part, and it appears to be the kind of thing the test cases were built for. 1-3 have me stumped though. I suspect that it might be possible to do this with the test suite, but it would take a hacking ninja with expertise as to how the system worked to craft.

Again, my sincere apologies if I'm bumping this bug beyond its priority. We're completely stumped as to how to proceed on this one.

tim.plunkett’s picture

Assigned: Unassigned » tim.plunkett
Status: Reviewed & tested by the community » Needs work

Well, it still needs manual testing regardless, so not RTBC yet.

At DrupalCon, I'll try to find out about writing a test for this, but I suspect you are correct.

chx’s picture

I would recommend looking at ./core/modules/system/tests/https.php for faking a request. Can't see why similar can't be done for this to fake a breaking request.

tim.plunkett’s picture

Assigned: tim.plunkett » Unassigned
Issue tags: +Needs tests

There you have it!

TrevorBradley’s picture

That handles step 4 above, I'm still completely stumped as to how to tackle 1-3 in #64 above. The problem is *not* with making an http request to the server! Again, my apologies if I'm being naive or rude, but I fear that chx and tim.plunkett completely misunderstand the scale of what's required to solve the problem. How do I craft a test that ***moves the entire Drupal Directory*** including the test file itself, creates a new root .htaccess, and verifies that mod_rewrite is enabled? Even verifying that this is remotely possible would make me feel justified in investing the hours crafting such a test. Most of the test would need to be system calls. Is the OS that the testing server runs on Unix? Windows? I have no clue.

(And I fear that now this is flagged as "needs work/needs tests" again, it will remain in this state for another month or three. I'm about ready to consider this issue as "wont fix", patch manually with every release and just wait for Drupal 8 until some hero steps up and gives some clue as to how to proceed. I do not have sufficient knowledge on how to abuse the testing system to craft a test that is capable of moving the entire Drupal directory - moving the test file that is to be tested on, and then continuing that same test.)

I'm getting too frustrated with this issue... I'm going to have to put it aside for a few weeks. Kudos to m.stenta on a marvelous patch. I only hope it makes it into the 7.x branch someday.

chx’s picture

Trevor, why would you need to do any of that? Drupal does not know magically where it is or what htaccess rules happened, it simply reads variables in $_SERVER and you can fake it. Please help me understanding where I am wrong.

chx’s picture

Sorry above I mentioned (slightly) wrong filename -- under D7 this is http://api.drupal.org/api/drupal/modules!simpletest!tests!https.php/7 modules/simpletest/tests/https.php. However, what I said still stand: Drupal reads $_SERVER['SCRIPT_NAME'], $_GET['q'] and such to figure out the context.

TrevorBradley’s picture

Because as m.stenta pointed out in #55, the core fault is in the following line of request_path():

 $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/'));

Drupal does indeed magically know where it is - when it makes a call to dirname() to determine $base_path_len. The value of $base_path_len cannot be forged by simply altering $_SERVER - instead we need to alter the server itself.

Staring at this for longer I can imagine a test that would compare the values of ($_SERVER['SCRIPT_NAME'] and $_SERVER['REQUEST_URI'], but I suspect the test would not fail on a server that wasn't set up with this particular mod_rewrite .htaccess setup.

EDIT: Sorry, for some reason I thought dirname actually called the file system. Maybe this is solvable.

EDIT2: Test then becomes:

1) Overwrite $_SERVER['REQUEST_URI'] with a fixed value
2) Overwrite $_SERVER['SCRIPT_NAME'] with a fixed value
3) Call request_path() and see if $path is returned correctly.

There's not even a need to make an http call to the server, I think...

TrevorBradley’s picture

OK, progress. Here's the test... Now I just need to figure out how to wrap it in a SimpleTest.

$_SERVER['REQUEST_URI'] = '/node/1';
$_SERVER['SCRIPT_NAME'] = '/subdirectory/index.php';
return (request_path() == 'node/1');

Returns TRUE with the patch, FALSE without it.

modctek’s picture

I'm guessing we'll need to re-apply this patch at #55 if we update to the latest security release.

Update: or maybe not? Still testing...but I haven't had to re-apply the patch.

m.stenta’s picture

@modctek: I just tried the latest release and the problem still exists.

Attached are two patches: the first contains a test that demonstrate the issue. The second is the patch from #55 combined with the test to show that it fixes it.

Status: Needs review » Needs work
Issue tags: -Needs tests, -Needs manual testing

The last submitted patch, request-path-bootstrap-757506-76.patch, failed testing.

m.stenta’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
Issue tags: +Needs tests, +Needs manual testing

The last submitted patch, request-path-bootstrap-757506-76.patch, failed testing.

m.stenta’s picture

Status: Needs work » Needs review
FileSize
5.5 KB
3.19 KB

Oops. I forgot that $base_url needs to be set in settings.php for this to work. I added that to subdir_rewrite.php. Let's try this again...

Status: Needs review » Needs work

The last submitted patch, request-path-bootstrap-757506-80-complete.patch, failed testing.

m.stenta’s picture

Dang. It's passing on my local install. I must be missing something...

m.stenta’s picture

Hmm, just noticed this... according to the FAQ at http://drupal.org/project/testbot

"The testbot has clean URLs turned off by default (as does Drupal)"

I'm not sure if that is what's causing my test to fail... but it raises a good question. Can we write a test for this, if the issue is specific to sites with clean-urls?

Edit: Also, the third point in the FAQ:

"The testbot webroot is in a subdirectory (like http://drupaltestbot.osuosl.test/checkout/?q=admin)"

The test could also be failing because it is assuming that the subdirectory is being rewritten out, so that the site thinks that it's at http://drupaltestbot.osuosl.test/ (without the "checkout" subdir).

I'm open to ideas... is this issue testable with the current testbot setup?

m.stenta’s picture

Status: Needs work » Needs review
Issue tags: -Needs manual testing
FileSize
5.74 KB
3.43 KB

Ok, I set up my test site to match the testbost server in those two regards: 1) clean URLs disabled by default, and 2) the test site itself is installed in a subdirectory. Doing so caused by test to fail locally, which allowed me to debug further.

Enabling/disabling clean URLs didn't make a difference, so that's not the issue. After giving it more thought, this makes sense, because subdir_rewrite.php is essentially creating a clean URL in the $_SERVER['REQUEST_URI'] anyway... which is what ultimately get's used by request_path() to generate the path.

My test did fail after moving it to a subdirectory, though, which also made sense. I just needed to add some extra logic to the code that generates the $base_url, to better replicate what it would be set to in settings.php in a situation like that. Specifically, it includes the subdirectory that the test site is installed into now... and then also adds an additional "/sub" subdirectory for the purpose of this test.

Crossing my fingers and testing again...

TrevorBradley’s picture

Ironically,I'm sitting the SimpleTest session in the Pacific Northwest Drupal summit at this very moment trying to figure this out.

chx’s picture

You need to wrap comments at column 80 and "+// Set the $base_url to the HTTP_HOST, and tack on any existing subdirectory that the testing server might be using." is just factually incorrect, it's not the testing server you have a problem with but any Drupal in any subdirectory. The testing server is merely set up as the worst case scenario.

m.stenta’s picture

Thanks for the input, chx.

I wrapped the comments in subdir_rewrite.php that were longer than 80 characters, and changed the comment about the $base_url to simply "Build the $base_url from $_SERVER['HTTP_HOST'], including the subdirectory that Drupal is installed in (if any)." I also went through and cleaned up some of the other comments to make sure they were accurate and helpful.

Attached are the updated test and test+fix patches.

Can you see any other changes that should be made?

chx’s picture

Assigned: Unassigned » David_Rothstein
Issue tags: -Needs tests

I see one more problem: parse_url is now called twice extremely early. Can't we reuse this $parts = parse_url($base_url); from drupal_settings_initialize?

chx’s picture

Assigned: David_Rothstein » Unassigned
Issue tags: +Needs tests

Sorry, I was about to RTBC this, but not yet.

m.stenta’s picture

Ok, I created a new global variable called $base_url_parts, which stores the output of parse_url($base_url) in drupal_settings_initialize(). This global variable is then used in request_path() so that parse_url() doesn't need to be called twice.

Status: Needs review » Needs work

The last submitted patch, request-path-bootstrap-757506-90-test.patch, failed testing.

modctek’s picture

Just FYI, #55 still seems to be working fine with 7.17.

pdcrane’s picture

Spent hours banging my head against a wall... finally found this and patched #55.

Thank you everyone (and especially m.stenta) for your hard work!

AdrianB’s picture

I tried the patch in #55 and indeed it worked when I was using the webroot .htaccess from #55:

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

But I actually didn't need the patch at all if I instead used this in my webroot .htaccess:

RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
  RewriteRule ^$ drupal/index.php [L]
  RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
  RewriteCond %{DOCUMENT_ROOT}/drupal%{REQUEST_URI} -f
  RewriteRule .* drupal/$0 [L]
  RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule .* drupal/index.php?q=$0 [QSA]

This is the same as I used for Drupal 6. I honestly don't remember if every line is necessary any more (it was a long time since I created it by trial and error for Drupal 6), but it works as far as I know. Clean URL:s works and overlay works. Is there anything else that the patch in #55 solves that I could test?

dcam’s picture

http://drupal.org/node/1427826 contains instructions for updating the issue summary with the summary template.

The summary may need to be updated with information from comments.

geek-merlin’s picture

I use the patch in #55 with every subdir install.
However, install.php has still trouble with subdir installs and it seems importand to set $base_url AFTER installing.
See #1849444-3: mod_fcgid: stderr: PHP Fatal error: Call to undefined function node_types_rebuild() in common.inc on line 7379

larowlan’s picture

+++ b/modules/simpletest/tests/bootstrap.testundefined
@@ -321,6 +321,54 @@ class HookBootExitTestCase extends DrupalWebTestCase {
+ * See related issue: http://drupal.org/node/757506

+++ b/modules/simpletest/tests/subdir_rewrite.phpundefined
@@ -0,0 +1,44 @@
+ * See issue: http://drupal.org/node/757506

We don't normally reference issue links in comments other than to-dos.

jpvivere’s picture

Issue summary: View changes

I came across this very problem with the latest Drupal 7.36 and found only this page mentioning the problem. After some debugging, I chose not to implement the patch and keep Drupal in line with the official release. Instead, I played with the public root .htaccess file.

Just as the original poster indicated, when the URI gets passed to the Drupal sub-directory from the root's .htacess file, Drupal immediately clips off the beginning of the URI before processing--clipped by the same number of characters as is the sub-directory name. For example, when the Drupal sub-directory gets http://viveredesign.com/testimonials, it tries to process http://viveredesign.com/als since the sub-directory is 8 characters long. m.stenta above has already solved it with a patch, but it hasn't seemed to have made it in the Drupal core as of 7.36---perhaps it only affects a minority of people.

My .htaccess approach was to create 2 rewrite conditions/rules because all the support files (css, images, etc.) need the regular URI format working (e.g., viveredesign.com/sites/default/files....), but all the clean-url paths need to be fed to Drupal's URI processor in a way to avoid the problem. I.e., all URI paths must be fed to Drupal in the non-clean way (e.g., viveredesign.com/index.php?=portfolio). So one Apache rewrite handles the navigation URLs and the other allows the standard URIs to pass through (for CSS, images, etc.).

Here's what I found works (truncated to show just the essentials):

...
RewriteEngine on

# To avoid Drupal cutting off characters from beginning of URI when processing pages....
# Convert all non-direct requests to index.php?q= old-school non-clean format. 
# (QSA will ensure original queries are appended to end of URI, with ampersands, so for example, paging still works) 

RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteCond %{REQUEST_URI} !^/(sites|modules|misc)/.*
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /drupal_subdirectory/index.php?q=$1 [QSA,L]

# .... and send all the rest of the requests to the subdirectory, just like usual, so that images and files are accessed directly

RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteCond %{REQUEST_URI} !^/drupal_subdirectory/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /drupal_subdirectory/$1 [L]

# handle root URI requests
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteRule ^(/)?$ drupal_subdirectory/index.html [L]

This is similar to what others have posted above and on other pages and on web hosts' help pages, but I couldn't get those to work as-is. Hope this helps others.

Larzan’s picture

#99 by jpvivere was a lifesaver, after activating the clean urls i had a lot of non-specific problems with the page (token were not valid, strange behaviour on some actions.
But after using jpvivere's snippets everything worked perfectly.
I had already wasted a considerable amount of time with this one, thinking it was realted to the token module or the admin_menu module.
Thanks a lot :)

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 90: request-path-bootstrap-757506-90-complete.patch, failed testing.

geek-merlin’s picture

Status: Needs review » Needs work

geek-merlin’s picture

Patch flying in to check for green lights.

geek-merlin’s picture

OK, lights are green but i accidentally included some junk, so here's the correct patches.

Here the explanation:
* this patch #108 builds on last green-light patch #87 from m.stenta
* it implements chx's suggestion to re-use parse_url($base_url) result
* but unlike #90 it factors this out into a statically caching function, so it works whatever code path is called first

pleas test to finally get this RTBC.

The last submitted patch, 108: drupal-757506-108-request-path-TEST-ONLY.patch, failed testing.

geek-merlin’s picture

This all does its job very well but has a minor issue when $base_url has no path:
Notice: Undefined index: path in request_path() (line 2829 of /var/www/virtual/clsys/html/clsys/frutra2dev/git/docroot/includes/bootstrap.inc).
which is fixed canonically.

The last submitted patch, 110: drupal-757506-110-request-path-TEST-ONLY.patch, failed testing.

geek-merlin’s picture

geek-merlin’s picture

geek-merlin’s picture

Title: request_path incorrectly interprets the path in case of a RewriteRule in .htaccess and $base_url in settings.php » $base_url broken with .htaccess RewriteRule
Issue tags: -Needs tests

Simplifying title, test are green.

portulaca’s picture

I've applied the patch and all the links are now working correctly (without the "subfolder" in the link) except for the front page.

The front page forces the "/drupal" after the domain name and shows a Page not found (since there is no content with that path on the site).

If I comment out the $base_url in settings.php the "/drupal/" returns to all the links, but this time the front page is working correctly, showing the content it is supposed to show.

The site is multilingual, and I've applied the patch from https://www.drupal.org/project/drupal/issues/1826252 but it doesn't help.

Is there anything special that needs to be adjusted for the front page? What should the root .htaccess look like?