apache 2.4 rewriterule redirect regex matching letters, but not matching dot - apache

I have a nodejs application that uses django application as a websocket and REST API server. Since I developed using node-http-proxy, I am trying to deploy using the same setup.
if /api is in REQUEST_URI, it should be proxied to rest server's /api.
If /api/ws is in REQUEST_URI, it should be proxied to websockets server's /api/ws.
If we are reading a deployed file, it should be served directly.
If we are going to any URI other than /api that is not a file it should just redirect to /
This last statement is needed because refreshing a react route generated URI causes 404.
I wrote the following virtual host, but the rewrite rule doesn't capture /dashboard
Listen 0.0.0.0:3001
<VirtualHost *:3001>
ServerName site.example.com
DocumentRoot /var/www/site.example.com
ProxyRequests on
ProxyPass /api/ws ws://127.0.0.1:8081/api/ws
ProxyPassReverse /api/ws ws://127.0.0.1:8081/api/ws
ProxyPass /api http://127.0.0.1:8081/api
ProxyPassReverse /api http://127.0.0.1:8081/api
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !^/api.*$
RewriteRule ^/(.+)$ / [L,R]
</VirtualHost>
But somehow the redirect rule fails to match non-API urls
If I replace
RewriteRule ^/(.+)$ / [L,R]
with
RewriteRule ^/([a-z]+)$ / [L,R]
then it captures /dashboard and redirects to / correctly.
The question is: why doesn't /dashboard match .+ while it matches [a-z]+ ?

Related

Redirect Error When using [OR] flag with RewriteCond

I have an apache 2.4 reverse proxy server setup that gets content from one of two different back end web servers depending on the request URL.
By default all http requests are redirected to https.
However, I need to make two exceptions to the default by allowing two diferent URL's to remain http.
Note that due to domain posting restrictions the reverse-proxy domain is example.com and one of the back end servers is example.org
I have the following configuration for the http (non-secure) apache instance of the reverse proxy:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/this [OR]
RewriteCond %{REQUEST_URI} !^/that
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
RewriteRule ^/that$ /that/ [R=301,L]
<Location /that/>
ProxyPass http://example.org/that/
ProxyPassReverse http://example.org/that/
</Location>
RewriteRule ^/this$ /this/ [R=301,L]
<Location /this/>
ProxyPass http://example.org/
ProxyPassReverse http://example.org/
</Location>
If I browse to http://example.com I am redirected to https://example.com as expected.
If I try browsing to http://example.com/this or http://example.com/that I get the following error:
The page isn’t redirecting properly
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
This problem can sometimes be caused by disabling or refusing to accept cookies.
If I only add this or that individually it works without any problems so the error seems to be caused when I add the [OR] flag.
For example, this works:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/this
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
RewriteRule ^/this$ /this/ [R=301,L]
<Location /this/>
ProxyPass http://example.org/
ProxyPassReverse http://example.org/
</Location>

mod_rewrite, multiple domain, virtualhost

Here's what I'm trying to achieve :
redirection to 2 different application hosted for 2 different domain
redirect to https://
Not www-domain
Make sure trailing slash gets appended in-case user misses out.
Please note :
It's a shared instance - so there's another application configured already.
My Current solution configuration :
# VirtualHost Listening on Port 80
123.123.1.1:80
# Original Configuration for Existing Application
<VirtualHost *>
ServerName 123.123.1.1:80
# Additional cluster configuration using Proxy ( mod_proxy ) & LoadBalancer
</VirtualHost>
<VirtualHost *>
ServerName domain1.com
Redirect / https://domain1.com/app1/$1
</VirtualHost>
<VirtualHost *>
ServerName domain2.com
Redirect / https://domain2.com/app2/$1
</VirtualHost>
Alternatives I have tried are :
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://domain1.com/app1/$1
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://domain2.com/app2/$1
Can someone please point out what additional configuration shall i do ?
What is my mistake ?
Try using a condition to look for the domain then redirect based on the incoming domain being requested.
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?domain1\.com [NC]
RewriteRule (.*)$ https://domain1.com/app1/$1/ [R=301,L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?domain2\.com [NC]
RewriteRule (.*)$ https://domain2.com/app2/$1/ [R=301,L]

