I attempted to create a Drupal installation on an internal host, with a base_url (i.e. "subdirectory" type) Apache2 reverse proxy publishing it.
So I had a reverse proxy 'www.example.com/drupal' pointing to a Drupal instance at localhost with base_url 'www.example.com/drupal' set.
During installation, I get the infamous #481758: Fatal error: Call to undefined function field_attach_load() in includes/entity.inc on line 321 during install
However, in this case, it's an easily isolated issue:
Drupal installation and bootstrap rely on $_SERVER['REQUEST_URI'] to be authoritative. In my setup, it isn't, because $_SERVER['REQUEST_URI'] does not include the base_url, because the internal host isn't (and shouldn't really need to be?) aware of it. I'm not sure if I'm going to be told this is a configuration issue, not a bug, but really why should the internal server need to be aware of the base url if it's already hardcoded into settings.php? That should be authoritative, right?
drupal-7.33/includes/install.inc:225: $uri = preg_replace("/\?.*/", '', $_SERVER['REQUEST_URI']);
drupal-7.33/includes/bootstrap.inc:673: // When clean URLs are enabled, emulate ?q=foo/bar using REQUEST_URI. It is
drupal-7.33/includes/bootstrap.inc:1621: * Returns the equivalent of Apache's $_SERVER['REQUEST_URI'] variable.
drupal-7.33/includes/bootstrap.inc:1623: * Because $_SERVER['REQUEST_URI'] is only available on Apache, we generate an
drupal-7.33/includes/bootstrap.inc:1627: if (isset($_SERVER['REQUEST_URI'])) {
drupal-7.33/includes/bootstrap.inc:1628: $uri = $_SERVER['REQUEST_URI'];
drupal-7.33/includes/bootstrap.inc:2819: elseif (isset($_SERVER['REQUEST_URI'])) {
drupal-7.33/includes/bootstrap.inc:2821: // Extract the path from REQUEST_URI.
drupal-7.33/includes/bootstrap.inc:2822: $request_path = strtok($_SERVER['REQUEST_URI'], '?');
drupal-7.33/includes/bootstrap.inc:2828: // $_SERVER['REQUEST_URI'] even when it wasn't provided in the URL (some
drupal-7.33/.htaccess:94: # RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
drupal-7.33/.htaccess:100: # RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [L,R=301]
drupal-7.33/.htaccess:116: RewriteCond %{REQUEST_URI} !=/favicon.ico
drupal-7.33/scripts/dump-database-d6.sh:23:$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
drupal-7.33/scripts/generate-d6-content.sh:23:$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
drupal-7.33/scripts/drupal.sh:67:$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
drupal-7.33/scripts/drupal.sh:118: $_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = $path['path'];
drupal-7.33/scripts/generate-d7-content.sh:25:$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
drupal-7.33/scripts/dump-database-d7.sh:23:$_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/';
drupal-7.33/scripts/run-tests.sh:289: $_SERVER['REQUEST_URI'] = $path .'/';I could get Drupal to install by hacking core with something like this wrapper around $_SERVER['REQUEST_URI']:
function apache2_request_uri($request_uri) {
if ($request_uri && isset($GLOBALS['base_url'])) {
$base_path = parse_url($GLOBALS['base_url'], PHP_URL_PATH);
if ($base_path && 0 !== strpos($request_uri, $base_path)) {
return $base_path . $request_uri;
}
}
return $request_uri;
}
This fixes the issue, for me, with Apache2, but is unlikely to address the problem with other web servers, so I'm not sure a patch would be accepted? Can an issue be fixed just for a particular web server?
Comments
Comment #1
lightsurge commentedI've discovered that although it's relatively easy to get an existing installation running as above by altering request_uri(), this doesn't work for a new installation.
Below is as far as I got at a function that would work during install, and it's getting so messy I think I'm going to have to give up on trying to get Drupal to install itself into in this type of setup, and just copy a basic non-base-url existing installation each time, then adding the base_url and patching request_uri() function to get it to work.
Comment #2
andypost1)
drupal_settings_initialize()uses$base_urlto be used for URL construction2) forms, dblog are bound to
request_uri() uses $_SERVER['REQUEST_URI']- to get current page addressSo here's inconsistency!
Quick solution is to populate
$_SERVER['REQUEST_URI']according$base_urlwhen definedComment #3
gaele commentedSo the proxy is listening to http://www.example.com/drupal,
the Drupal instance is at http://internal.example.com,
and its $base_url is set at http://www.example.com/drupal.
This will fail on forms where the #action is not set, like the user login page or the search box, or in dblog. There request_uri() is used and $base_url is ignored, resulting in /user instead of /drupal/user:
This seems to be still present in D8:
Comment #4
ivanstegic commentedMaking a note here that $base_url was removed from settings.php in a recent commit
Comment #6
catchClosing this as a duplicate of #2753591: Fix mismatch of $base_url with Symfony request object see you over there!
Comment #7
catchComment #8
xjm