Apache Rewrite Rules for CentOS Grails Application with Tomcat - apache

I am using Apache and Tomcat on a CentOS box and I want to do the following rewrites:
I want to handle abc.com to redirect to www.abc.com when a request is made.
I want to load my resources with Apache instead of Tomcat
This is my conf file. It is located in /etc/httpd/conf.d/tomcat.conf
#
# This configuration file enables the default "Welcome"
# page if there is no default index page present for
# the root URL. To disable the Welcome page, comment
# out all the lines below.
#
RewriteEngine on
RewriteRule ^/images/(.*) /images/$1
RewriteRule ^/css/(.*) /css/$1
RewriteRule ^/js/(.*) /js/$1
RewriteCond %{HTTP_HOST} ^abc\.com
RewriteRule ^(.*)$ http://www.abc.com$1 [R=301,L]
NameVirtualHost *:80
<VirtualHost *:80>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / ajp://127.0.0.1:8009/
ProxyPassReverse / ajp://127.0.0.1:8009/
ProxyPassReverseCookiePath / /
</VirtualHost>
My AJP proxy rewrite is working, I just need to do the following rewrites above.

apache redirect from non www to www
To load your resources with apache instead of tomcat, you can:
use apache mod_cache module, so you can decrease your tomcat load dramatically by caching your resources (css, js, images)
add servlet filters in your web application to set http cache headers in order to enable caching

Related

Configure Apache for Angular and Tomcat on the same host

