Remove or add trailing slash from CakePHP 2.x on Apache using .htaccess - apache

I am trying to enforce the removal or add of trailing slashes to my CakePHP 2.x app using the following inside the .htaccess located at /app/webroot.
#<IfModule mod_rewrite.c>
# RewriteEngine On
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteRule ^ index.php [L]
#</IfModule>
<IfModule mod_rewrite.c>
# Add trailing slash
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|)$
RewriteRule ^(.*)$ http://www.domain.com/$1 [L,R=301]
</IfModule>
or the following for add the trailing slash.
RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.*) %{REQUEST_URI}/ [R=301,L]
But I don't want to enforce the domain as it could be running locally or inside a subfolder. How do I fix this? All the docs I've read online seem to enforce the FULL url of the app.
In fact even if I use the FULL url it still doesn't work. Has anyone managed to get this working with CakePHP? Seems you MUST run it through the index.php file
To clarify I'm looking for a solution for ADDING and REMOVING trailing slashes in CakePHP without having to hardcode the url into the .htaccess file.

This is usually not a complicated thing.
What about this ?
<IfModule mod_rewrite.c>
RewriteEngine On
# if this is an existing folder/file then leave
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [L]
# if trailing slash then redirect to url without trailing slash
RewriteRule ^/?(.+)/$ /$1 [R=301,L]
# internal rewrite to controller/dispatcher index.php
RewriteRule ^.*$ /index.php [L,QSA]
</IfModule>
If this one is not working, well this could be a problem on your side.
Did you already use mod_rewrite before ? Is it enabled ?
EDIT: if your website is not in root folder (DOCUMENT_ROOT) you have 2 options. You could put your htaccess in application folder or in root folder.
I suggest you to put your htaccess in your application folder (dedicated for your website only). Otherwise, the code would not be exactly the same. Here's the code in this case:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /application/
# if this is an existing folder/file then leave
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [L]
# if trailing slash then redirect to url without trailing slash
RewriteRule ^/?(.+)/$ $1 [R=301,L]
# internal rewrite to controller/dispatcher index.php
RewriteRule ^.*$ index.php [L,QSA]
</IfModule>
Your second question:
Also what would be the code for ENFORCING a trailing slash?
You could handle that with this code (only one line changed)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /application/
# if this is an existing folder/file then leave
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [L]
# if no trailing slash then redirect to url with trailing slash
RewriteRule ^/?(.+)([^/])$ $1$2/ [R=301,L]
# internal rewrite to controller/dispatcher index.php
RewriteRule ^.*$ index.php [L,QSA]
</IfModule>

Try this :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|)$
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [L,R=301]
</IfModule>

Try this (bakery):
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
#RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [L,R=301]
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [L,R=301]
If you want to do it for SEO you always have an option to use canonical links and stop bother about redirects:
<link rel="canonical" href="/your_controller/action/"/>

Related

.htaccess language based RewriteRule like example.com/en/

