Apache 2.4 mod_rewrite not working as expected - apache

I'm sure this is a simple one but I'd like to get some insight on this. I have a vm running plex media server and I'm trying to setup mod_rewrite for this. I'd like to have an HTTP connection -> SSL -> Plex
Keeping it simple, without SSL the following works
ServerName plex
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
RewriteCond %{HTTPS} !=on
ProxyPass / http://127.0.0.1:32400/
ProxyPassReverse / http://127.0.0.1:32400/
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/web
RewriteCond %{HTTP:X-Plex-Device} ^$
RewriteRule ^/$ /web/$1 [R,L]
This allows me to enter
http://plex/
Which rewrites to
http://plex/web
And removes my port number, now if I take the same as above and use https at lines 9 and 10 I break the rewrite.
Interestingly, if I use
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
RewriteCond %{HTTPS} !=on
ProxyPass / http://127.0.0.1:32400/
ProxyPassReverse / http://127.0.0.1:32400/
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/web
RewriteCond %{HTTP:X-Plex-Device} ^$
RewriteRule ^/?(.*) https://%{SERVER_NAME}:32400/web/$1 [R,L]
This works fine, but the port number is not removed. I understand this is because I'm including it in my rewrite rule.
So my question here is really two fold.
A) Why would using https instead of http at lines 9 and 10 not work as desired?
B) What is the correct setup to forward http->https while using a rewrite rule?
tyia

Try %{HTTP_HOST} instead of %{SERVER_NAME}

Related

Apache HTTP server redirect to port 8085 IF url contains "demo" ELSE redirect to port 8080

I have 2 applications running on port 8080 and 8085. Both has different URL queries/paths and application on port 8085 have keyword demo on all of its URL queries/paths and other doesn't. So it acts as an unique identifier
Can I make any change to /etc/httpd/conf/httpd.conf file so that if the server identifies demo as the keyword then request will reach application on port 8085, if not then request will reach port application on port 8080 ?
If there is a way, please provide sample configuration which goes into httpd.conf file
EDIT 1:
After trying from first 2 of below answers, I couldn't achieve this. I don't know if ProxyPass and ProxyPassReverse are not allowing to achieve this. I tried commenting them, adding them in VirtualHost etc. But did not help.
This is the flow we are expecting:
User will hit URL (without mentioning port) like - https://example.com/demo and this will be routed to app on port 8085 else routed to 8080
May be taking look at my complete httpd.conf might help
Link to my httpd.conf - https://gofile.io/d/tWIHvX
Rewrite Condition if the query string contains a word "demo":
<VirtualHost *:8080>
<Directory /var/www/example/>
Allow From All
RewriteEngine On
RewriteCond %{SERVER_PORT} !^8085$
RewriteCond %{QUERY_STRING} (demo)
RewriteRule ^Demo http://%{HTTP_HOST}:%{SERVER_PORT}/$1 [L,R]
</Directory>
</VirtualHost>
Rewrite condition if the query string does not contain the word "demo":
<VirtualHost *:8085>
<Directory /var/www/example/>
Allow From All
RewriteEngine On
RewriteCond %{SERVER_PORT} !^8080$
RewriteCond %{QUERY_STRING} (!demo)
RewriteRule ^Demo http://%{HTTP_HOST}:%{SERVER_PORT}/$1 [L,R]
</Directory>
</VirtualHost>
if the SERVER_PORT doesn't work, please try the port directly like below:
RewriteRule ^Demo http://%{HTTP_HOST}:8085/$1 [L,R]
Try:
<VirtualHost *:8080>
#some conf
RewriteCond %{REQUEST_URI} demo [OR]
RewriteCond %{QUERY_STRING} demo
RewriteRule ^ http://%{HTTP_HOST}:8085%{REQUEST_URI} [QSA,L]
#some more conf
</VirtualHost>
OR
<VirtualHost *:8085>
#some conf
RewriteCond %{REQUEST_URI} !demo
RewriteCond %{QUERY_STRING} !demo
RewriteRule ^ http://%{HTTP_HOST}:8080%{REQUEST_URI} [QSA,L]
#some more conf
</VirtualHost>
Note: self answer after being able to achieve this
Achieved this using LocationMatch directive easily. Below is the configuration.
As this is regex dependent you can change to check conditions like ends with, starts with, contains and etc. And both the below LocationMatch conditions are in my httpd.conf
1.If URL like 192.168.1.113/demo then go to 8085
<LocationMatch "^/(demo)(.*)$">
RewriteEngine on
ProxyPass http://localhost:8085/ nocanon
ProxyPassReverse http://localhost:8085/
</LocationMatch>
2.If URL not like 192.168.1.113/demo then go to 8080
<LocationMatch "^/((?!demo).)*$">
RewriteEngine on
ProxyPass http://localhost:8080/ nocanon
ProxyPassReverse http://localhost:8080/
</LocationMatch>

RewriteCond QUERY_STRING or/and ProxyPass?