I am trying to serve my application on a Centos 7 host, where I have deployed an Angular app for the frontend and Java Spring Boot app for the backend.
My versions are Apache 2.4.6, Tomcat 9 and Angular 7.
Let's say my domain is example.com. I want the user to write the following on the browser to access the Angular app routes, i.e. the frontend:
example.com/**
Also I would like to be able to write the following on the browser to access the Java app routes, i.e. the backend:
example.com/api/**
I tried to do it using Apache's mod_proxy, after reading this post: https://stackoverflow.com/a/33095758/350061. However, I only managed to serve Angular through example.com, while my API is only served on its original endpoint, that is example.com:8080/my-api and not through example.com/api.
These are my Apache settings:
/etc/httpd/conf.d/example.conf
<VirtualHost *:80>
ServerName example.com
ProxyPreserveHost On
DocumentRoot "/var/www/my-ng-app/dist/my-ng-app"
RewriteRule ^/api/(.*) http://localhost:8080/$1 [P,L,QSA]
ProxyPassReverse /api/ http://localhost:8080/
</VirtualHost>
/var/www/my-ng-app/.htaccess
RewriteEngine On
RewriteRule ^api/(.*) http://localhost:8080/my-api/$1 [P,L,QSA]
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html
I have configured .htaccess to be read from that folder and verified that it is actually read. Also even if I remove the last part of .htaccess that redirects non-existing resources to index.html, the api does not get served from example.com/api, as I wish. It only gets served from example.com:8080/my-api
Any ideas on how to configure it?
After a long time of googling and trial and error, my solution consists of these changes:
I edited Tomcat's server.xml connector to serve requests through localhost. This made possible for rewrite settings to access my Java app through localhost:8080, but made impossible for me to access remotely my Java app through example.com:8080, which is fine.
I configured SELinux to allow Apache (httpd) to initiate outbound connections, in my case connections to localhost
I applied some fixes on my original VirtualHost and .htaccess configuration
More specifically:
sudo nano /opt/tomcat/latest/conf/server.xml
Find the connector for port 8080 and add address attribute as such:
<Connector port="8080" protocol="HTTP/1.1"
address="127.0.0.1"
connectionTimeout="20000"
redirectPort="8443" />
/usr/sbin/setsebool -P httpd_can_network_connect 1
The -P persist the setting for future reboots
/etc/httpd/conf.d/example.conf
<VirtualHost *:80>
ServerName example.com
ProxyPreserveHost On
DocumentRoot "/var/www/my-ng-app/dist/my-ng-app"
RewriteRule ^/api/(.*) http://localhost:8080/my-api/$1 [P,L,QSA]
ProxyPassReverse /api/ http://localhost:8080/my-api/
</VirtualHost>
/var/www/my-ng-app/.htaccess
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html
After these changes just restart Tomcat and Apache and you will be able to access your API through example.com/api

Redirecting HTTP to HTTPS with Apache RedirectPermanent for sites that use modperl

I have an Apache 2.4 site that serves content that is generated by modperl via HTTPS. The relevant Location section is as follows:
<Location />
SetHandler modperl
PerlResponseHandler MyService
</Location>
I would now like to enable the same content via HTTP as well. The following /etc/apache2/sites-enabled/myservice.conf works to some extend in that it redirects URLs with trailing paths but not the "root" page (say, http://myservice.mycompany.com). I suspect this is (also) because this page is special in that it is backed by modperl.
<VirtualHost *:80>
LogLevel debug
ServerName myservice.mycompany.com
RedirectPermanent / https://myservice.mycompany.com
</VirtualHost>
So how can I use RedirectPermanent for redirecting from HTTP to HTTPS for an entire Apache sites, including those pages that are backed by modperl?
To redirect any path in your site, you probably want to use mod_rewrite. These rules should work:
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]
(I've removed the perl and mod_perl tags from this question. The rewrite happens long before the server cares about how it's going to serve the content.)

mod_rewrite - Port 80 does not change to 443 when HTTP is explicitly requested

I have an app deployed to Elastic Beanstalk whose Tomcat container uses Google OpenID Connect for authentication. I want to redirect all http requests to https, for which I have the following mod_rewrite configuration in a file in .ebextensions -
files:
"/etc/httpd/conf.d/ssl_rewrite.conf":
mode: "000644"
owner: root
group: root
content: |
LoadModule rewrite_module modules/mod_rewrite.so
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule . https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]
Google OAuth2 credentials console has https://example.com/j_security_check as an authorized redirect URL. The configuration works fine when either example.com or https://example.com is requested, whereupon the app is redirected to the mentioned authorized URL.
However, when http is explicitly requested - http://example.com - the app is being redirected to https but port 80 is still being used. The authorized redirect URL then becomes https://example.com:80/j_security_check and I get Error: redirect_uri_mismatch.
How can I redirect explicit http requests to https with the port changed to 443? The main goal is to match the mentioned authorized redirect URL. If possible, I'd like to implement this with the .ebextensions configuration file or a similar solution.
Can you something like this. If it got worked I will give you the explanation.
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
The problem was not with the rewrite rule. The file had to be placed in a specific path within .ebextensions for it to work in Tomcat 8. The configuration files had to be setup differently too. Most examples provided were not for Tomcat so I ended up putting them in the wrong location.
What worked -
In /.ebextensions/httpd/conf.d/myconf.conf, place -
LoadModule rewrite_module modules/mod_rewrite.so
and in /.ebextensions/httpd/conf.d/elasticbeanstalk/00_application.conf, place -
<VirtualHost *:80>
<Proxy *:80>
Order Allow,Deny
Allow from all
</Proxy>
ProxyPass / http://localhost:8080/ retry=0
ProxyPassReverse / http://localhost:8080/
ProxyPreserveHost on
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule . https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]
ErrorLog /var/log/httpd/elasticbeanstalk-error_log
</VirtualHost>
Take note of the use of .conf files instead of .config. This is important!
Also, the redirection that I was getting was not genuine. I was not paying close attention, because when I requested example.com, the browser cache was serving me https://example.com. It was not actually redirecting an http request to https.

URL Rewrite in httpd.conf

I have a redirect setup on my Apache server within the httpd.conf file that redirects all traffic to "server.mydomain.com" to https://server.mydomain.com/uri. Unfortunately, some users will enter https before the URL and it does not redirect, instead they get Apache error page. I want to know how can I get users who input https before the URL to be redirect to https://server.mydomain.com/uri. I believe I may have to do a rewrite but I'm not sure or know how to go about doing it. I've research about rewrite and found it should be done in the .htaccess file but when I read Apache best practice they state it should not be done within .htaccess file for security and performance. Instead, it should be done within the config file. Since the redirection is working within the httpd.conf file, I would like to incorporate the rewrite there as well. I presume that is the correct according to Apache website. My issue is how do I go about doing this within that file. I've included the file information below. Any assistance is greatly appreciated. The server is using Tomcat 7 with Apache 2.2.15.
httpd.conf file:
</IfModule>
#
ProxyPass /uri/fbs-ws ws://server.mydomain.com:8081/uri/fbs-ws
ProxyPassReverse /uri/fbs-ws ws://server.mydomain.com:8081/uri/fbs-ws
</IfModule>
<VirtualHost *:80>
ProxyPass /uri http://server.mydomain.com:8080/uri
ProxyPassReverse /uri http://server.mydomain.com:8080/uri
Redirect permanent / https://server.mydomain.com/uri
</VirtualHost>
Did you try creating a vhost for 443 and switching to http there via Rewrite?
<VirtualHost *:443>
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

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 :)