mod_rewrite is sending multiple requests back to Lucee server - mod-rewrite

I seem to have a problem whereby mod_rewrite is sending multiple requests back to my Lucee server. Sometimes 2 requests, sometimes 4 requests. I have a special application framework in Lucee to handle and manage all requests. It requires the request to be rewritten and proxied back to Lucee as "/" (root) with a request parameter set to the user requested URI. All of the rewriting appears to work properly but more than one request gets fired by the backend server. The following is my rewrite rule setup:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ "/" [E=vPath:$1,PT,NE,NS,L]
<If "-T reqenv('vPath')">
RequestHeader add "vPath" "%{vPath}e"
</If>
The RewriteRule simply grabs the URI and sets the environment variable "vPath", then rewrites the URI to "/" with the parameters:
PT (pass through to next handler)
NE (no URI escaping of output)
NS (not for internal sub-requests)
L (last rule)
This all seems to work just as needed, however, in testing I have verified that the request hitting the code behind in Lucee is actually getting called multiple times. If I turn RewriteEngine off, then only a single request is sent to the backend. Turn RewriteEngine on and multiple requests are again sent (anywhere from 2 to 6).
Also note that it doesn't seem to matter if I use "P" (force proxy) or "PT" (pass through to next handler), I get the same multiple request results.
Any help would be greatly appreciated. I am somewhat of a NUBE to mod_rewrite.
System:
OS: Linux 4.18.0-11-generic
Java: 1.8.0_181
Lucee: 5.2.9.31
Apache Tomcat: 8.5.33

Alex was correct in referring me to utilizing the logging for mod_rewrite. [hat tip to Alex, thanks!]
Take note that for mod_rewrite v2.4 and above, you simply use
LogLevel alert rewrite:trace6
And this will update the log file in
/var/log/apache2/error.log
My problem was that I was not accounting for other requests to files that don't actually exist that were also being redirected to the web root, like
/favicon.ico
The lesson here is to be certain to account for all requests being proxied back to the application server, otherwise it will simply execute the root request for each URI that is directed to the application.

Related

How to redirect example.com and example.com/anything to example.com/blog

I want to redirect example.com and example.com/anything to example.com/blog. Please note few things.
I refer example.com for a 1 domain.
I use apache as web server.
My document root is set to /var/www/html/public within apache vhost conf file (For a laravel APP).
I tried setting redirects in .htaccess and using apache vhost conf file and I get redirect too many times error.
Can someone help me to accomplish this please?
This probably is what you are looking for: rewriting on the level of the http server:
RewriteEngine on
RewriteRule ^/?$ /blog [R=301]
RewriteRule ^/?anything/?$ /blog [R=301]
If by "anything" you actually mean anything so that a redirection should get applied regardless of the requested path, then this should do:
RewriteEngine on
RewriteCond %{REQUEST_URI} !/blog
RewriteRule ^ /blog [R=301]
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
This implementation will work likewise in the http servers host configuration or inside a distributed configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a distributed configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using distributed configuration files (".htaccess"). Those distributed configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).
You can do that in your routes
// web.php
Route::redirect('/', '/blog');
Route::redirect('/anything', '/blog');

How to capture url requests made by my router?

I'm trying to deploy my own Dynamic DNS service at Dreamhost and following some guides managed to get the server side functioning perfectly - when I open a url the DNS A record for a subdomain gets updated.
But when I place the data on the router and try to make it work (following the standards at dyndns or no-ip) the router fails to update.
Here's what I have:
1. Server side works as I expected.
2. Router works when using the default services (tested with no-ip) to update IP.
3. If I fail the authentication on my server, then router throws an auth failed error - it's accessing the server and authenticating.
4. Tried logging to see if at any point the script is even accessed, and it's not.
So I think the router is requesting a url that is different than I expect. I tried with /, white /update/ and with /nic/update/
At this point I wanted to see what the router is actually requesting. Fired up XAMPP, installed Wireshark, and tried to set the router to update my own computer. Found the requests and found a 301 response since the router is asking for /nic/update? and I have it on /nic/update/?.
Browser handles this redirect transparently but the router seems to not be requesting the new url. Might need to mess with mod_rewrite?
As suspected, the router was taking the redirect as a bad reply.
After messing around with mod_rewrite I got it to work.
Used this:
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#
# If the requested path and file is not /index.php and the request
# has not already been internally rewritten to the index.php script
RewriteCond %{REQUEST_URI} !^/index\.php
# and the requested path and file doesn't directly match a physical file
RewriteCond %{REQUEST_FILENAME} !-f
# and the requested path and file doesn't directly match a physical folder
RewriteCond %{REQUEST_FILENAME} !-d
# internally rewrite the request to the index.php script
RewriteRule .* index.cgi [L]

redirect subdomain to page unless other page is called

