Redirect subdomain to subdirectory - trailing slash - apache

I want to redirect [abc].apps.example.com to the following apps.example.com/[abc] but still showing the using the [abc].apps.example.com in the url.
[abc] an be anything eg.
calendar.apps.example.com
books.apps.example.com
etc
With a bit of digging around and tweaking, I have the following setup but doesn't work when an ending slash is missing:
RewriteEngine On
RewriteBase /
# Fix missing trailing slashes.
RewriteCond %{HTTP_HOST} !^www\.apps\.example\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.apps\.example\.com$ [NC]
RewriteCond %{DOCUMENT_ROOT}/%2%{REQUEST_URI}/ -d
RewriteRule [^/]$ %{REQUEST_URI}/ [R=301,L]
# Rewrite sub domains.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} !^www\.apps\.example\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.apps\.example\.com$ [NC]
RewriteRule ^.*$ /%2/$0 [QSA,L]
When the following is entered:
calendar.apps.example.com/showcalendar/
it's redirected correctly to: apps.example.com/calendar/showcalendar/
But for when a trailing slash is missing
calendar.apps.example.com/showcalendar
I get a 404 error saying /calendar/calendar/showcalendar/ not found.
Please, if you know what's wrong with the above code or have a better solution do let me know.
Cheers,
Doggy

try the following rewrite rule for adding trailing slashes.
# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*[^/]$ /$0/ [L,R=301]

Related

.htaccess - remove everything after third slash in path

On my website, I only use 3 slashes in my URL path:
https://example.com/this/isatest/
Right now I use .htaccess which makes it possible (as a side effect) to add as many stuff on the URL as you like:
https://example.com/this/isatest/hipperdihopperdus/pizza/bacon/with/cheese
I'd like to automatically remove everything after "isatest" while keeping the trailing slash using .htaccess.
This is what my .htaccess currently looks like:
Options -Indexes
Options +FollowSymLinks
RewriteEngine on
# 301 Redirect all requests that don't contain a dot or trailing slash to
# include a trailing slash
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !\.
RewriteRule ^(.*) %{REQUEST_URI}/ [R=301,L]
RewriteCond %{THE_REQUEST} /index\.html [NC]
RewriteRule ^index\.html$ /? [R=301,L,NC]
RewriteRule ^listen/$ /console/ [NC,L]
# Rewrites urls in the form of /parent/child/
# but only rewrites if the requested URL is not a file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?page=$1 [L,QSA]
How can I achieve this?
As your first rule, after the RewriteEngine directive, you can do something like the following:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
This checks if there is anything else (the dot) after two path segments and a slash, and redirects to removed "anything else".
Note that this is a 302 (temporary) redirect. Only change this to a 301 (permanent) redirect - if that is the intention - once you have confirmed that it works OK. This is to avoid the browser caching erroneous redirects whilst testing.
UPDATE: It may be more efficient to simply avoid redirecting files that end in a recognised file extension. Or perhaps exclude known directory location(s) of your static resources. For example:
RewriteCond %{REQUEST_URI} !\.(css|js|jpg|png|gif)$ [NC]
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
OR,
RewriteCond %{REQUEST_URI} !^/static-resources/
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
You can add this rule just below RewriteEngine On line:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+/[^/]+/).+$ /$1 [R=301,L,NE]

Cannot make htaccess redirect www to non-www

