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

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

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]

mod_rewrite redirect url if no file found to main page

I want to be able to Access my scripts without the .php, .html etc., so I already wrote
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.php -f
RewriteRule ^(.*)$ $1.php
##same for other extensions
in my .htaccess file (note: this file lies not in the root-path), but I also want to Redirect every incorrect request to my main page, so that www.mysite.com/dir/incorrect will be rewritten to www.mysite.com/dir/.
But my first try (RewriteRule ^ / [R] after RewriteCond) redirected me to www.mysite.com/, my experiments with RewriteBase (RewriteBase . and RewriteBase /) didnt work and I also noticed that many similar scriptredirect to www.mysite.com/dir/index.php (www.mysite.com/dir/index in my case), but I really want to Redirect to www.mysite.com/dir/. Is there any way to achieve this?
Have it this way:
RewriteEngine on
# see if .php is found
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.php -f
RewriteRule ^(.*)$ $1.php [L]
# determine DIR_BASE dynamically
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=DIR_BASE:%1]
# if not found redirect to %{ENV:DIR_BASE}
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ %{ENV:DIR_BASE} [L,R]

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

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/"/>

htaccess issue causing internal server error too many redirects

so I am playing with .htaccess to have clean URLs in my codeigniter app.
in short, i am trying to:
1) remove index.php in urls (redirect permanent)
http://localhost/directory/index.php*
to
http://localhost/directory/*
http://my.domain.com/index.php*
to
http://my.domain.com/*
2) rewrite requests for certain controllers to index.php/[controller_name]
http://localhost/directory/controller1*
to
http://localhost/directory/index.php/controller1*
http://my.domain.com/controller2*
to
http://my.domain.com/index.php/controller2*
my htaccess file currently goes like this:
Options +FollowSymlinks
RewriteEngine On
#RewriteBase /
# Redirect index.php
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{THE_REQUEST} !/system/.*
RewriteRule ^(.*)index\.php((/)(.*))?$ /$1/$4 [R=301,L]
first issue:
this does not work for http://localhost/dir/index.php/controller1.
instead redirecting to http://localhost/dir/controller1, it redirects to http://localhost//controller1 ($1 return empty string?)
# Rewrite CI certain controllers
RewriteCond %{THE_REQUEST} directory/(home|other_controller) [NC]
RewriteRule ^(.*)(home|other_controller)(.*)$ /$1index.php/$2$3 [NC,L]
second issue:
this does not work for http://localhost/dir/home gives internal server error (too many redirects).
but if I test added R=301 code, it successfully redirect to http://localhost/dir/index.php/home. but this is not my intention to redirect, I only need to rewrite it.
please advise.. :)
Try with this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
You can place this in the directory the bootstrap file (index.php) is in.
If you have FastCGI implementation, you need to add a question mark in the rewrite rule:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]

Can't work out rewrite rule

I am trying to setup a rewrite rules(s) that will:
redirect anything but /path and files to another site
then if path is /path/*, rewrite the url to index.php
Here is my rules:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/path.*
RewriteRule !\.(js|gif|css|jpg|png|jpeg) http://www.domain.com [R,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA]
</IfModule>
For some reason it's not working.
Other than making sure that you have mod_rewrite turned on, you need to change your first condition to also check for index.php, because after the second rule, the process loops and you end up getting redirected to domain.com:
Change:
RewriteCond %{REQUEST_URI} !^/path.*
to:
RewriteCond %{REQUEST_URI} !^/(path|index.php)