htaccess redirect url without changing address bar

Im using bigcartel and i would like to redirect my url to bigcartels url without changing the broswers address bar, i.e
www.example.com to be redirect to www.test.bigcartel.com but show www.example.com in the browsers address bar
I dont want to use iframes but htaccess file.
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule ^/?$ "http\:\/\/testing\.bigcartel\.com\/" [L]
can anybody help? i found this below but didn't know what to change to make it work
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+)$ ?url=$1 [L]
You should enable mod_proxy. Then allow access with:
<proxy http://www.test.bigcartel.com>
Allow from all
</proxy>
And setup the redirection:
ProxyPass / http://www.test.bigcartel.com
For more options see the docs for mod_proxy.

apache rewrite with virtual host has recursion

I want to rewrite test.com to test.com/context.
The browser returns redirection recursion error.
Anyone has a clue?
I put below in httpd-vhosts.conf.
<VirtualHost *:80>
ServerName test.com
JkMount /* mschoi
ErrorLog logs/mschoi-error_log
CustomLog logs/mschoi-acces_log common
RewriteEngine On
RewriteRule ^/(.*)$ /context/$1 [L,R]
</VirtualHost>
httpd.conf
Include conf/extra/httpd-vhosts.conf
This is a simple case of your rule matching /context again when it rewrites. You can just use a RewriteCond to avoid it:
RewriteEngine On
# Rewrite only if the request doesn't already match /context
RewriteCond %{REQUEST_URI} !^/context
RewriteRule ^/(.*)$ /context/$1 [L,R]
If the files being accessed actually exist (rather than a rewrite pattern) you can test for and not rewrite any real existing files:
RewriteEngine On
# If the requested resource is not actually a real file or directory (doesn't exist)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /context/$1 [L,R]
Edit after comment to explain:
Not only per-directory rules can cause recursion. In this case, it is the simple matter that /(.*) matches anything and that gets appended unconditionally to /content. Since the [R] flag is present to redirect and each of these is a new request, it becomes a redirection chain of :
/something
/content/something
/content/content/something
/content/content/content/something
Subsequent redirects always continue to match the leading /content as well as what follows with /(.*) and append to it.

apache redirect from non www to www

I have a website that doesn't seem to redirect from non-www to www.
My Apache configuration is as follows:
RewriteEngine On
### re-direct to www
RewriteCond %{http_host} !^www.example.com [nc]
RewriteRule ^(.*)$ http://www.example.com/$1 [r=301,nc]
What am I missing?
Using the rewrite engine is a pretty heavyweight way to solve this problem. Here is a simpler solution:
<VirtualHost *:80>
ServerName example.com
Redirect permanent / http://www.example.com/
</VirtualHost>
<VirtualHost *:80>
ServerName www.example.com
# real server configuration
</VirtualHost>
And then you'll have another <VirtualHost> section with ServerName www.example.com for your real server configuration. Apache automatically preserves anything after the / when using the Redirect directive, which is a common misconception about why this method won't work (when in fact it does).
http://example.com/subdir/?lold=13666 => http://www.example.com/subdir/?lold=13666
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
<VirtualHost *:80>
ServerAlias example.com
RedirectMatch permanent ^/(.*) http://www.example.com/$1
</VirtualHost>
To remove www from your URL website use this code in your .htaccess file:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1$1 [R=301,L]
To force www in your website URL use this code on .htaccess
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^YourSite.com$
RewriteRule ^(.*)$ http://www.yourSite.com/$1 [R=301]
RewriteCond %{REQUEST_fileNAME} !-d
RewriteCond %{REQUEST_fileNAME} !-f
RewriteRule ^(([^/]+/)*[^./]+)$ /$1.html [R=301,L]
Where YourSite.com must be replaced with your URL.
<VirtualHost *:80>
DocumentRoot "what/ever/root/to/source"
ServerName www.example.com
<Directory "what/ever/root/to/source">
Options FollowSymLinks MultiViews Includes ExecCGI
AllowOverride All
Order allow,deny
allow from all
<What Ever Rules You Need.>
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName example.com
ServerAlias *.example.com
Redirect permanent / http://www.example.com/
</VirtualHost>
This is what happens with the code above. The first virtual host block checks if the request is www.example.com and runs your website in that directory.
Failing which, it comes to the second virtual host section. Here anything other than www.example.com is redirected to www.example.com.
The order here matters. If you add the second virtualhost directive first, it will cause a redirect loop.
This solution will redirect any request to your domain, to www.yourdomain.com.
Cheers!
This is similar to many of the other suggestions with a couple enhancements:
No need to hardcode the domain (works with vhosts that accept multiple domains or between environments)
Preserves the scheme (http/https) and ignores the effects of previous %{REQUEST_URI} rules.
The path portion not affected by previous RewriteRules like %{REQUEST_URI} is.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ %{REQUEST_SCHEME}://www.%{HTTP_HOST}/$1 [R=301,L]
Redirection code for both non-www => www and opposite www => non-www. No hardcoding domains and schemes in .htaccess file. So origin domain and http/https version will be preserved.
APACHE 2.4 AND NEWER
NON-WWW => WWW:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ %{REQUEST_SCHEME}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
WWW => NON-WWW:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ %{REQUEST_SCHEME}://%1%{REQUEST_URI} [R=301,L]
Note: not working on Apache 2.2 where %{REQUEST_SCHEME} is not available. For compatibility with Apache 2.2 use code below or replace %{REQUEST_SCHEME} with fixed http/https.
APACHE 2.2 AND NEWER
NON-WWW => WWW:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
... or shorter version ...
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|offs
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
WWW => NON-WWW:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
... shorter version not possible because %N is available only from last RewriteCond ...
RewriteCond %{HTTP_HOST} ^!example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
This starts with the HTTP_HOST variable, which contains just the domain name portion of the incoming URL (example.com). Assuming the domain name does not contain a www. and matches your domain name exactly, then the RewriteRule comes into play. The pattern ^(.*)$ will match everything in the REQUEST_URI, which is the resource requested in the HTTP request (foo/blah/index.html). It stores this in a back reference, which is then used to rewrite the URL with the new domain name (one that starts with www).
[NC] indicates case-insensitive pattern matching, [R=301] indicates an external redirect using code 301 (resource moved permanently), and [L] stops all further rewriting, and redirects immediately.
If you are using Apache 2.4 ,without the need to enable the rewrite apache module you can use something like this:
# non-www to www
<If "%{HTTP_HOST} = 'domain.com'">
Redirect 301 "/" "http://www.domain.com/"
</If>
I ran this...
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www.*$ [NC]
RewriteRule ^/.+www\/(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
I need this to be universal for 25+ domains on our new server, so this directive is in my virtual.conf file in a <Directory> tag. (dir is parent to all docroots)
I had to do a bit of a hack on the rewrite rule though, as the full docroot was being carried through on the pattern match, despite what http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html says about it only being stuff after the host and port.
Redirect domain.tld to www.
The following lines can be added either in Apache directives or in .htaccess file:
RewriteEngine on
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Other sudomains are still working.
No need to adjust the lines. just copy/paste them at the right place.
Don't forget to apply the apache changes if you modify the vhost.
(based on the default Drupal7 .htaccess but should work in many cases)
<VirtualHost *:80>
ServerAlias example.com
RedirectMatch permanent ^/(.*) http://www.example.com/$1
</VirtualHost>
This will redirect not only the domain name but also the inner
pages.like...
example.com/abcd.html ==> www.example.com/abcd.html example.com/ab/cd.html?ef=gh ==> www.example.com/ab/cd.html?ef=gh
This is simple!
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Try this:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteRule ^(.*) http://www.example.com$1 [R=301]
Do not always use Redirect permanent (or why it may cause issues in future)
If there is a chance that you will add subdomains later, do not use redirect permanent.
Because if a client has used a subdomain that wasn't registred as VirtualHost he may also never reach this subdomain even when it is registred later.
redirect permanent sends an HTTP 301 Moved Permanently to the client (browser) and a lot of them cache this response for ever (until cache is cleared [manually]). So using that subdomain will always autoredirect to www.*** without requesting the server again.
see How long do browsers cache HTTP 301s?
So just use Redirect
<VirtualHost *:80>
ServerName example.com
Redirect / http://www.example.com/
</VirtualHost>
Apache.org - When not to use mod_rewrite
Apache.org - Canonical Hostnames
To 301 redirect all requests made directly to the domain to www you can use:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^([^.]+\.[^.]+){2,}$ [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
The benefit of this is that this will work if you have any valid subdomains, e.g.
example.com REDIRECTED TO www.example.com
foo.example.com NO REDIRECT
bar.example.com NO REDIRECT
RewriteEngine On
RewriteCond %{HTTP_HOST} ^yourdomain.com [NC]
RewriteRule ^(.*)$ http://www.yourdomain.com/$1 [L,R=301]
check this perfect work
-If you host multiple domain names (Optional)
-If all those domain names are using https (as they should)
-if you want all those domain names to use www dot domainName
This will avoid doble redirection (http://non www to http://www and then to https://www)
<VirtualHost *:80>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^(.*)$ https://www.%1$1 [R=301,L]
</VirtualHost>
And
<VirtualHost *:443>
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
You should change the redirection code 301 to the most convenient one
If you want to load only the https version of www, use the below configurations in apache virtual host file. all these can have in a single file.
redirecting all http to https of www:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://www.example.com/
</VirtualHost>
redirecting https non-www to https www:
<VirtualHost *:443>
ServerName example.com
Redirect permanent / https://www.example.com/
</VirtualHost>
real server configuration
<VirtualHost *:443>
ServerAdmin hostmaster#example.com
DocumentRoot "/path/to/your/sites/.htaccess-file-folder"
SetEnv APPLICATION_ENV "production"
<Directory "/path/to/your/sites/.htaccess-file-folder">
Options Indexes FollowSymLinks
DirectoryIndex index.php index.html
AllowOverride All
Order allow,deny
Allow from all
</Directory>
ServerName www.example.com
SSLEngine ON
SSLCertificateFile "/path/to/your/example.cert.pem"
SSLCertificateKeyFile "/path/to/your/example.key.pem"
ErrorLog /path/to/your/example.com-error.log
CustomLog /path/to/your/example.com-access.log combined
#Your other configurations if you have
</VirtualHost>
If using the above solution of two <VirtualHost *:80> blocks with different ServerNames...
<VirtualHost *:80>
ServerName example.com
Redirect permanent / http://www.example.com/
</VirtualHost>
<VirtualHost *:80>
ServerName www.example.com
</VirtualHost>
... then you must set NameVirtualHost On as well.
If you don't do this, Apache doesn't allow itself to use the different ServerNames to distinguish the blocks, so you get this error message:
[warn] _default_ VirtualHost overlap on port 80, the first has precedence
...and either no redirection happens, or you have an infinite redirection loop, depending on which block you put first.
I've just have a same problem.
But solved with this
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
This rule redirecting non-www to www.
And this rule to redirecting www to non-www
RewriteEngine On
RewriteCond %{HTTP_HOST} !^my-domain\.com$ [NC]
RewriteRule ^(.*)$ http://my-domain.com/$1 [R=301,L]
Refer from http://dense13.com/blog/2008/02/27/redirecting-non-www-to-www-with-htaccess/
I had a similar task on a WP Multisite, where the redirection rule had to be generic (for any given domain I'd add to the network). I solved first adding a wildcard to the domain (parked domain). Note the . after .com.
CNAME * domain.com.
And then I added the following lines to the .htaccess file at the root of my multisite. I guess it'd work for any site.
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
Hopefully this will help.
ps. If you'd like to redirect from not www to www, change the last line into
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
This works for me:
RewriteCond %{HTTP_HOST} ^(?!www.domain.com).*$ [NC]
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L]
I use the look-ahead pattern (?!www.domain.com) to exclude the www subdomain when redirecting all domains to the www subdomain in order to avoid an infinite redirect loop in Apache.
The code I use is:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
This is my own site's configuration, and works like a charm.
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin admin#domain.com
ServerName www.domain.com
ServerAlias domain.com
DocumentRoot /var/www/html/domain
<Directory /var/www/html/domain/>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Redirect non-www to www
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
</VirtualHost>
</IfModule>
I found it easier (and more usefull) to use ServerAlias when using multiple vhosts.
<VirtualHost x.x.x.x:80>
ServerName www.example.com
ServerAlias example.com
....
</VirtualHost>
This also works with https vhosts.