The 3 comments in the code explain fairly accurate what I want to achieve.
<IfModule mod_rewrite.c>
RewriteEngine On
# Change secretdiary.org/index.php?url=URL to secretdiary.org/URL on the browser's url
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
# Redirect http://www.secretdiary.org/ to http://secretdiary.org/
RewriteCond %{HTTP_HOST} !^secretdiary.org$ [NC]
RewriteRule ^(.*)$ http://secretdiary.org/$1 [L,R=301]
# Add trailing slash / if there's none
RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.*) %{REQUEST_URI}/ [R=301,L]
</IfModule>
However, I am finding some problems and I think they come from putting the conditions together. When I enter www.secretdiary.org/about , it gets (showing it in the browser) to secretdiary.org/index.php?url=about, deleting the www but ignoring the first rule. Switching the order did not help at all nor messing with RewriteBase. However, if I enter normally without the www, the uri is shown normally, secretdiary.org/about, without any rewriting. Why is this and how can I fix it?
Besides, I've followed this answer and this other attempting to add automatically a trailing slash to the uri if missing. I could achieved it with PHP ( if (substr($_GET['url'], -1) != "/") header("Location: " . htmlspecialchars($_GET['url']) . '/');, but now it bothers me that I cannot achieve it with .htaccess, so if you could also spot where's the problem here it'd be very helpful.
Try this .htaccess code :
RewriteEngine On
# Change secretdiary.org/index.php?url=URL to secretdiary.org/URL on the browser's url
RewriteCond %{HTTP_HOST} ^secretdiary.org$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [L]
# Redirect http://www.secretdiary.org/ to http://secretdiary.org/
RewriteCond %{HTTP_HOST} !^secretdiary.org$ [NC]
RewriteRule ^(.*)$ http://secretdiary.org/$1 [R=301]
# Add trailing slash / if there's none
RewriteRule ^([^/]*)[^/]$ $1/ [R=301,L]
I'm not sure for the last rule.
The main problem I faced was with Firefox storing the 301 redirect, which made the changes in .htaccess "not work". I deleted the cache and now it's working perfectly, although I made the trailing slash to be added with PHP to avoid headaches.
.htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
# For some shady reason, this redirect should be first.
# Redirect http://www.secretdiary.org/ to http://secretdiary.org/
RewriteCond %{HTTP_HOST} !^secretdiary.org$ [NC]
RewriteRule ^(.*)$ http://secretdiary.org/$1 [L,R=301]
# Change secretdiary.org/index.php?url=URL to secretdiary.org/URL on the browser's url
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
</IfModule>
index.php:
<?php
// Redirect if there's no trailing slash
if (!empty($_GET['url']) && substr($_GET['url'], -1) != "/")
{
header ('HTTP/1.1 301 Moved Permanently');
header ("Location: http://secretdiary.org/" . htmlspecialchars($_GET['url']) . "/");
}
// The rest of the php

Non www to www redirect doesn't removes trailing backslash

I'm having a bit of problem with Apache redirect.
While bellow rules work for any page on site, mydomain.com will get redirected to mydomain.com//, which ignores trailing slash removal rule.
Also is it efficient to use multiple rules such as this or should I try to combine them or chain them somehow together in order to avoid multiple redirects for single url?
Thanks
#Turn on options for url rewriting
Options +FollowSymlinks
RewriteEngine on
#lovercase all urls
RewriteMap lc int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteCond %{REQUEST_URI} ^/fonts/.*
RewriteCond %{REQUEST_URI} ^/css/.*
RewriteCond %{REQUEST_URI} ^/js/.*
RewriteRule (.*) ${lc:$1} [R=301,L]
#redirect all requests made to http:// to http://www.
RewriteCond %{HTTP_HOST} ^mydomain\.com$ [NC]
RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R=301,L]
#removes trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^\.localhost$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}$1 [R=301,L]
The reason the mydomain.com gets redirected to www.mydomain.com// is because you have an extra "/" in your rewrite rule target:
RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R=301,L]
^----here
When you have rules in your server/vhost config, the leading slash isn't removed so that gets match and used as a backreference, so mydomain.com is / which matches ^(.*)$ and the target becomes http://www.mydomain.com//. So you can either remove the slash in the target or add one to the regex:
RewriteRule ^(.*)$ http://www.mydomain.com$1 [R=301,L]
or
RewriteRule ^/(.*)$ http://www.mydomain.com/$1 [R=301,L]
Your other rule you have:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^\.localhost$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}$1 [R=301,L]
are fine. They are for removing trailing slashes when there is something between them, e.g. /something/, because of the (.+). It wouldn't match // anyways because that inherently gets turned into just /. You just need to prevent redirecting to http://www.mydomain.com//

