У меня есть старый сайт (Tomcat), который раньше назывался host.domain и недавно развернул сайт Drupal. Новый сервер Drupal теперь называется host.domain, а старый сервер Tomcat - legacy.domain. Большая часть иерархии реплицирована в Drupal, поэтому закладки и результаты поисковых систем должны по-прежнему работать: запросите host.domain / dir / page.jsp, и Drupal обрежет .jsp и будет искать узел с именем dir / page. Некоторый контент еще не был перенесен, поэтому я использую модуль Drupal «Перенаправляет 404» для проверки содержимого старого сервера перед возвратом 404: request host.domain / legacy / oldpage.jsp, Drupal ищет устаревший Узел / oldpage, не находит его, пробует legacy.domain / legacy / oldpage.jsp, находит его и прозрачно передает контент в браузер с помощью drupal_http_request () - URL-адрес клиента даже не меняется. Эта часть отлично работает.
Проблема в файлах .js и .css - по какой-то причине запрос host.domain / legacy / file.js или file.css не вызовет обработку Drupal 404, поэтому Drupal никогда не спрашивает legacy.domain, получил ли он файл . Вместо этого 404 переходит к Apache и отображает Apache 404 (не Drupal или Tomcat). Это означает, что контент на legacy.domain, обслуживаемый Drupal на host.domain, если он включает локальный css или js, не получит эти стили или поведение.
На мой взгляд, у меня есть три варианта:
Думаю, я мог бы также просмотреть весь контент на старом сервере Tomcat и заменить все относительные включения абсолютными, используя имя legacy.domain, но я уже пытаюсь переместить этот контент выключен этот хост, и я действительно не хочу вкладывать усилия в файлы, которые скоро будут заменены - я просто хочу, чтобы они работали правильно, пока я не смогу их перенести. Есть ли у кого-нибудь советы или руководства по реализации варианта 2 или 3?
Конфигурация Apache - это стандартный Ubuntu 12.04.3 LTS. .Htaccess в каталоге Drupal:
# Protect files and directories from prying eyes.
<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php
)?|xtmpl)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|
^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig\.save)$">
Order allow,deny
</FilesMatch>
# Don't show directory listings for URLs which map to a directory.
Options -Indexes
# Follow symbolic links in this directory.
Options +FollowSymLinks
# Make Drupal handle any 404 errors.
ErrorDocument 404 /index.php
# Set the default handler.
DirectoryIndex index.php index.html index.htm
# Override PHP settings that cannot be changed at runtime. See
# sites/default/default.settings.php and drupal_environment_initialize() in
# includes/bootstrap.inc for settings that can be changed at runtime.
# PHP 5, Apache 1 and 2.
<IfModule mod_php5.c>
php_flag magic_quotes_gpc off
php_flag magic_quotes_sybase off
php_flag register_globals off
php_flag session.auto_start off
php_value mbstring.http_input pass
php_value mbstring.http_output pass
php_flag mbstring.encoding_translation off
</IfModule>
# Requires mod_expires to be enabled.
<IfModule mod_expires.c>
# Enable expirations.
ExpiresActive On
# Cache all files for 2 weeks after access (A).
ExpiresDefault A1209600
<FilesMatch \.php$>
# Do not allow PHP scripts to be cached unless they explicitly send cache
# headers themselves. Otherwise all scripts would have to overwrite the
# headers set by mod_expires if they want another caching behavior. This may
# fail if an error occurs early in the bootstrap process, and it may cause
# problems if a non-Drupal PHP file is installed in a subdirectory.
ExpiresActive Off
</FilesMatch>
</IfModule>
# Various rewrite rules.
<IfModule mod_rewrite.c>
RewriteEngine on
# This forces all drupal links to end in a trailing slash.
# Companion rules to trailing slash module.
# https://drupal.org/project/trailing_slash
RewriteBase /
RewriteCond %{REQUEST_METHOD} !=post [NC]
RewriteRule ^(.*(?:^|/)[^/\.]+)$ $1/ [L,R=301]
# Set "protossl" to "s" if we were accessed via https://. This is used later
# if you enable "www." stripping or enforcement, in order to ensure that
# you don't bounce between http and https.
RewriteRule ^ - [E=protossl]
RewriteCond %{HTTPS} on
RewriteRule ^ - [E=protossl:s]
# Make sure Authorization HTTP header is available to PHP
# even when running as CGI or FastCGI.
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Block access to "hidden" directories whose names begin with a period.
RewriteRule "(^|/)\." - [F]
# Pass all requests not referring directly to files in the filesystem to
# index.php. Clean URLs are handled in drupal_environment_initialize().
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]
# Rules to correctly serve gzip compressed CSS and JS files.
# Requires both mod_rewrite and mod_headers to be enabled.
<IfModule mod_headers.c>
# Serve gzip compressed CSS files if they exist and the client accepts gzip.
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule ^(.*)\.css $1\.css\.gz [QSA]
# Serve gzip compressed JS files if they exist and the client accepts gzip.
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule ^(.*)\.js $1\.js\.gz [QSA]
# Serve correct content types, and prevent mod_deflate double gzip.
RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1]
RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1]
<FilesMatch "(\.js\.gz|\.css\.gz)$">
# Serve correct encoding type.
Header set Content-Encoding gzip
# Force proxies to cache gzipped & non-gzipped css/js files separately.
Header append Vary Accept-Encoding
</FilesMatch>
</IfModule>
</IfModule>
ОБНОВИТЬ
Согласно рекомендации Шейна Мэддена ниже, я добавил это в начало раздела mod_rewrite корневого файла .htaccess:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} \.(css|js)$
RewriteRule ^(.*)$ http://legacy.domain/$1 [L]
Это сработает, если я прошу host.domain / oldfile.css: даже если oldfile.css не существует на устаревшем хосте, я получаю Tomcat 404, поэтому я знаю, что перезапись работает. Проблема заключается в каталогах, которых нет, в несуществующих каталогах.
Если у меня есть файл в устаревшей системе:
http://legacy.domain/root.css
и спроси об этом в
http://host.domain/root.css
файл появится, потому что он соответствует трем правилам RewriteCond. Однако, если я попрошу
http://host.domain/long/path/to/file.css
то я получаю Apache (не Tomcat) 404 с записью в error.log:
File does not exist: /var/www/long
Похоже, что правило перезаписи вступает в силу только в том случае, если запрошенный документ находится (или будет) в том же каталоге, что и .htaccess, содержащий это правило. Если запрошенный файл находится внутри каталога, каталог вызывает ошибку 404, которая не соответствует условиям, потому что не заканчивается на .css или .js, и Apache сразу же прекращает обработку. Есть ли способ применить правило для любой 404, независимо от того, насколько далеко он может находиться в иерархии каталогов, которая не существует локально?
Как насчет прямого проксирования файлов css и js, которые не существуют в файловой системе, поскольку все файлы для сайта drupal должны работать с реальными файлами в /sites
каталог?
В рамках <Directory>
блок для вашей установки Drupal, примерно так:
RewriteCond %{REQUEST_FILENAME} \.(css|js)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ http://proxy-target/$1 [P,L]
Редактировать:
Поскольку отображение файловой системы задыхается до того, как оно может проверить существование, давайте вместо этого выполним проверку без необходимости отображения файловой системы.
Поместите это в свой <VirtualHost>
блокировать напрямую (или в основной конфигурации сервера, если вы не используете виртуальные хосты):
RewriteCond %{REQUEST_URI} \.(css|js)$
RewriteCond /path/to/your/docroot%{REQUEST_URI} !-f
RewriteRule ^/(.*)$ http://proxy-target/$1 [P,L]