I'm trying to write redirect directives in the .htaccess to forward internally all user requests like this:
Every request in a language folder should redirect to the requested file with the language query string:
example.com/en/contact.php -> example.com/contact.php?lang=en
Redirect any request without language path to a default language folder like this:
example.com -> example.com/en
Remove trailing slash if the address is entered with it:
example.com/en/ to example.com/en
For the folder projects, every request should lead to the view-project.php file with the respective query strings:
example.com/en/projects/test -> example.com/view-project.php?lang=en&path=test
Here is my attempt, but it's not working without trailing slash on a request like: http://www.example.com/de and is not redirecting http://www.example.com to a default language folder.
RewriteEngine On
RewriteRule ^(en|de)/(.*)$ $2?lang=$1 [L,QSA,NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^projects/([^/\.]+)/?$ view-project.php?path=$1 [QSA,L]
How can I achieve this?
This is possible a duplicate and I apologize for that. I searched everywhere and read about 100 posts, but I did't found what I'm looking for.
after struggling a while and with the help of someone else, here is the .htaccess file that works for me:
RewriteBase /example.com/
DirectorySlash Off
RewriteEngine On
RewriteOptions AllowNoSlash
RewriteRule ^$ de [R=301,L]
RewriteRule ^(de|en)/$ $1 [R=301,L]
RewriteRule ^(de|en)$ index.php?lang=$1 [L]
RewriteRule ^(de|en)/projects/(.+) view-project.php?lang=$1&path=$2 [L,QSA]
RewriteRule ^(de|en)/(.+) $2?lang=$1 [L,QSA]
Try:
RewriteEngine On
RewriteBase /mysite.com/
RewriteCond %{HTTP:Accept-Language} (en|de) [NC]
RewriteRule ^ /%1/index.php [L]
RewriteCond %{HTTP:Accept-Language} (en|de)
RewriteCond %{DOCUMENT_ROOT}%1%{REQUEST_URI} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule ^(en|de)/(.+)$ $2&lang=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^projects/([^/\.]+)/?$ view-project.php?path=$1 [QSA,L]
Edit:
The above was before the detailed explanation: After the detailed explanation, I've come up with this solution which is very similar to the solution the author has come up with while I was not aware about the edit explaining the situation:
DirectorySlash Off # disables mod_dir slash redirect
RewriteEngine On
RewriteBase /mysite.com/ # rewrites inside /mysite.com/
RewriteOptions AllowNoSlash # stops ignoring the directory redirects that redirect directories without slash, so by default: example.com/dir1 -> example.com/dir2 would be ignored. This is used because DirectorySlash is off
RewriteRule ^(en|de)\/projects\/(.+)$ view-project.php?lang=$1&path=$2 [QSA,L] # rule 4
RewriteRule ^(en|de)\/(.*)$ $2?lang=$1 [QSA,L] # rule 1
RewriteRule ^$ en [R=302,L] # rule 2
RewriteRule ^(en|de)\/$ $1 [R=302,L] # rule 3

htaccess RewriteRule rewrite to subfolder

I am trying to rewrite the url 'test' to a subdirectory in /public. This is a Laravel App end I want to run the content in public/test independend of Laravel so I should be prevented to go through the Laravel router.
/test/whatever should be invisbly forwarded to /public/test/whatever (The url should stay /test/whatever).
I now have this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/test/ [NC]
RewriteRule ^(.*)$ public/test/$1 [L]
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
So far this is forwarding to: /public/test/test/(index.php)
I think I am close...
Update:
In the public directory is also a .htaccess file (Original, from Laravel 5.4):
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>
You only need the last rule
RewriteRule ^(.*)$ public/$1 [L]
for the root dir .htaccess file. This will rewrite everything to the public/.htaccess, including requests starting with /test.
As long as public/test/ is a directory, and any requested URLs starting with /test/ are real files inside public/test, this will be sufficient, because the conditions
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
will prevent existing files and directories to be handled by index.php.
If test is not an existing directory, or the requests for /test/... are not real files, you need additional rules. Possibly in /public/.htaccess or in /public/test/.htaccess.
The reason for /test being rewritten to /public/test/test was the combination of
# /.htaccess
RewriteRule ^(.*)$ public/test/$1 [L]
where (.*) already includes test, which becomes public/test/test, and then
# /public/.htaccess
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
because public/test/test is not an existing file or directory (-> RewriteCond), and is therefore handled by this rule.

.htaccess: Redirect 301 conflict with rewriterule

I recently updated an old website and I want to 301 all the old pages to the new version of each of them.
Here is my .htaccess
Options +FollowSymlinks -MultiViews
RewriteEngine On
#
# below are the 301 redirects
# **rules**
#
# below are the RewriteCond
# **rules**
#
# other stuff
#
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+?)/?$ $1.php [NC,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ /$1 [R=301,L]
The problem is that some of the old link are with the extension declared oldfile.html, others are just folders oldfolder/.
On the new version there are products, products/category and products/category/subcategory. These urls are generated with RewriteCond.
The following rule works:
Redirect 301 /category/ /products/category
The following does not work and instead redirects me to the home page.
Redirect 301 /old-folder/subcategory.html /products/category/subcategory
# /products/category/subcategory is also a RewriteRule
Here is the exact code in the .htaccess
# 301 rule
Redirect 301 /arredo-urbano/blocchi-standard.html /prodotti/arredo-urbano/001-blocchi-standard
# RewriteRule
RewriteRule ^prodotti/([^/]+)/([^/]+)/?$ prodotti.php?category=$1&subcategory=$2 [L]
I tried adding the [L] flag after each Redirect 301 so the rest of the .htaccess is ignored, but this causes a 500 Internal Error
All redirects are manually declared, with no regular expressions or wildcards and they are all spelled correctly.
Is there a way of making all redirect work as intended ? Also the thing that I do not understand is why the [L] flag causes an internal error.
Thank you
Three recommendations about redirect rules in general:
Keep redirect rules before internal rewrite rules
Keep specific patterns matching rules before generic pattern matching rules
Don't mix Redirect (mod_alias) rules with RewriteRule (mod_rewrite) rules.
Try these rules in your .htaccess:
Options +FollowSymlinks -MultiViews
RewriteEngine On
RewriteRule ^category/?$ /products/category [L,NC,R=301]
RewriteRule ^old-folder/subcategory\.html$ /products/category/subcategory [L,NC,R=301]
#
# below are the 301 redirects
# **rules**
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ /$1 [R=301,L]
#
# below are the RewriteCond
# **rules**
#
# other stuff
#
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
Make sure to clear your browser cache before testing this change.

.Htaccess - Remove trailing slash, whilst all pages still go to index.php

I've searched over previously asked questions but none have the same problem as me. I'm wanting to remove the trailing slash, whilst still sending all pages to index.php (or if the file actually exists, use that.)
I'd like a solution that I don't have to fiddle with between server and localhost.
So localhost/pages/to/file/ and http://example.com/pages/to/file/, go to ... /pages/to/file
My current htaccess file:
RewriteEngine on
# removes www.
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1%{REQUEST_URI} [R=301,QSA,NC,L]
# if file exists, ignore the index.php re-write
RewriteCond %{REQUEST_FILENAME} !-f
# send everything to index.php
RewriteRule . index.php
Give the following a try:
RewriteEngine on
# Remove the trailing slash, if not in a directory
# DirectorySlash off can be used instead.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Remove www. (generic method with HTTPS support)
RewriteCond %{HTTP_HOST} ^www\.
RewriteCond %{HTTPS}s ^on(s)|off
RewriteCond http%1://%{HTTP_HOST} ^(https?://)(www\.)?(.+)$
RewriteRule ^ %1%3%{REQUEST_URI} [R,L]
# Send everything (except existing files) to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
If this works for you, change the R flag to R=301 to make the redirect permanent.
You can add an extra condition to your existing rule to remove www and remove any trailing slash in that rule too.
RewriteEngine on
# removes www. and trailing slash
RewriteCond %{REQUEST_URI} /$ [OR]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*?)/?$ http://%1/$1 [R=301,QSA,NC,L]
# if file exists, ignore the index.php re-write
RewriteCond %{REQUEST_FILENAME} !-f
# send everything to index.php
RewriteRule . index.php
See the documentation for clarification.
Have a separate rule for removal of trailing slash:
RewriteEngine on
# removes www.
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,NE,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} \s/+(.*?)[^/][?\s]
RewriteRule [^/]$ %{REQUEST_URI}/ [L,NE,R=301]
# if file/directory exists, ignore the index.php re-write
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# send everything to index.php
RewriteRule . index.php [L]