How to remove multiple trailing slashes?

Here are my rewrite rules:
###########
# Rewrite #
###########
# Settings
RewriteEngine On
RewriteBase /
# Cache Busting
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} "^(.+)\.\d+\.(css|js)$" [NC]
RewriteRule "^.*$" "/%1.%2" [L]
# No Index
RewriteCond %{THE_REQUEST} "\ /.*index\.php.*\ " [NC]
RewriteRule "^(.*)index\..+$" "/$1" [L,NC,R=301]
# No Question Mark
RewriteCond %{THE_REQUEST} "\ /[^?]*\?\ "
RewriteRule "^(.*)$" "/$1?" [L,R=301]
# WWW
# RewriteCond %{HTTP_HOST} !"^(?:static|www)\.(.+)$" [NC]
# RewriteCond %{HTTPS}s "^on(s)|"
# RewriteRule "^(.*)$" http%2://www.%1/$1 [L,R=301]
Everything works fine (any suggestion to improve performances or for better regexps is welcome, anyway) but I'm experiencing a weird situation and I can't understand if it's produced by my rewrite rules or by a default Apache behavior.
If my URL ends with a "/", I can append as many slashes as I want without it being rewritten.
For example, if in my address bar I insert the following:
http://[MY-HOST-NAME]////////////////////////////
All those slashes are not being removed. And I'm still seeing my index.php page.
If I insert the following address:
http://[MY-HOST-NAME]/members///
All those multiple slashes are not being removed and I can see my members index.php page.
And so on...
Can someone help me please? Many thanks!
RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R]
# rule 1: remove multiple leading slashes (directly after the TLD)
RewriteCond %{THE_REQUEST} \s/{2,}
RewriteRule (.*) $1 [R=301,L]
# rule 2: remove multiple slashes in the requested path
RewriteCond %{REQUEST_URI} ^(.*)/{2,}(.*)$
RewriteRule (.*) %1/%2 [R=301,L]
RewriteEngine on
RewriteBase /
#existing rule
#remove the www.
RewriteCond %{HTTP_HOST} ^www.website.co.uk$ [NC]
RewriteRule ^(.*)$ http://local.website.co.uk/$1 [R=301,L]
#new Rule
#if its not a directory
RewriteCond %{REQUEST_FILENAME} !-d
#and it has a trailing slash then redirect to URL without slash
RewriteRule ^(.+)/$ /$1 [L,R=301]
# rest of your existing rules go here
Gerbens answer works well for .htaccess but not so much for global config.
This one removes all the slashes before sending the redirect.
# if match set environment variable and start over
RewriteRule ^(.*?)//+(.*)$ $1/$2 [E=REDIR:1,N]
# if done at least one. redirect with 301
RewriteCond %{ENV:REDIR} 1
RewriteRule ^/(.*) /$1 [R=301,L]

Adding slashes to the end of directories + more (htaccess)

This is beyond my level and I need some help.
In the htaccess make redirect rules for the following...
if example.com/1stleveldirectory doesn't end in a slash add one.
if example.com/1stleveldirectory/ ends in a slash don't add anything.
if example.com/1stleveldirectory/file is like this add .html.
if example.com/1stleveldirectory/file.html is like this don't add anything.
There are no publicly accessible directories past the first level
Thanks!
EDIT: I should have said I already have this code at the top of the file.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.([^.]+.[^.]+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
Options +FollowSymLinks
RewriteRule ^([^/]*)/([^/]*)\.html$ /index.php?cat=$1&name=$2 [L]
RewriteRule ^([^/]*)/$ /index.php?cat=$1 [L]
Try these rules:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^/]+$ %{REQUEST_URI}/ [L,R=301]
RewriteCond $0 !.+\.html$
RewriteRule ^[^/]+/[^/]+$ %{REQUEST_URI}.html [L,R=301]