Can ProxyPass and ProxyPassReverse work in htaccess? - apache

I've never set up a proxy before. I'm using shared hosting, so to set Apache directives, I need to use .htaccess. Can I use .htaccess to do something like below? Any limitations?
ProxyRequests Off
ProxyPass /img/ http://internal.example.com/img/
ProxyPass /app/ http://internal.example.com/app/
ProxyPassReverse / http://internal.example.com/

You cannot use a ProxyPass in an htaccess file. The documentation says it is only applicable in the context:
Context: server config, virtual host, directory
which excludes htaccess (you can't have a <Directory> block in htaccess). However, you can use a ProxyPassReverse to internally rewrite the Location field of proxied requests that cause a redirect. You'll just need to use mod_rewrite's P flag to proxy instead of ProxyPass. So something like:
RewriteEngine On
RewriteRule ^/?img/(.*)$ http://internal.example.com/img/$1 [L,P]
RewriteRule ^/?app/(.*)$ http://internal.example.com/app/$1 [L,P]
ProxyPassReverse / http://internal.example.com/
Just to be clear, you cannot use ProxyPass or ProxyPassReverse in the htaccess file, but you can use ProxyPassReverse with mod_rewrite rules that utilize the P flag.

You can't use ProxyPassReverse, but you can mimic it if you have the ability to rewrite the HTML as it comes back from the origin server.
See my writeup here.

Related

How to add a query parameter to apache 2.4.27 ProxyPass?

I want to map multiple customer facing URLs to a single internal end-point, but with a query parameter to to identify each customer.
For example customer enters https://external_host/customer1
I want a reverse proxy to forward it as https://internal_host/app?customer=cust1
I have tried the following:
<Location "/customer1" >
RewriteEngine On
RewriteRule /customer1 /customer1?customer=cust1 [QSA,P]
ProxyPass https://<internal host>/app
ProxyPassreverse https://<internal host>/app
</Location>
<Location "/customer2" >
RewriteEngine On
RewriteRule /customer2 /customer2?customer=cust2 [QSA,P]
ProxyPass https://<internal host>/app
ProxyPassreverse https://<internal host>/app
</Location>
The basic proxy works, in that the request is forwarded to the internal server, but the query parameter is not added.
From all the reading I have done, I feel it should be possible to do what I want, but cannot get it to work.
Any pointers gratefully received.
Regards
Chris
I solved this as follows:
ProxyRequests off
ProxyPass /app http://<internal server>/app
ProxyPassReverse /app http://<internal server>/app
RewriteEngine on
RewriteRule ^/cust1.htm /app?client=cust1.htm [QSA,P]
RewriteRule ^/cust2.htm /app?client=cust2.htm [QSA,P]
Chris
The ProxyPass and ProxyPassReverse from the question config are ignored, because the P in [QSA,P] performs the proxy request.
Some additional cases to add query parameter extraparam=something to the proxied server:
Regular expression and remote server
if you need to use a regular expression in your rule (first wildcard (.*) is replaced by $1):
RewriteEngine on
RewriteRule ^/path/to/hook/to/proxy/(.*) http://example.org/$1?extraparam=something [QSA,P]
If the proxied server uses https, you should add SSLProxyEngine On to the configuration:
RewriteEngine on
SSLProxyEngine on
RewriteRule ^/path/to/hook/to/proxy/(.*) https://example.org/$1?extraparam=something [QSA,P]

Apache - Proxy external files to download

Consider this:
we have an external server for files that can be downloaded
our website (plone based) is the interface for downloading them and we try to hide the direct links as much as possible
jquery.fileDownload plugin needs a cookie set on file on download
I'm trying to set our Apache configuration to replace links like this:
original: data-files-example.com/folder/subfolder/file.zip
replaced: our-website-example.com/_downloads/folder/subfolder/file.zip
So, the missing part in my case is: how to set Apache to work like this?
I'm trying:
NameVirtualHost *:80
<VirtualHost :80>
ServerAdmin email#our-website-example.com
ServerName our-website-example.com
RewriteEngine On
RewriteRule "^/_downloads(.)$" "https://data-files-example.com/$1" [P]
RewriteCond %{REQUEST_METHOD} ^(PUT|DELETE|PROPFIND|OPTIONS|TRACE|PROPFIND|PROPPATCH|MKCOL|COPY|MOVE|LOCK|UNLOCK)$
RewriteRule .* - [F,L]
RewriteRule ^/(.*) http://127.0.0.1:/VirtualHostBase/http/data-files-example.com:80/my_plone_website/VirtualHostRoot/$1 [L,P]
</VirtualHost>
I receive 503 Service Unavailable.
How to fix this?
Try a reverse proxy. Just make sure that mod_proxy and mod_proxy_http are enabled in your Apache configuration and that your proxy rule is set before the VirtualHostBase rule for Plone, if the pattern is the root slash.
ProxyPass /_downloads http://data-files-example.com
ProxyPassReverse /_downloads http://data-files-example.com
When proxying to a https backend you'll also need mod_ssl installed and the directive SSLProxyEngine On.
SSLProxyEngine On
ProxyPass /_downloads https://data-files-example.com
ProxyPassReverse /_downloads https://data-files-example.com
Following code at least rewrites your given original- to your desired target-URL:
<VirtualHost>
SSLProxyEngine On
RewriteEngine On
RewriteCond %{HTTP_HOST} ^our-website-example.com$
RewriteRule "^/_downloads(.*)$" "https://data-files-example.com/$1" [P,L]
</VirtualHost>
This requires the modules mod_ssl, mod_proxy and mod_rewrite to be activated.
Let us know if it was your sought solution and if not, where it went wrong :)

