Apache rewrite rule - apache

I want to redirect "http://localhost/b.html" --> "http://localhost/a.html"
I tried RewriteRule for that. But somehow it is not working for me.
I am using apache2 and my httpd.conf contains:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule rewrite_module modules/mod_rewrite.so
RewriteEngine On
RewriteRule ^/b.html$ http://localhost/a.html
When I tri "http://localhost/a.html" It shows me the web page. But when I triend "http://localhost/b.html" apache2/error_log says "file does not exist: b.html"
Does any setting missing to enable rewrite_module?

The problem is in your RewriteRule. this should work:
RewriteEngine On
RewriteRule ^/b.html$ /a.html [L]
the rule match (^b.html$) must not include the starting slash. (this works in .htaccess, but not in server config)
the rewrite target should be a relative URI if possible (i.e. on the same host)
the rule should end with a directive "what to do" - in this case [L]eave processing (no more rules will be processed)

Have you checked whether in your Apache configuration file (most likely httpd.conf) the directive for the Alias or VirtualHost section:
AllowOverride All
I had the same problem of modrewrite not working because I had it off:
AllowOverride None
Good luck.

Do you have it inside the virtualhost section?
<VirtualHost *:80>
RewriteEngine On
RewriteRule ^/b.html$ /a.html
</VirtualHost>

It works now. Had to do two things:
Change "AllowOverride None" in /etc/apache2/sites-available/default to "AllowOverride All".
Put the rewrite rule in /var/www/.htaccess instead of httpd.conf
I am not sure why it does not works in httpd.conf. But it works after doing the above two things.

Related

Can htaccess return the output from another domain without issuing a 301?

let's say I have abc.com and def.com.
On def.com, I have a def.com/test.html that displays "hello".
I want to make it so that if I do a GET abc.com/something/, it returns a 200 with the contents of def.com/test.html directly, and not a 301 def.com/test.html. I don't want users to -know- communication between 2 servers happened.
Now, I could setup a abc.com/.htaccess to url rewrite to abc.com/test.php which would take care of echoing the contents of the other website with CURL like this:
<?
$url = "def.com/test.html"; //Would be received from the .htaccess's URL rewrite, say $_GET['wantedURL']
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
echo $output;
But, is there a way to tell the .htaccess to do the CURL by itself (or return the output of a shell script that would do so), something like the following ?
RewriteEngine on
RewriteRule ^/something/$ <curl def.com/test.html> [L]
#NOT THIS: RewriteRule ^/something/$ def.com/test.html [R=301,L]
Of course, I would be doing that for several dynamic URLs of a given pattern, so I've just hardcoded paths to explain what I'm looking for
thanks !
--- EDIT ---
I found Can ProxyPass and ProxyPassReverse work in htaccess? which seems to require to put it in vhosts configuration, and that's something I want to avoid. I would prefer if it could be done via .htaccess. Trying the above in .htaccess yields what they indeed explain to be impossible: ProxyPassReverse not allowed here
--- EDIT 2 ---
Following #MrWhite's recommendations, I now get No protocol handler was valid for the URL /something/. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule
But I think everything is loaded. When I do httpd -M | grep "proxy" I get:
proxy_module (shared)
proxy_ajp_module (shared)
proxy_balancer_module (shared)
proxy_connect_module (shared)
proxy_express_module (shared)
proxy_fcgi_module (shared)
proxy_fdpass_module (shared)
proxy_ftp_module (shared)
proxy_http_module (shared)
proxy_scgi_module (shared)
proxy_wstunnel_module (shared)
BTW this is my vhost:
<VirtualHost *:80>
ServerName abc.com
ProxyPass "/" "https://def.com/"
ProxyPassReverse "/" "https://def.com/"
</VirtualHost>
In .htaccess you can use the P (proxy) flag on the mod_rewrite RewriteRule directive to send the request via mod_proxy.
For example in the .htaccess file at abc.com:
RewriteEngine on
RewriteRule ^something/$ https://def.com/test.html [P]
(Note, that when used in .htaccess, the URL-path matched by the RewriteRule pattern does not start with a slash.)
However, this naturally requires that mod_proxy and related modules have already been loaded/enabled in the server config.
And if you don't set ProxyPassReverse in the server config (as you state, this is not allowed in .htaccess) then it would be trivial for the target domain (ie. def.com) to issue a redirect to itself and effectively break out of the reverse proxy. Although, this is not necessarily an issue if the target domain is in your control.