SocialEngine - Redirects in .htaccess

I've completed a fresh install of SocialEngine PHP in my private server.
I also need now to install Moodle, and access in the following way to it:
http://www.example.com/moodle
SocialEngine creates its own .htaccess file, so every time I try to access the moodle directory, I got a "Page Not Found. The page you have attempted to access could not be found." because the redirection forces it to search moodle inside SocialEngine plugins, and I want it to redirect to a /moodle/ directory inside /httpdocs.
I am very noob with .htaccess options, I need a hint about what can I do.
The .htaccess content is the following:
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
# Get rid of index.php
RewriteCond %{REQUEST_URI} /index\.php
RewriteRule (.*) index.php?rewrite=2 [L,QSA]
# Rewrite all directory-looking urls
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*) index.php?rewrite=1 [L,QSA]
# Try to route missing files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} public\/ [OR]
RewriteCond %{REQUEST_FILENAME} \.(jpg|gif|png|ico|flv|htm|html|php|css|js)$
RewriteRule . - [L]
# If the file doesn't exist, rewrite to index
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?rewrite=1 [L,QSA]
</IfModule>
# sends requests /index.php/path/to/module/ to "index.php"
# AcceptPathInfo On
# #todo This may not be effective in some cases
FileETag Size
Any suggestion or tip, please?
Thank you very much in advance!
Regards.
I would exclude the moodle-folder in every rewrite and check if it works. After it is working I would remove it in every rule where you don't really need it.
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
# Get rid of index.php
RewriteCond %{REQUEST_URI} !^/moodle
RewriteCond %{REQUEST_URI} /index\.php
RewriteRule (.*) index.php?rewrite=2 [L,QSA]
# Rewrite all directory-looking urls
RewriteCond %{REQUEST_URI} !^/moodle
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*) index.php?rewrite=1 [L,QSA]
# Try to route missing files
RewriteCond %{REQUEST_URI} !^/moodle
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} public\/ [OR]
RewriteCond %{REQUEST_FILENAME} \.(jpg|gif|png|ico|flv|htm|html|php|css|js)$
RewriteRule . - [L]
# If the file doesn't exist, rewrite to index
RewriteCond %{REQUEST_URI} !^/moodle
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?rewrite=1 [L,QSA]
</IfModule>
# sends requests /index.php/path/to/module/ to "index.php"
# AcceptPathInfo On
# #todo This may not be effective in some cases
FileETag Size