ProxyPass but exclude certain sub directory

This is what I need to achieve
I need to proxy all requests to /public/ route to another server, except that requests to /public/forms/ must not be proxied and should be served by this apache server.
I have added these directives to my httpd.conf
ProxyPass /public/ http://localhost:3002/public/ retry=10
ProxyPassReverse /public/ http://localhost:3002/public/
It proxies all requests to /public/ to this localhost:3002 but is there any way to exclude /public/forms/ from this proxying?
On top of those because most specific requests should be defined first with ProxyPass add this:
ProxyPass /public/forms/ !
That tells mod_proxy to "not proxy" for that path.

Apache: Rewrite URL in the Background

This question is probably too simple but I cannot get it to work despite hours of testing (and even crashing the server twice o.o ).
The issue is asked frequently: A Tomcat server is accessible through:
"domain.net:8080/theserver/"
and I want it to be accessible directly on "domain.net/".
Just that should also be visible in the user's browser.
The engine "Plesk" which I'm using to configure the site offers a command field for such things. Using the following lines, I've established visible redirecting:
ProxyRequests off
RequestHeader unset Accept-Encoding
RewriteEngine on
RewriteRule ^(/.*) http://www.domain.net:8080/theserver [P]
The redirection doesn't happen in the background though. When I type domain.net into the browser, it switches to "domain.net:8080/theserver/".
What's the right way to make this happen in the background?
"theserver" is the root-location which should be accessible on the server for now.
Huge thanks in advance!
Make sure Rewrite Module of webserver is enabled.
Make sure apache listens on port 80 and 8080 both.
Add this to .htaccess file in the root BUT NOT in the subdirectory "theserver".
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?domain.net$
RewriteCond %{REQUEST_URI} !^/theserver/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://domain.net:8080/theserver/$1
RewriteCond %{HTTP_HOST} ^(www.)?domain.net$
RewriteRule ^(/)?$ http://domain.net:8080/theserver/index.php [L]
You first need to make sure both mod_proxy and mod_proxy_http are enabled in plesk.
Also you should probably either use www or not www.
ProxyRequests Off
RewriteEngine on
RewriteRule ^(.*)$ http://domain.net:8080/myserver/$1 [P]
You can also use the ProxyPass in the server config/vhost.
<Location />
ProxyPass http://domain.net:8080/
ProxyPassReverse http://domain.net:8080/
</Location>
You're just missing ProxyPassReverse. The backend is sending a redirect on the initial URL to add a trailing slash. ProxyPassReverse fixes those redirects for you to use the frontend host/port.
If you control the apache web server, then do you not have to redirect any URL.
Rewriting is supposed to happen for unique requests. If possible, then should the type of rewrite you want get done in the configuration of apache.
First do you have to tell the apache server to listen on port 8080:
listen 8080
Then can you make a virtual host like this:
<VirtualHost *.:8080>
Servername www.domain.net
</VirtualHost>
See for instance:
https://httpd.apache.org/docs/trunk/vhosts/examples.html
and
https://httpd.apache.org/docs/trunk/vhosts/examples.html#port
specifically.
This is much more efficient than using .htaccess, because the latter is parsed at every request, where the solution with virtual hosts is loaded into memory during startup of the server.
Your solution is the other way around. It will make the port visible, because that is the rewrite you create. You want it the other way around and that can be established best by making use of virtual hosts.
A little example of a virtual host:
<VirtualHost www.example.nl:8080>
ServerName www.example.nl
ServerAlias example.nl
DocumentRoot /var/www/theserver
<Directory /var/www/theserver>
etc..
</Directory>
etc...
</VirtualHost>
You may want to actually setup ProxyPass and ProxyPassReverse to accomplish what you are trying to do
ProxyRequests on
ProxyPass / http://IP_OR_LOCALHOST:8080/theserver/
ProxyPassReverse / http://IP_OR_LOCALHOST:8080/theserver/
OR
ProxyPass /theserver/ http://IP_OR_LOCALHOST:8080/theserver/
ProxyPassReverse /theserver/ http://IP_OR_LOCALHOST:8080/theserver/
OR
ProxyPass /anyname/ http://IP_OR_LOCALHOST:8080/theserver/
ProxyPassReverse /anyname/ http://IP_OR_LOCALHOST:8080/theserver/

Content Fetching Using htaccess

Let I have two domains named www.abc.example and www.xyz.example hosted in different servers.
I have a .htaccess file in the root directory of www.abc.example (i.e. www.abc.example/.htaccess)
What will be the .htaccess script if I want to load the contents of www.xyz.example when I request from www.abc.example.
As for example:
If I browse www.abc.example/test then it will display the content of www.xyz.example/test and so on without changing the host url (i.e. www.abc.example) in browser's addressbar.
What you're trying to do is run a reverse proxy. It requires mod_proxy on the server.
The documentation seems to suggest you'd want something like:
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://www.xyz.example/
ProxyPassReverse / http://www.xyz.example/
Assuming that such configuration is allowed in .htaccess. If not, you will have to use mod_rewrite and a RewriteRule with the [P] flag:
RewriteRule ^/(.*) http://www.xyz.example/$1 [P]
If you're going the RewriteRule route, don't forget to add RewriteEngine On if it isn't there already!