I have to forward requests from internet client like this one :
https://www.app.com/AppServer?User=guest&ID=8PKX3Q2DT45&Type=laptop&Cmd=exec
to internal server with changing some parameters :
https://192.168.0.1/AppServer?User=guest&ID=NEW_ID&Type=NEW_TYPE&Cmd=exec
with Apache web server. NEW_ID and NEW_TYPE are static variables.
I've tried differents things with ProxyPass and RewriteCond %{QUERY_STRING} but without success.
RewriteEngine On
RewriteCond %{QUERY_STRING} .*User=(\w+).*&ID=(\w+).*&Type=(\w+).*&Cmd=(\w+).*$ [NC]
RewriteRule . HOST/AppServer?User=$1&ID=NEW_ID&Type=NEW_TYPE&Cmd=Exec [R=301,L]
ProxyPass HOST/AppServer
ProxyPassReverse HOST/AppServer
(URL has been replaced with HOST because of post restriction)
Also, I should be able to change header with RequestHeader (this work properly).
Could you help me to build the configuration ?
Kindest regards,
I answer to my question, this work :
#NEW UA
RequestHeader set User-Agent "NEW_UA"
RewriteEngine On
RewriteCond %{QUERY_STRING} ^(.*)OLD_ID(.*)OLD_DEVICE(.*)$
RewriteRule (.*) HOST/AppServer/?%1NEW_ID%2NEW_DEVICE%3 [P,L]
ProxyPass / HOST/
ProxyPassReverse / HOST
Thanks,

Apache and ProxyPass proxy

I would like to implement a kind of a proxy system, where I can type url like this: http://example.com/www.stackoverflow.com and get contents of www.stackoverflow.com returned. What I tried is this:
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/external/.*
RewriteRule ^/(.*) http://%{HTTP_HOST}/external/$1 [NC,R=302,L]
ProxyPassMatch /external/([A-Za-z]*)/(.*) wwww.stackoverflow.com/$1/$2
ProxyPassMatch /external/(.*) http://$1/
This works fine, but works only for stackoverflow.com because it is hardcoded. Is there some kind of rule so that dynamic URL can work, so I can use http://example.com/yahoo.com ? And yes, if try to hardcode yahoo.com or google.com, instead of rewrite url get automatically redirected to yahoo.com or google.com, what's up with that ?
You can use the [P] flag of RewriteRule:
RewriteEngine On
RewriteRule ^/(.*) http://$1 [P]
More info here

Redirect URL in browser before Proxy Pass

I am trying to remove the trailing slash from all of my URLs and redirect.
I've accomplished this here:
<Directory /var/www/html/ >
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+[^/])/$ ${BaseUrl}/$1 [R=301,L]
</Directory>
However, I am also running a service locally and want to proxy to it visits /${ServiceRoot}.
ProxyPass /${ServiceRoot} http://localhost:${ServicePort}/
ProxyPassReverse /${ServiceRoot} http://localhost:${ServicePort}/
Each of these works fine individually. However, if I try to visit a URL like this: ${BaseUrl}/${ServiceRoot}/some/path/
The trailing slash is left on. I would like to force a redirect so the URL in the browser shows without the trailing slash.
Thanks in advance!
Just remove the L from the RewriteRule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+[^/])/$ ${BaseUrl}/$1 [R=301]
That should apply the rule to your ProxyPass directive. Just remember to check DirectorySlash if you plan to support directory listings, it will try to redirect directories to / and then back in a loop.
You probably got something like this in your apache config:
ProxyRequests On
ProxyVia On
<Proxy *>
Order deny,allow
Allow from xx.xx.xx.xx
</Proxy>
Then you have to add the following in order to proxy-pass all requests to www.olddomain.com/foo to www.newdomain.com/bar
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.olddomain\.com$
RewriteRule /foo(.*)$ http://www.newdomain.com/bar/$1 [P,L]
What this does is:
When a request is made to host www.olddomain.com the RewriteRule will fire
This rule substitutes /foo to http://www.newdomain.com/bar/
The substitution is handed over to mod_proxy (P)
Stop rewriting (L)
Example result:
Browser is configured to use your apache as proxy server
It requests www.olddomain.com/foo/test.html
Your apache will rewrite this to www.newdomain.com/bar/test.html
It will request this page from the responsible webserver
Return the result to the browser as www.olddomain.com/foo/test.html

Internal redirect in Apache VirtualHost configuration

Accessing the Plex media server requires to access http://my-ip:32400/web which isn't very easy for non-techies to remember. I followed a blog post I found to simplify this:
<VirtualHost *:80>
ServerName mediaserver
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:32400/
ProxyPassReverse / http://127.0.0.1:32400/
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/web
RewriteCond %{HTTP:X-Plex-Device} ^$
RewriteRule ^/$ /web/$1 [R,L]
</VirtualHost>
I also pointed mediaserver on my DNS server to the correct IP. This works in a way. Now I can just type http://mediaserver to access the Plex media server. However, this redirects to http://mediaserver/web. In the RewriteRule there are R and L flags. I read the documentation for the flags, removed them and added PT flag. I also checked the documentation for internal redirecting, where I found the PT flag.
So, with the rewrite rule written as RewriteRule ^/$ /web/$1 [PT], I thought it would internally redirect to /web/ and not show it in the URL. How do I fix this?
Try changing the rule to this:
RewriteRule ^/$ /web [L]
There is no group capture, so the $1 was not doing anything
The R is what causes the url to change in the browser. With just the L, you have an internal redirect, but the user doesn't see the rewritten url.