Apache rewrite for particular file requests - apache

I'm trying to setup Apache to rewrite particular file names when requested under a virtual host. The goal is to change certain branding elements based on the host header used (all of which have virtual host configs).
I had this working in nginx as per the example below
if ($host = "test.example.com") {
rewrite ^/images/file1.png$ /images/otherfile1.png;
rewrite ^/images/file2.png$ /images/differentfile2.png;
break;
}
For Apache I used the following config in the virtual hosts file, and confirmed the module is running, but it does not seem work (the original file1 is used).
<Directory "/opt/site/html/">
AllowOverride All
Options FollowSymLinks MultiViews
Require all granted
RewriteEngine On
RewriteBase /
RewriteRule ^/images/file1.png$ /images/otherfile1.png
RewriteRule ^/images/file2.png$ /images/differnetfile2.png
</Directory>
Any advice on what I'm missing to enable this rewrite would be greatly appreciated.

RewriteRule ^/images/file1.png$ /images/otherfile1.png
RewriteRule ^/images/file2.png$ /images/differnetfile2.png
These directives are inside a <Directory> container (inside a <VirtualHost>). In a directory context (as with .htaccess), the URL-path matched by the RewriteRule pattern does not start with a slash. So the above rules will not match. The directives should be like this instead:
RewriteRule ^images/file1\.png$ /images/otherfile1.png [L]
RewriteRule ^images/file2\.png$ /images/differnetfile2.png [L]
NB: Don't forget to backslash-escape literal dots in the regex and you should use the L flag here to stop further processing by the rewrite engine.
Alternatively, you can move these rules out of the <Directory> wrapper and into the <VirtualHost> container directly. In this context, the rules match against the full root-relative URL-path, starting with a slash (as you have written). But in a virtualhost context, the RewriteBase directive is not permitted so must be removed (you are not making use of this anyway).
Aside:
AllowOverride All
Options FollowSymLinks MultiViews
You are allowing .htaccess overrides (first directive). Note that if you do have an .htaccess file with mod_rewrite directives (RewriteRule etc.) then these will completely override the directives in the corresponding <Directory> container in the server config. You may want to explicitly disable .htaccess overrides, for example:
AllowOverride None
You've also enabled MultiViews - is that intentional? This basically enables extensionless URLs out-of-the-box (on everything) and can potentially conflict with mod_rewrite, so generally, this should be disabled. Simply remove it from the above rule to disable this, for example:
Options FollowSymLinks
RewriteBase /
You're not actually using this in the directives you've posted.

Related

.htaccess not working on SSL apache

Trying to fix this .htaccess, so it can work on a SSL apache server. Before it was hosted on another Linux server (http://) and was working without problems, but when uploading the files to another Linux server with apache and SSL (https://), it stopped working. The main function is to hide the .php extension...
HereĀ“s what I was using:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R,L,NC]
## To internally redirect /dir/foo to /dir/foo.php
RewriteCond %{REQUEST_FILENAME}.php -f [NC]
RewriteRule ^ %{REQUEST_URI}.php [L]
Thanks for your help!
So, .htaccess files may not be allowed, and by default on many systems they are not allowed. To see if .htaccess is allowed, make this your .htaccess:
BREAK IT!
That should be the only contents in your .htaccess. Attempt to load any page on your website, and if .htaccess usage is enabled, you would see "Internal Server Error" or possibly some other error, but you would not see your actual page.
If you do see the error, that's actually good and means .htaccess usage is enabled. If you don't see the error, it's likely that you will have to find your Apache .conf file and inside look for the line(s):
AllowOverride None
Change that to:
AllowOverride All
If after doing that you still can't use .htaccess, then there may be other apache related files that have "AllowOverride None". On that comes to mind is your virtual host file, and on my system that is located at /etc/apache2/sites-available/.
If you still have problems, check this out:
https://docs.bolt.cm/3.3/howto/making-sure-htaccess-works
Solution is for the issue, need to change in apache2.conf file after that it will works,
Change this file /etc/apache2/apache2.conf
update it same
OLD:
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
New Updated Code:
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
I had a similar problem. Apache 2.4.23 with .htaccess error 404 set up.
Using it with HTTP works fine; access it with HTTPS didn't work.
I seted AllowOverride All in the http.conf and error 404 wors well.