i am trying to redirect all subdomains with more than 2 letters :
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^([^\.]{2,})\.domain\.com$ [NC]
RewriteRule .* index.php?page=static&subject=%1 [L,QSA]
for example : about.domain.com to display content of domain.com/?page=static&subject=about
but the URL remains about.domain.com in the browser
as well as if you're on about.domain.com and requested another page on that domain ( all pages go through index.php?page=blablabla) you need to be redirected back to domain.com/(whatever requested)
Same-domain internal rewrites can be done with the [P] (proxy) option.
If you need to reverse proxy a URL from the same virtual host config, you might be able to get away with a [P] rule, but if the domain of the internal request is from a different virtual host (or on a different box entirely) you probably need to look at a ProxyPass config.
In either case you will need mod_proxy installed and enabled.

Apache2 redirect all but some pages back to http using vhosts

I am using rewrite rules with Apache 2 to redirect certain types of pages to HTTPS using vhosts. These are anything that starts with mydomain.com/users. In other words, all pages having to do with users and their information should be on HTTPS. I want to redirect all other pages to HTTP.
What happens now is that when a user goes to a /users page, he is redirected fine to HTTPS. But when he navigates away from the /users area, I can't get the redirect back to HTTP.
I need the rules and conditions to rewrite anything that is NOT /users/* to HTTP. In other words, please help me fill in the blanks:
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{REQUEST_URI} __blank__
RewriteRule __blank__ http://mydomain.com%{REQUEST_URI} [R=301,L]
In researching this, there are a few things I am trying to avoid. I need a wildcard under /users because I am developing the app and often add pages under users (it's a Rails app).
I understand that it is not easy to do a NOT match with regular expressions. All I am trying to do here is have the bulk of the site run on HTTP except the /users/* pages on HTTPS.
Also, yes I have a valid cert and yes I have verified that the Apache2 rewrite mod works. I can get all URLs rewritten to HTTP no problem. How do I NOT rewrite ones that start with /users in the REQUEST_URI? I think I have actually tried about every answer on this site so far...
There quite a few answers for this sort of questions, -- you just need to search this site a bit. Yes, they do not answer your question 100% straight away (as everyone has slightly different requirements -- like different page name etc) but the whole approach is the same.
In any case -- here how it can be done:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# don't do anything for images/css/js (leave protocol as is)
RewriteRule \.(gif|jpe?g|png|css|js)$ - [NC,L]
# force https for /users/*
RewriteCond %{HTTPS} =off
RewriteRule ^/users/ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# force http for all other URLs
RewriteCond %{HTTPS} =on
RewriteCond %{REQUEST_URI} !^/users/
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# your other rewrite rules below
These rules need to be placed inside VirtualHost directive BEFORE any other rewrite rules (if such present). If placed elsewhere some small tweaking may be required.
They will
force HTTPS for all resources in /users/,
do nothing for images, css styles and JavaScript files (to be precise, for files with those extensions)
and will force HTTP for all other URLs
IMPORTANT NOTE: It is very likely that these rule will not work for you straight away. That is because modern browser do CACHE 301 redirects from your previous attempts. Therefore I recommend testing it on another browser and change 301 to 302 during testing (302 is not cached) .. or clear all browser caches (maybe even history) and restart browser.

mod_rewrite returns 302 found

I have an apache 2.2 and I am using mod_rewrite. My objective is to forward traffic from
http://localhost:80/AA to http://localhost:8090/BB. So I have a simple rule
RewriteRule http://localhost:80/AA http://localhost:8090/BB
My problem is that the client receives "302 Found". I was hoping that the RewriteRule will
forward the traffic from AA to BB and finally the BB will send the response to my client.
Is there a problem with my configuration?
See the documentation for RewriteRule
What you wanna do is add the R flag to your rule, for redirection.
RewriteRule http://localhost:80/AA http://localhost:8090/BB [R=permanent,L]
L for last rule.
The left side, or pattern, of your RewriteRule should just be the filename you want to match, e.g. ^/AA$. If you also want to make sure the host and port match specific values, you should set up RewriteCond's to match %{HTTP_HOST} and %{SERVER_PORT}. However the latter may be unnecessary unless your web server is configured for multiple domains and ports.
This is untested, but something like this:
RewriteCond %{HTTP_HOST} ^localhost
RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^/AA$ http://localhost:8090/BB
I would recommend that you try just this first:
RewriteRule ^/AA$ http://localhost:8090/BB
and add the RewriteCond's if you need them.
Edit based on comments: If you are trying to avoid the "302" response, you cannot do that for the situation you describe. When you use mod_rewrite to redirect from one host to another, you will get two responses sent to your browser. The first is 302, which tells the browser to go to the second URL. The second response should be 200.
With mod_rewrite, you can avoid the redirect in the middle if the rewrite is from one page to another on the same server and port. In that case, the rewrite is internal and the web server can respond with the BB page even though the request is for AA. If you use a different server or port, the web server for AA does not have access to the page BB, so it responds with a redirect to the server that does have access.
If you can reconfigure your site to use the same port for AA and BB, you can make it work. If not, I think you might be able to do what you want with mod_proxy. I have never used mod_proxy so I am not sure what you would need to do.
If you wish to forward traffic, I guess mod_rewrite can't do that. You should preferably use mod_proxy: http://httpd.apache.org/docs/2.0/mod/mod_proxy.html#proxypassreverse
Example from the documentation:
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass /foo http://foo.example.com/bar
ProxyPassReverse /foo http://foo.example.com/bar

Resources