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.
Related
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.
There are some PHP files on an external drive which is mapped to the Z: drive on a Windows 10 machine. This code is in the httpd-vhosts.conf Apache file:
<VirtualHost *:8080>
DocumentRoot "Z:/files/xampp/htdocs"
<Directory "Z:/files/xampp/htdocs">
Options Indexes
Require all granted
</Directory>
</VirtualHost>
The task at hand is to allow .htaccess overrides for a file path within the path shown above. In the httpd.conf file the rewrite module is enabled. That line looks like this: LoadModule rewrite_module modules/mod_rewrite.so. I tried adding this code to the httpd.conf file:
<Directory "Z:/files/xampp/htdocs/miscellaneous/WebServiceExamples">
AllowOverride All
</Directory>
The Apache web server was stopped and restarted after making these changes. The code in .htaccess looks like this:
<IfModule mod_rewrite.c>
# turn rewrite engine on
Options +FollowSymlinks
RewriteEngine on
# map neat URL to internal URL
RewriteRule ^mobile/list/$ RestController.php?view=all [nc,qsa]
RewriteRule ^mobile/show/([0-9]+)/$ RestController.php?view=single&id=$1 [nc,qsa]
</IfModule>
However, when a URL that should be handled by the rewrite rule in the .htaccess file is entered in the Chrome address bar the result is an Object not found! Error 404. Where did I go astray?
EDIT:
Another thing I tried was putting httpd.conf back to its original state, then modifying httpd-vhosts.conf as follows:
<VirtualHost *:8080>
DocumentRoot "Z:/files/xampp/htdocs"
<Directory "Z:/files/xampp/htdocs">
Options Indexes
Require all granted
</Directory>
<Directory "Z:/files/xampp/htdocs/miscellaneous/WebServiceExamples">
AllowOverride All
</Directory>
</VirtualHost>
After stopping and restarting the Apache web server, the result is still the same as before:
Object not found! Error 404.
Figured this out. The configuration files were left in the state as described in the Edit section in the original post. The Troubleshooting section in this link was a helpful guide for determining that the configuration files were set up correctly.
This was entered as the URL in Chrome's address bar: http://localhost:8080/miscellaneous/WebServiceExamples/SimpleRestfulWebService/mobile/list. Notice there is no trailing forward slash. The rewrite rule was in .htaccess was written in such a way that made a trailing forward slash mandatory. When the rewrite rule lines were modified to make the trailing slash optional, then it worked fine. Here are the modified rewrite rules:
RewriteRule ^mobile/list/?$ RestController.php?view=all [nc,qsa]
RewriteRule ^mobile/show/([0-9]+)/?$ RestController.php?view=single&id=$1 [nc,qsa]
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.
I'm trying to configure apache to redirect the requests containing only hostname (domain) to another path.
I found the following directives useful, but as long as those are enclosed in VirtualHost, put in site_available folder (/etc/apache2/) and enabled as a separate site (with a2ensite command).
<VirtualHost *:80>
ServerName myserver:80
WSGIScriptAlias / /var/path/to/myproject/myproject.wsgi
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/?$
RewriteRule ^(.*)$ /path/path [R=301,L]
</VirtualHost>
Note that only Rewrite* directives don't work. The alias to my Python project works fine.
Morover, I found out that if I disable other virtual host(s) (000-default) with a2dissite command and put the directives mentioned above (without VirtualHost) to httpd.conf file everything (including the Rewrite* rules) work.
So, I am in doubt why I couldn't get this done in simple server config context, and what is the solution?
The reason why it appears that the Rewrite* directives do not work in the server configuration and need to be declared inside the VirtualHost is because (from the RewriteEngine documentation):
[...] rewrite configurations are not inherited by virtual hosts. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use rewrite rules.
To change this behaviour, you can set RewriteOptions to something InheritDownBefore or similar. You then still need to have a RewriteEngine On on each VirtualHost but at least you won't need to copy the rewrite rules on each one.
So, taking your code example, this should work:
RewriteEngine On
RewriteOptions InheritDownBefore
RewriteCond %{REQUEST_URI} ^/?$
RewriteRule ^(.*)$ /path/path [R=301,L]
<VirtualHost *:80>
ServerName myserver:80
WSGIScriptAlias / /var/path/to/myproject/myproject.wsgi
RewriteEngine On
</VirtualHost>
I just made a subdomain on my webside mainly becouse i want a spesific address to it.
Lets say my website is : http://website.com
And my subdomain is http://sub.website.com with its main folder in /home/username/public_html/sub/
When i enter the subdomain address the address suddently changes to http//website.com/sub/
how can i keep the subdomain address?
EDIT for Dennis:
i have a rule that directs all http://www.website.com to http://website.com
I use
RewriteEngine on
Redirect to non-www
RewriteCond %{HTTP_HOST} !^(website\.com)?$
RewriteRule (.*) http://website.com/$1 [R=301,L]
even if i comment out this the address still changes to
http://website.com/sub/
Best of regards,
Alexander
I would imagine something like this would work (not tested):
Options FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} !^website\.com
RewriteCond %{HTTP_HOST} ^([^.]+)
RewriteRule \?cat_id=([0-9]+)&photo_id=([0-9]+) http://website.com/$1/$2/
RewriteRule ^/(.*)/(.*)/ /%1.php?cat_id=$1&photo_id=$2 [P]
Note: according to the documentation, Options FollowSymLinks needs to
be an option you can override to get the rewrite to work.
The first RewriteCond will ensure the "webiste.com" host is not rewritten (but
domains like sub.website.com will). The second one matches anything
up to the first dot of the hostname. Both of these must succeed and if so the host
part is accessible in %1.
The first RewriteRule rewrites the args to the php script to the directory paths
(a change seen on URL on the browser). The next RewriteRule uses the [P]
flag to proxy any requests of the form /xx/yy/ to %1.php (our remembered host name)
with the args passed to the php script.
As I've stated, this is not tested, but hopefully it will get you "in the right direction".
EDIT: removed the [R] from the first rewrite rule.
Another solution is to have a Virtualhost dedicated for your subdomain (that should already be the case, if not you'll get a lot of problems) and to make this VirtualHost ignore .htaccess instructions of the master domain. You should really try to keep your subdomain configuration independant of the master domain domain configuration.
Let's say your documentRoot in the subdomain VH is /home/username/public_html/sub/, when Apache serve the index.php or index.html file or anything else in this directoy it performs a recursive search of all .htaccess in /home/username/public_html/sub/, /home/username/public_html/, /home/username/, /home/ and /. So the rules defined in your master domain (I think it's in /home/username/public_html/) are applied.
You can tell this subdomain VirtualHost to ignore all .htaccess files which are before the VH DocumentRoot by adding:
<Directory />
AllowOverride None
</Directory>
<Directory /home/username/public_html/sub/>
AllowOverride All
</Directory>
You could even remove the AllowOverride All, remove all .htaccess and put the things you have in the .htaccess of your subdomain (if you have one) directly in the <Directory /home/username/public_html/sub/> section, same effect without having Apache searching for configuration parts on the filesystem (so faster).