I'm moving an old site from apache 2.2 to 2.4
I've got a vhost.conf file that contains the following rewriterule:
RewriteRule ^/news/[0-9]{4}/[A-za-z]{3}/([0-9a-zA-Z-]*)/([0-9]{4})([0-9]{6})/?$ "/news/article.cfm?article_id=$3&urltitle=$1&clk=$2" [NE,L]
So I'm trying to turn this url:
https://example.com/news/2016/Feb/Article-Title/0025012345
into this:
https://example.com/news/article.cfm?article_id=012345&urltitle=Article-Title&clk=0025
Depending on what I put in the 2nd part of the RewriteRule I get the following:
"https://example.com/news/article.cfm?article_id=$3&urltitle=$1&clk=$2" this works fine but I don't want to specify the hostname as it gets used on dev/staging/live servers, so the URLs change
"/news/article.cfm?article_id=$3&urltitle=$1&clk=$2" this throws a 404 which shows up in the access_log
"news/article.cfm?article_id=$3&urltitle=$1&clk=$2" this throws a 503 which shows up in the access_log
So I know I'm correctly identifying the URL in the first part of the rule and grabbing the correct components with my regex, as specifying the full domain name shows the correct URL manipulation.
I'm completely failing to do a relative redirect though, and I'm certain this rule works in Apache 2.2
I'm using the following software:
CentOS Linux release 7.7.1908 (Core)
Server version: Apache/2.4.6 (CentOS)
Server built: Aug 8 2019 11:41:18
Obviosuly, the answer is in the manual... which I should have read in more detail:
https://httpd.apache.org/docs/2.4/rewrite/remapping.html#old-to-new
Assume we have recently renamed the page foo.html to bar.html and now want to provide the old URL for backward compatibility. However, we want that users of the old URL even not recognize that the pages was renamed - that is, we don't want the address to change in their browser.
RewriteEngine on
RewriteRule "^/foo\.html$" "/bar.html" [PT]
The key thing here being the [PT], that fixed it for me:
RewriteRule ^/news/[0-9]{4}/[A-za-z]{3}/([0-9a-zA-Z-]*)/([0-9]{4})([0-9]{6})/?$ "/news/article.cfm?article_id=$3&urltitle=$1&clk=$2" [PT,NE,L]
Related
I have the following excerpt in my .htaccess file:
RewriteEngine On
# Whether RewriteBase is commented does not appear to have an impact on my problem
# RewriteBase /
RewriteRule ^admin/(.*) members/$1 [L]
The idea is that the pages in /admin load from the /members directory, since certain features are duplicated between them, so that I don't have to duplicate my code. (There are other directives in the file that are related to a CMS system, and those are working as expected.)
On the current Apache 2.2 server, everything works fine. My client's webhost wants to upgrade to a server with Apache 2.4, and on the test server the rewrite rule fails. Instead of loading the page, it just displays "File not found."
All other rules are executed as expected, it's just that one that fails. I have tried adding/removing / characters and removing [L] from the rule, it always fails. I tried adding [R] to send the redirect to the browser, but even that failed. But if I change the url to the same filename but in the members directory, then the file loads successfully.
Being able to change one directory name to another seems like a pretty basic function of mod_rewrite. What am I missing?
I'm using an Apache RewriteMap to permanently redirect 60 or so urls. In one development environment, the below configuration works flawlessly while in another development environment it doesn't work at all. Most notably, the last RewriteCond never passes and unfortunately the logging options I've attempted are no help. With LogLevel debug rewrite:trace8, I can see that the RewriteCond just before the map is receiving the expected input, but the map nonetheless returns no match:
[Thu Apr 19 19:35:19.109789 2018] [rewrite:trace4] [pid 11188] mod_rewrite.c(470): [client 127.0.0.1:62369] 127.0.0.1 - - [server.dev/sid#7f7719da0d50][rid#7f7719fc8000/initial] [perdir /html/path/] RewriteCond: input='/help_center/help_center.php?' pattern='^/?(.*[^\\?])\\??/?$' => matched
[Thu Apr 19 19:35:19.109793 2018] [rewrite:trace4] [pid 11188] mod_rewrite.c(470): [client 127.0.0.1:62369] 127.0.0.1 - - [server.dev/sid#7f7719da0d50][rid#7f7719fc8000/initial] [perdir /html/path/] RewriteCond: input='NOTFOUND' pattern='!NOTFOUND' [NC] => not-matched
For debugging purposes I've simplified things to pass a constant key into the map, but the map nonetheless returns no substitute value. I've also tried simplifying the map file, adding all the possible variations of a key it could receive (with and without leading/trailing slashes and ?). I've tried renaming the map file and extension, renaming the map itself, moving the map file outside of the public directory, all with no change in results. The map file is readable as is the directory it's in, Apache starts up error-free with the config and yes I've been restarting it when testing config changes.
What's left to try? Both systems run CentOS 7, Apache 2.4, one works and one doesn't. Configs below
Apache server-level config declaring map
RewriteMap help_center txt:/path/to/rewritemap/help_center.map
.htaccess
RewriteEngine on
RewriteCond %{REQUEST_URI} !(\.(js|css|less|png|swf|flv|jpg|svg|ico))$
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} ^/?(.*[^\?])\??/?$
RewriteCond ${help_center:%1|NOTFOUND} !NOTFOUND [NC]
RewriteRule ^.*$ /${help_center:%1}/ [QSD,L,NC,R=301]
Abbreviated contents of help_center.map
help_center/help_center.php help-center
help_center/help_center.php?1_7_q-1 help-center/article/authorized-dealer
pages/appliance_installation help-center/article/installation-services
UPDATE
After 6 hours of debugging, I've finally been able to get the RewriteMap to match. By moving the RewriteMap directive to the <VirtualHost _default_:443> scope of /etc/conf.d/ssl.conf, urls are rewriting as expected.
Why is this the case?
The config between these two environments is very similar with the exception of virtual hosting. Both environments run SSL and redirect all requests to the SSL site. The environment that works is configured without a name based virtual host config (i.e. one site for the server) while the environment that didn't work is running name based virtual hosting. I have a single hypothesis related to this:
While I'd expect the root directive to apply to the default site and all virtual sites (including SSL), perhaps the RewriteMap directive must be virtual host scoped to be referenced by a virtual host. Not sure this makes sense, but I couldn't find any documentation to clarify. After testing, turning off NameVirtualHost nothing changes :/
Related: It seems that referencing a non-existent RewriteMap logs no error. Perhaps it was buried while I had debug logging turned on, but is there a config for logging RewriteMap reference errors? That would have help narrow my debugging much sooner.
Finally, for examining parsed Apache config run this from command line: httpd -DDUMP_CONFIG -k start or to view in vi httpd -DDUMP_CONFIG -k start | vi -. I was able to use this to confirm that my RewriteMap directive was being loaded despite it still not matching.
I'm not entirely sure this should qualify as an answer, but I THINK this is what has made it work: Remove the QSD argument and append a ? to manually discard it. This change was made because we have a server running 2.2 that would error out entirely (rather than not match) and it seems that a side effect is that our 2.4 servers are now matching. I'm sure not it's Voodoo, but unfortunately I can't explain it with confidence.
## QSD not available in apache 2.2, add a ? to the end of the rewrite to discard
RewriteRule ^.*$ /${help_center:%1}/? [L,NC,R=301]
I have a .htaccess rewrite condition / rule, which works fine on my local, which is OSX mavericks, running apache Apache/2.2.26, but when I deploy to my production server it no longer works, running Apache/2.2.22 (Debian).
this is the condition:
RewriteCond %{REQUEST_URI} ^([a-z]{2})/sitemap.xml$
RewriteRule ^([a-z]{2})/sitemap.xml /sitemaps/$1_sitemap.xml [NC,L]
As you can see, I have a directory for sitemaps in the base directory, and this being a multi-lingual site, I have a sitemap for each language. However I cannot simply create a directory like /en/sitemap.xml for each one, as this effects how the framework deals with the request, as apache trys to serve the directory, rather than passing it to the index file to be handled.
So i create this rewrite condition, which should rewrite the request /en/sitemap.xml to /sitemaps/en_sitemap.xml and as stated, this works great locally, but not on my Debian server, it never matches that regex from the request, it just moves onto the next one and passes the request to the index.php file.. which is wrong!
Any advice / help would be great, I cannot find anything in apache docs referring to mod_rewrite under these 2 versions that may be different.
Thanks
That's because %{REQUEST_URI} value always begins with a leading slash.
Also, your condition is useless since your RewriteRule does the same.
This code should work as expected on both sides
RewriteRule ^([a-z]{2})/sitemap\.xml$ /sitemaps/$1_sitemap.xml [L]
I have a joomla site which starts with an index.php file that delivers the pages.
However I want to include a non-php page that would be delivered with priority if someone includes it when they type the URL in their browser.
For example. If the page is bananas.html and the person types www.domainname.com/bananas I want that page to come up instead of any Joomla page.
I also want the "html" removed, so the page shows up as domainname.com/bananas (instead of www.domainname.com/bananas.html
Of course if they enter http://www.domain.com by itself, the joomla site would appear as usual.
I have only one page that I want this to happen.
There was a similar question here on stackoverflow which should be helpful to refer to:
Server page priorities between index.php or index.html
It is an apache site and I have ftp access to the web root. So I can modify the htacess file. The site is on a university server and I can have the IT person make any changes to any server files
Thanks for any help on this,
Rowby
Here is info about the site and the server:
PHP Built On Linux 2.6.32-431.11.2.el6.i686 #1 SMP Mon Mar 3 13:33:00 EST 2014 i686
Database Version 5.5.38-MariaDB-log
Database Collation latin1_swedish_ci
PHP Version 5.3.3
Web Server Apache/2.2.15 (Red Hat)
WebServer to PHP Interface apache2handler
Joomla! Version Joomla! 3.1.5 Stable [ Ember ] 01-August-2013 14:00 GMT
Joomla! Platform Version Joomla Platform 12.2.0 Stable [ Neil Armstrong ] 21-September-2012 00:00 GMT
User Agent Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.3
Use Rewrite should do it:
RewriteRule ^bananas/(\d+)*$ ./bananas.html
DirectoryIndex is not of much use here, because you want to load joomla unless you have a very good reason not to load it. That is, when the user requests a file that is present on the server. You can accomplish this with mod_rewrite (docs).
The following rule checks if the current requested file does not exist, then checks if the current requested file with .html appended does exist. If both of those are true, it internally rewrites the request to that file. This means that in the browser you'll see http://example.com/bananas and it will load http://example.com/bananas.html instead. If you request http://example.com/, it will check http://example.com/.html, which does not exist, which causes this rule to not match. Add this rule before any other rule you might have in the .htaccess file in your www-root.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.html -f
RewriteRule ^ %{REQUEST_URI}.html [L]
I am a newbie to ubuntu and apache. Can someone tell me how I could direct to
www.mysite.com/drupal6
when user address www.mysite.com?
Thanks a lot.
Cheers.
If you are running Apache and Ubuntu, there is actually a really easy way to force this redirect using a simple php script.
Create an index.php file in the root of your server and paste the following code into it
<?php header("location: drupal6/") ?>
This will cause the site to auto-redirect to the drupal6 folder whenever it is visited.
This should work. Create a file in the root folder of your server called .htaccess - the dot at the beginning is very important as this helps the server identify the file as a hidden / system config file.
Open the file and paste the following lines of code in :
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ www.mysite.com/drupal6/$1 [R,L]
This should force all traffic to the server to redirect to your custom folder.
A brief explanation of the .htaccess code
If you want rewrites to work, you have to enable the Rewrite Engine and tell the server to follow symlinks.
The second section establishes the rule - specifically applying it to all traffic on the standard web port of 80.
The final line tells the server to grab everything after the URL and append it to the new address (mysite.com/drupal6).
There's a lot more you can do with .htaccess files but you really need to Google for good examples to test out.
Look at Apache's mod_rewrite documentation. You will need a RewriteRule in your apache configuration at the minimum, you may also need RewriteCond's to define when the RewriteRule is used.
Your rewrite pattern will be rewriting the REQUEST_URI with something from: ^/$ to: /drupal6. The ^ and $ are essential to prevent Apache getting into an infinite loop while rewriting the base URI by only matching "/" and not "/anything-else".
I assume you're on a recent version of Ubuntu and Apache? If so, see the Apache 2.2 documentation on mod_rewrite.