Add www and remove slash - regex

I am trying to always add www to my website and remove the slash at the end but only for the homepage.
I had this code:
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.example.com$1 [L,R=301]
However, since it was always removing the slash it lead to a bunch of problems with our images etc (because it would be pointing on http://www.example.commedia instead of http://www.example.com/media).
Anyone could point me out how to do this ?

As stated in the apache2 docs you obtain the desired results with the following rules:
RewriteCond "%{HTTP_HOST}" "!^www\." [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteRule "^/?(.*)" "http://www.%{HTTP_HOST}/$1" [L,R,NE]

Related

How to properly write a RewriteCond for https and subdomains

Thus far I've gotten this far with my RewriteConditions but it's from hacking and slashing from internet examples. They seems to behave a little funny at times, like showing the directory in the url, so I assume I'm not doing it right.
The desired behaviour: I have multiple subdomains all pointing to the same root. Based on the subdomain value I want to redirect to a sub-folder in the root. I also want to force HTTPS. I have multiple subdomains, but I'll only show two for the sake of brevity. All the other conditions are virtually identical.
Here's my .htaccess code:`
RewriteEngine On
RewriteCond %{HTTP_HOST} purchase.mydomain.com [NC]
RewriteCond %{REQUEST_URI} !purchase/
RewriteRule (.*) https://purchase.mydomain.com/purchase/$1 [L]
RewriteCond %{HTTP_HOST} booking.mydomain.com [NC]
RewriteCond %{REQUEST_URI} !booking/
RewriteRule (.*) https://booking.mydomain.com/booking/$1 [L]
`
Thank you,
Mike
Change your rules like this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(purchase|booking)\.mydomain\.com$
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
RewriteCond %{HTTP_HOST} =purchase.mydomain.com
RewriteRule ^((?!purchase/).*)$ /purchase/$1 [L]
RewriteCond %{HTTP_HOST} =booking.mydomain.com
RewriteRule ^((?!booking/).*)$ /booking/$1 [L]
http:// or https:// in target will redirect instead of rewriting.

Apache multiple rewrite conditions for a single rule

SOLVED: The problem was related to Symfony. See my answer below.
I recently changed the domain of my site, and I'd like to permanently redirect visitors to the new domain, excluding a few specific URLs that must remain accessible via the old domain. Here's what I tried. The issue is that redirection occurs, but the specified directories are not excluded.
RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example1/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example2/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example3/.*$ [NC]
RewriteCond %{REQUEST_URI} !/examplepage.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com%{REQUEST_URI} [R=301,L]
I also tried placing the following at the top of my configuration file, no luck.
RewriteRule ^(example1|example2|example3)($|/) - [L]
Edit: It's also worth noting that these directives seem to work for examplepage.html, it's just the "directories" that don't work. This is Apache 2.4.7
The following example URLs should all be left out of the rewriting process (so pretty much anything containing "/example1":
https://olddomain.com/example1
https://olddomain.com/example1/action1
https://olddomain.com/app.php/example1/action1
For the sake of completeness, the above directives are in my apache.conf file. In addition, Symfony2 provides a default .htaccess file with the following rewrite directives. Could there be some sort of contradiction here?
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the app.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Redirect to URI without front controller to prevent duplicate content
# (with and without `/app.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
# following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]
# Rewrite all other queries to the front controller.
RewriteRule .? %{ENV:BASE}/app.php [L]
Try this instead:
RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/example1 [NC]
RewriteCond %{REQUEST_URI} !^/example2 [NC]
RewriteCond %{REQUEST_URI} !^/example3 [NC]
RewriteCond %{REQUEST_URI} !/examplepage.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com/$1 [R=301,L]
I think you are making the folder conditions overly complex. Also note that you can use $1 in the last line to just carry over the value caught in the () in the left side of the line. Makes no difference in this example, but would if you needed only part of the left hand side to be used in the destination URL on the right.
I figured it out. If anyone else runs into a similar issue, the problem is due to Symfony issuing an [INTERNAL REDIRECT] on all URLs to /app.php. /app.php is then passed through the gauntlet of rewrite conditions for a second round. Excluding app.php in your rewrite conditions will solve it.
RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/example1/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/example2/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/example3/.*$ [NC]
RewriteCond %{REQUEST_URI} !/app.php [NC]
RewriteCond %{REQUEST_URI} !/examplehtml.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com/$1 [R=301,L]

Apache Rewrite Issue. Unable to figure out query string

So I have been struggling on finding the rule to match this rewrite. I am working on a client website and it is a nightmare with the number of duplicate title tags. I have managed to resolve most of them by enforcing forward slash, redirect non www. to the www. version and disallow crawling of https version of the website.
The issue I am having at the moment. I have over 1000 URLs that are duplicate content, each product has two different URLs with the exact same content. An example is:
http://www.example.co.uk/product/widget1/
http://www.example.co.uk/widget1/
http://www.example.co.uk/product/widget2/
http://www.example.co.uk/widget2/
Now the following URLs have the same content:
http://www.example.co.uk/product/widget1/
http://www.example.co.uk/widget1/
I want to redirect any URL that contains "/product/" to the URL version without "/product/" in the URL if that makes sense. I honestly don't know where to start and would really appreciate the help.
Thanks in advance
EDIT: The recommended rule:
RewriteEngine On
RewriteRule ^/product/(.*)$ /$1 [R=301]
does not work. It may be conflicting. These are the other rules:
RewriteEngine On
RewriteCond %{QUERY_STRING} .+
RewriteRule ^(.*)$ /$1? [R=301,L]
RewriteRule ^/product/(.*)$ /$1 [R=301]
RewriteCond %{HTTP_HOST} ^example\.co [NC]
RewriteRule (.*) http://www.example.co.uk/$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)([^/])$ /$1$2/ [L,R=301]
I dont know if there are any conflicts here. Please help
Have your full .htaccess like this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.co [NC]
RewriteRule (.*) http://www.example.co.uk/$1? [L,R=301]
RewriteCond %{QUERY_STRING} .+
RewriteRule ^(.*)$ /$1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+?[^/])$ /$1/ [L,R=301]
RewriteRule ^product/([^/]+)/?$ /$1/ [R=301,L]
Assuming the URLs always start with product, this should work:
RewriteEngine On
RewriteRule ^/product/(.*)$ /$1 [R=301]
It'll need to go in your main site conf or .htaccess

Fixing a RewriteRule that adds two extra slashes

I'd like to redirect web requests from example.org to www.example.org. I think I have the right rule, but it is adding two extra forward slashes:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.org [NC]
RewriteRule ^(.*)$ http://www.example.org/$1 [R=permanent,L]
The above would take me from example.org to www.example.org//
Is there a way to strip those trailing slashes? I tried the following variant, which strips those slashes but causes a redirect loop:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.org [NC]
RewriteRule ^(.*)$ http://www.example.org/$1 [R=permanent,L]
RewriteRule ^(.*)/$ /$1 [L,R=301]
How might I solve this?
Try adding RewriteBase / right after RewriteEngine on.
If that doesn't do it, change your rule to RewriteRule ^/(.*)$ http://www.example.org/$1 [R=301,L] so you don't capture the initial /.

Problem using .htaccess to replace characters in URL

I've tried dozens of different ways of doing this but can't get any of them to work. My .htaccess does a few things, like setting a custom 404 and blocking image hotlinking. I want to do two things on the URL: add www. if it isn't there (rather annoying Facebook login can't cope with two different sources!), and replacing // with / except after http:.
I've tried this:
# Replace // with /
RewriteCond %{REQUEST_URI} (.*)(?<!http:)\/{2,5}(.*)
RewriteRule .* %1/%2 [R=301,L]
And this:
# Replace // with /
RewriteCond %{REQUEST_URI} (.*).com\/\/(.*)
RewriteRule .* %1.com/%2 [R=301,L]
And all sorts of permutations. Can anybody tell me what I'm doing wrong?
I need to do this because sometimes multiple /s are being inserted between the .com and the rest of the URL.
Thanks
I don't think http:// is part of REQUEST_URI at all (or of any other environment variable for that matter). It will get parsed out by the browser, and used to determine the nature of the request, long before the actual request is made.
I can be wrong, but I think this is not fixable on htaccess level. The link would have to be properly formatted in the first place.
Update: Looking at the information Apache passes on to PHP, I think I'm right. The protocol used to make the request is not part of the URI components we get to play with.
Here's how to force www.:
<IfModule mod_rewrite.c>
#Add WWW
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
#End Add WWW
</IfModule>
Considering what #Tim mentioned below, I would check %{REQUEST_URI} if it contains //, and that would be my RewriteCond:
<IfModule mod_rewrite.c>
#Replace // with /
RewriteCond %{REQUEST_URI} // [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
#End Replace // with /
</IfModule>
I'm not sure why you're experiencing trouble with the multiple slashes, since it should be able to resolve the file either way. However, it is possible to check for and remove them with a redirect (I've combined this with your force-www so there's at most one external redirection):
RewriteCond %{THE_REQUEST} ^[A-Z]+\s[^\s]*/{2,} [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteRule ^ http://www.%2%{REQUEST_URI} [R=301,L]
Note that %{REQUEST_URI} has the duplicate slashes removed (only in mod_rewrite, this isn't true for scripts later on), so we can use it in the redirect to automatically take care of that issue for us. The original request will still have the multiple slashes though, so we check for them by examining %{THE_REQUEST}.