RewriteRule working on .htaccess but not httpd.conf

I'm trying to redirect all urls that have /__/ to /public/assets/ and got it working in .htaccess but not globally in httpd.conf
What it should do is re-write:
http://example.com/__/test.css
to
http://example.com/public/assets/test.css
So far I have this working for .htaccess:
RewriteRule ^(.*)/?__/(.*)$ $1/public/assets/$2 [L]
(Which might not be written properly but it's the only way I managed to make it work). If I put it in httpd.conf however, it doesn't work at all. I tried tweaking it, tried putting it inside <VirtualHost 127.0.0.1> and inside <Directory "c:/DEV/wamp/www/"> but it still won't work. Been losing 3 hours of time on this now and found plenty of examples on Stackoverflow/forums, but oddly none of them work for me..
EDIT:
Here are two examples of blocks I tried. [R] is to verify if the rule was working and redirecting:
<VirtualHost 127.0.0.1>
DocumentRoot "c:/DEV/wamp/www/"
<Directory "c:/DEV/wamp/www/">
Allow From All
RewriteEngine On
RewriteRule ^/(.*)?__/(.*)$ /$1public/assets/$2 [R]
</Directory>
</VirtualHost>
And this one:
<Directory "c:/DEV/wamp/www/">
Allow From All
RewriteEngine On
RewriteRule ^/(.*)?__/(.*)$ /$1public/assets/$2 [R]
</Directory>
EDIT2:
Tried selected edit from proposed answer, still cannot find the css files on the server.
<Directory "c:/DEV/wamp/www/">
Allow From All
RewriteEngine On
RewriteRule ^__/(.*)$ public/assets/$1 [L]
</Directory>
RewriteRule ^/(.*)?__/(.*)$
You've included a slash prefix on your RewriteRule pattern in the <Directory> container. This should be the same as in your .htaccess file, ie. no directory-prefix.
.htaccess files and <Directory> containers behave the same in this respect. Only when the directive is directly in the server config / VirtualHost container should the directory-prefix be included (but then it matches the URL-path, not the filesystem path, as it does in a .htaccess / Directory context).
If you put it in a <Directory> container then there should be no need to "tweak it".
I'm trying to redirect
Strictly speaking, this is an internal rewrite (as you have in your .htaccess file), rather than an external redirect.
/__/<file> to /public/assets/<file>
RewriteRule ^(.*)/?__/(.*)$ $1/public/assets/$2 [L]
This rewrite can be simplified, providing /__/ always occurs at the start of the URL-path. Try the following in either a .htaccess file or <Directory> container:
RewriteRule ^__/(.*)$ public/assets/$1 [L]
[EDIT] WARNING: mod_rewrite inheritance
If you are switching between testing .htaccess and <Directory> containers in your server config and wondering why the directives in the <Directory> container aren't doing anything then it's possible that the mod_rewrite directives in .htaccess are completely overriding the directives in the <Directory> container. This is the default behaviour. .htaccess directives will take priority and parent directives are not inherited by default.
Generally, if you are using <Directory> containers in the server config then you don't need .htaccess, so the easiest option is to simply disable them in your <Directory> container with AllowOverride None. So, the <Directory> container looks like:
<Directory "c:/DEV/wamp/www/">
Allow From All
AllowOverride None
RewriteEngine On
RewriteRule ^__/(.*)$ public/assets/$1 [L]
</Directory>
If you needed to have mod_rewrite directives in both .htaccess and a parent <Directory> container then you would need to explicitly enable mod_rewrite inheritance by placing the following directive in .htaccess:
RewriteOptions Inherit
If you are on Apache 2.4 then you have more options.
You can't simply disable the rewrite engine in .htaccess (ie. RewriteEngine Off) since that will also prevent the parent directives from being processed. If you simply remove the RewriteEngine directive from .htaccess then the RewriteEngine On directive in the <Directory> container will enable the rewrite engine but will result in the .htaccess directives overriding the parent again, so you are back to requiring the RewriteOptions Inherit directive.

How to use DAV and DirectoryIndex in Apache 2.4?

In my apache configuration I have a virtual host configured like this:
Alias /mediamanager /storage/files/mediamanager
<Directory /storage/files/mediamanager>
DirectoryIndex /mediaManagerIndex.php
DAV On
# ... And some authentication directives ... #
</Directory>
The idea is that someone can access the files both by a WebDAV-Client and also a simple web browser in which case some pretty directory view is generated by a PHP script.
That worked great in Apache 2.2, but recently I upgraded to Apache 2.4 and now it is broken. I highly suspect I I suffer from this bug which is already 2 years old and no fix in sight. The proposed workaround to add:
<Limit PROPFIND>
DirectoryIndex never-encounterable-file-name.html
</Limit>
Does not work for me. Probably because I still want to have a directory index. If I remove my DirectoryIndex altogether WebDAV works again (no index.html or similar files exists in this directory) but of course I loose the ability to use my PHP file as directory index. I tried to specify my DirectoryIndex in a <Limit GET> but this had no effect.
Is there any way to get both DAV and DirectoryIndex to work simultaneously in Apache 2.4 on Debian (if anyhow possible without changing the source code and recompiling)?
In order to fix this, disable directory indexing for the WebDAV site.
In your sites-available/site.conf file add DirectoryIndex disabled to the <Directory> declaration, like so:
<Directory /path/to/my/webdav/dir>
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Require all granted
DirectoryIndex disabled
</Directory>
Then just reload Apache and you will no longer have that issue:
sudo service apache2 reload
For me, the following configuration solved both problems:
WebDAV works again
directory indexing, if the user uses a web browser to access the repository
It works by manually implementing the directory-indexing feature with simple rewrite rules, which are applied only for the GET request method.
The following code has to be placed inside the server config or virtual host context in the apache configuration file.
# Turn off (automatic) Directory-Indexing
DirectoryIndex disabled
RewriteEngine On
# Rewrite rules for the root directory
RewriteCond "%{REQUEST_METHOD}" "(GET)"
RewriteRule "^/$" "/index.php" [L]
# Rewrite rules for other sub-directories
RewriteCond "%{REQUEST_METHOD}" "(GET)"
# The following line checks, if the index.php file exists
RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" "-f"
RewriteRule "^/(.*)/$" "/$1/index.php" [L]
Don't forget to reload Apache!
This is the solution I am currently using, located in a .htaccess file at the root of the directory tree used by the WebDav service. In this case I do not use PHP, only html files, but it can be easily adapted:
# Turn off automatic directory indexing
Options -Indexes
DirectoryIndex disabled
# Redirect directory requests to index.html, only for GET requests
RewriteEngine On
RewriteCond %{REQUEST_METHOD} "GET"
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ $1index.html [L]
In order to launch always the requested PHP file, just replace "index.html" on the last line by the PHP file name:
RewriteRule ^(.*)$ $1mediaManagerIndex.php [L]

mod_rewrite: redirect requests from localhost to remote server

I have a following scenario:
Remote server with some webapp running at http://remote/webapp
Local machine inside corporate network
Corporate proxy between them
Apache with mod_rewrite running on my local machine
I would like to have the mod_proxy rewrite every request like http://localhost/webapp?someparams into http://remote/webapp?someparams.
Currently I have the following httpd.conf:
DocumentRoot "C:/Apache2.2/htdocs"
<Directory />
RewriteEngine On
RewriteRule ^(.+) http://remote/$1
Options FollowSymLinks
AllowOverride All
Order deny,allow
Deny from all
</Directory>
Which results in mod_rewrite transforming http://localhost/webapp?someparams into http://remote/C:/Apache2.2/htdocs/webapp?someparams
How to configure mod_rewrite to handle it correctly?
Since it looks like you have access to vhost/server config, you should ditch mod_rewrite and just use mod_proxy:
ProxyPass /webapp http://remote/webapp
ProxyPassReverse /webapp http://remote/webapp
and get rid of the 2 mod_rewrite lines (which is redirecting, not proxying):
RewriteEngine On
RewriteRule ^(.+) http://remote/$1
Note that if you have cookies, you may need to reverse map their domains.using ProxyPassReverseCookieDomain.
Also:
The fact that windows absolute path appears in the URL is due to misconfiguration of the mod_rewrite and this is what I'm trying to avoid
This is not a misconfiguration with mod_rewrite. When you put rewrite rules inside a <Directory>, the filepath is used in the match instead of the URI-path. According to the mod_rewrite documentation
What is matched?
In VirtualHost context, The Pattern will initially be matched against the part of the URL after the hostname and port, and before the query string (e.g. "/app1/index.html").
In Directory and htaccess context, the Pattern will initially be matched against the filesystem path, after removing the prefix that lead the server to the current RewriteRule (e.g. "app1/index.html" or "index.html" depending on where the directives are defined).
Thank you Jon for inspiration, finally mod_proxy + mod_rewrite worked:
# Global context
RewriteEngine On
RewriteRule ^(.+) http://remote/$1 [P]
ProxyPassReverse / http://remote/
I know that this is a simplified and coarse solution, but works for my purpose.

URL rewriting doesn't work if web-site is accessed via alias directory

I have a web-site in the directory d:\www\mysite on my local computer. I installed WAMPServer and set up an alias directory mysite for my site.
So, for instance, http://localhost/mysite/static-resource.html correctly retrieves my file which is located in d:\www\mysite\static-resource.html.
My issue is with the URL rewriting in my .htaccess file:
RewriteEngine On
RewriteRule ^articles/(\d+) ./article.php?id=$1
When I try to access http://localhost/mysite/articles/1, I get this response:
Not Found
The requested URL /www/mysite/article.php was not found on this
server.
I can confirm that there exists a article.php file at d:\www\mysite\article.php.
In the past, I had the root of my site (d:\www\mysite) set up as the DocumentRoot of the Apache server (instead of c:\wamp\www which is the default), and in that scenario, my URL rewriting worked, so my current issue must be related to the fact that my site is "behind" an alias directory.
The contents of my mysite.conf file:
Alias /mysite/ "d:/www/mysite/"
<Directory "d:/www/mysite/">
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
Allow from all
</Directory>
I do not see a RewriteBase in your rewrite rules.
In your .htaccess, add a RewriteBase rule.
RewriteEngine On
RewriteBase /mysite/
RewriteRule ^articles/(\d+) ./article.php?id=$1
RewriteBase has to have /mysite/ because of your Alias /mysite/ "d:/www/mysite/"
If just http://localhost/mysite is accessed, It should return a not found on this server.
If you do not want this to happen, add another alias along with the above like this:
Alias /mysite "d:/www/mysite/"
or
Just this:
AliasMatch /mysite(/.*)? d:/www/mysite/$1
why a RewriteBase? from RewriteBase Directive Apache Docs:
The RewriteBase directive explicitly sets the base URL for per-directory rewrites. As you will see below, RewriteRule can be used in per-directory config files (.htaccess). In such a case, it will act locally, stripping the local directory prefix before processing, and applying rewrite rules only to the remainder. When processing is complete, the prefix is automatically added back to the path. The default setting is; RewriteBase physical-directory-path
When a substitution occurs for a new URL, this module has to re-inject the URL into the server processing. To be able to do this it needs to know what the corresponding URL-prefix or URL-base is. By default this prefix is the corresponding filepath itself. However, for most websites, URLs are NOT directly related to physical filename paths, so this assumption will often be wrong! Therefore, you can use the RewriteBase directive to specify the correct URL-prefix.
Example from RewriteBase Directive Apache Docs:
#
# /abc/def/.htaccess -- per-dir config file for directory /abc/def
# Remember: /abc/def is the physical path of /xyz, i.e., the server
# has a 'Alias /xyz /abc/def' directive e.g.
#
RewriteEngine On
# let the server know that we were reached via /xyz and not
# via the physical path prefix /abc/def
RewriteBase /xyz
# now the rewriting rules
RewriteRule ^oldstuff\.html$ newstuff.html