MASKING URL with HTACCESS

I am trying to redirect visitors of alldomain.com to the domain newdomain.com it does redirect however I want that when the user open's alldomain.com the data should be of newdomain.com however the top url should be alldomain.com
My Current HTACCESS:
RedirectMatch .* http://www.newdomain.com
I believe the solution to this consist of two parts: correct .htaccess, and using mod_proxy on your Apache server:
Uncomment these lines in httpd.conf (and restart Apache!):
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Add the following lines to your .htaccess:
RewriteEngine on
RewriteRule .* http://www.newdomain.com/ [P]
ProxyPassReverse / http://www.newdomain.com/
The key here is that the [P] flag in the RewriteRule tells Apache to use mod_proxy (which you enabled earlier), and the ProxyPassReverse makes sure that any links from the new domain are properly "attributed" to the old domain as well. I think that does it, but I can't test... Let me know whether this works for you!

How to debug .htaccess RewriteRule not working

I have a RewriteRule in a .htaccess file that isn't doing anything. How do I troubleshoot this?
How can I verify if the .htaccess file is even being read and obeyed by Apache? Can I write an echo "it is working" message, if I do write it, where would that line be echoed out?
If the .htaccess file isn't being used, how can I make Apache use it?
If the .htaccess is being used but my RewriteRule still isn't having an effect, what more can I do to debug?
Enter some junk value into your .htaccess
e.g. foo bar, sakjnaskljdnas
any keyword not recognized by htaccess
and visit your URL. If it is working, you should get a
500 Internal Server Error
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request....
I suggest you to put it soon after RewriteEngine on.
Since you are on your machine. I presume you have access to apache .conf file.
open the .conf file, and look for a line similar to:
LoadModule rewrite_module modules/mod_rewrite.so
If it is commented(#), uncomment and restart apache.
To log rewrite
RewriteEngine On
RewriteLog "/path/to/rewrite.log"
RewriteLogLevel 9
Put the above 3 lines in your virtualhost. restart the httpd.
RewriteLogLevel 9 Using a high value for Level will slow down your Apache server dramatically! Use the rewriting logfile at a Level greater than 2 only for debugging!
Level 9 will log almost every rewritelog detail.
UPDATE
Things have changed in Apache 2.4:
FROM Upgrading to 2.4 from 2.2
The RewriteLog and RewriteLogLevel directives have been removed. This functionality is now provided by configuring the appropriate level of logging for the mod_rewrite module using the LogLevel directive. See also the mod_rewrite logging section.
For more on LogLevel, refer LogLevel Directive
you can accomplish
RewriteLog "/path/to/rewrite.log"
in this manner now
LogLevel debug rewrite_module:debug
The 'Enter some junk value' answer didn't do the trick for me, my site was continuing to load despite the entered junk.
Instead I added the following line to the top of the .htaccess file:
deny from all
This will quickly let you know if .htaccess is being picked up or not. If the .htaccess is being used, the files in that folder won't load at all.
Generally any change in the .htaccess should have visible effects. If no effect, check your configuration apache files, something like:
<Directory ..>
...
AllowOverride None
...
</Directory>
Should be changed to
AllowOverride All
And you'll be able to change directives in .htaccess files.
To answer the first question of the three asked, a simple way to see if the .htaccess file is working or not is to trigger a custom error at the top of the .htaccess file:
ErrorDocument 200 "Hello. This is your .htaccess file talking."
RewriteRule ^ - [L,R=200]
On to your second question, if the .htaccess file is not being read it is possible that the server's main Apache configuration has AllowOverride set to None. Apache's documentation has troubleshooting tips for that and other cases that may be preventing the .htaccess from taking effect.
Finally, to answer your third question, if you need to debug specific variables you are referencing in your rewrite rule or are using an expression that you want to evaluate independently of the rule you can do the following:
Output the variable you are referencing to make sure it has the value you are expecting:
ErrorDocument 200 "Request: %{THE_REQUEST} Referrer: %{HTTP_REFERER} Host: %{HTTP_HOST}"
RewriteRule ^ - [L,R=200]
Test the expression independently by putting it in an <If> Directive. This allows you to make sure your expression is written properly or matching when you expect it to:
<If "%{REQUEST_URI} =~ /word$/">
ErrorDocument 200 "Your expression is priceless!"
RewriteRule ^ - [L,R=200]
</If>
Happy .htaccess debugging!
Perhaps a more logical method would be to create a file (e.g. test.html), add some content and then try to set it as the index page:
DirectoryIndex test.html
For the most part, the .htaccess rule will override the Apache configuration where working at the directory/file level
If you have access to apache bin directory you can use,
httpd -M to check loaded modules first.
info_module (shared)
isapi_module (shared)
log_config_module (shared)
cache_disk_module (shared)
mime_module (shared)
negotiation_module (shared)
proxy_module (shared)
proxy_ajp_module (shared)
rewrite_module (shared)
setenvif_module (shared)
socache_shmcb_module (shared)
ssl_module (shared)
status_module (shared)
version_module (shared)
php5_module (shared)
After that simple directives like Options -Indexes or deny from all will solidify that .htaccess are working correctly.
To test your htaccess rewrite rules, simply fill in the url that you're applying the rules to, place the contents of your htaccess on the larger input area and press "Test" button.
http://htaccess.mwl.be/
Check whether the permission to read and execute the .htaccess by apache process is possible. Looking into the error_log of Apache will help you to sort the permission related error.
Why not put some junk in your .htaccess file and try to reload apache. If apache fails to start you know its working. Remove the junk then reload apache if it loads congrats you configured .htaccess correctly.

Apache mod_rewrite internally to different port

Is it possible to internally redirect (so url won't change in address bar) with mod_rewrite to different port on same host?
Eg
http://host.com:8080 -> http://host.com:9999/myapplication/?param=val
1, Enable mod_proxy
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
2, You should configure apache for vhost :
<VirtualHost *:8080>
....
ProxyPass / http://host.com:9999/myapplication/?param=val
ProxyPassReverse / http://host.com:9999/myapplication/?param=val
</VirtualHost>
3, Setup also VHost on port 9999
More info here:
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
http://www.apachetutor.org/admin/reverseproxies
Elaboration on the mod_proxy solution with [P], the proxy flag:
Enable modules mod_proxy and mod_proxy_http:
a2enmod proxy proxy_http
Without these two enabled, you'd later get a 300 Forbidden status and the error message "AH00669: attempt to make remote request from mod_rewrite without proxy enabled" in the logs.
Place the following into the Apache2 vhost config section for the forwarding host:
<VirtualHost *:8080>
…
RewriteEngine on
RewriteCond %{REQUEST_URI} !^$
RewriteCond %{REQUEST_URI} !^/
RewriteRule .* - [R=400,L]
RewriteRule (.*) http://host.com:9999/myapplication/$1?param=val [P,L]
…
</VirtualHost>
This includes a technique by Steve Webster to prevent malicious URL crafting, explained here. Not sure how to deal with appending the GET parameter in this context, though.
Restart Apache2:
sudo service apache2 restart

mod_headers not working

I enable mod_headers and mod_rewrite in my http.config removing the # from line.
LoadModule headers_module modules/mod_headers.so
LoadModule rewrite_module modules/mod_rewrite.so
I need enable more something or the error is on .htaccess?
.htaccess.
RewriteEngine On
RewriteRule ^(.*?)\.x$ /$1.php [L]
<IfModule mod_headers.c>
<filesMatch "\.(x)$">
Header set foo "baa"
</filesMatch>
</IfModule>
Thanks in advance!
Try loading the headers module with
sudo a2enmod headers
sudo service apache2 restart
I resolved this problem by clearing cache of browser. If you are looking at browser inspector of chrome then check the 'Disable Cache' in 'Network' tab. But first make sure that mod_headers is already installed and working.