Joomla: Permanently redirect from example.com/index.php/foo/bar to example.com/foo/bar (no index.php in URL) - apache

.htaccess
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
With this setup the page /foo/bar is accessible under the pretty URL example.com/foo/bar while the ugly URL example.com/index.php/foo/bar is still valid. What I need to achieve is a permanent redirection from example.com/index.php/foo/bar to example.com/foo/bar.
RewriteRule .* index.php [R=301,L] doesn't work.
RewriteRule (.*) index.php/$1 [R=301,L] does the exact opposite, it redirects from example.com/foo/bar to example.com/index.php/foo/bar. Please help me out!

I recommend writing this:
RewriteEngine On
RewriteBase /
# remove index.php from / OR any /dir
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteCond %{REQUEST_URI} ^(.*/)index\.php$ [NC]
RewriteRule ^ %1 [L,R=301,NE]
# redirect rule to remove /index.php/ from start
RewriteRule ^index\.php(/.*) $1 [L,R=301,NC]
RewriteCond %{REQUEST_URI} !^/index\.php [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
In the new rule, we match a pattern using regex ^index\.php(/.*) which matches a URI that starts with /index.php/ followed by zero or more of any characters. (/.*) is our match and the capture group after /index.php which is used as back-reference i.e. $1 (string that we've captured in group #1) in target to get a URI after /index.php as desired.
References:
Apache mod_rewrite Introduction
.htaccess tips and tricks

Related

htaccess - remove index.php and keep a variable without key

original url is one of the following:
example.com
example.com/index.php
example.com/index.php?c=lorem
if example.com - nothing should be done
if example.com/index.php - it should be visible as example.com and here is my code - works fine:
RewriteEngine ON
RewriteRule ^index\.php/?$ https://%{HTTP_HOST}/ [NC,R=301]
RewriteRule ^/?$ index.php [L]
if example.com/index.php?c=lorem it should be visible as example.com/lorem
and lorem should be accessible by php in both cases:
if a user type example.com/index.php?c=lorem or
a user type example.com/lorem
pls help
Could you please try following, based on your shown samples.
Please do clear your browser cache before testing your URLs.
RewriteEngine ON
##This rule is for handling index.php file in uri.
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^index\.php/?$ / [R=301,NC,L]
##This rule is to redirect from index.php?c=lorem to lorem in uri.
RewriteCond %{THE_REQUEST} index\.php\?c=(lorem)\s [NC]
RewriteRule ^ http://%{HTTP_HOST}/%1? [R=301,L,NE]
##Rule for non-existing files/directories to index.php with variables.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?c=$1 [L]
OR: Above is for specifically lorem in case your query string could be anything then try following.
RewriteEngine ON
##This rule is for handling index.php file in uri.
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^index\.php/?$ / [R=301,NC,L]
##This rule is to redirect from index.php?c=lorem to lorem in uri.
RewriteCond %{THE_REQUEST} index\.php\?c=([^\s&]*) [NC]
RewriteRule ^ http://%{HTTP_HOST}/%1? [R=301,L,NE]
##Rule for non-existing files/directories to index.php with variables.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?c=$1 [L]
You may use these rules in your site root .htaccess:
DirectoryIndex index.php
RewriteEngine On
# remove index.php
RewriteCond %{THE_REQUEST} /index\.php\s [NC]
RewriteCond %{REQUEST_URI} ^(.*/)index\.php$ [NC]
RewriteRule ^ %1 [L,R=301,NE]
# external redirect from actual URL to pretty one
RewriteCond %{THE_REQUEST} \s/+index\.php\?c=([^\s&]+) [NC]
RewriteRule ^ /%1? [R=301,L,NE]
# internal forward from pretty URL to actual one
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/.]+)/?$ index.php?c=$1 [L,QSA]

.htaccess rewrite subfolders to remove /index

I have some htaccess rules which rewrite friendly URLs. Everything is working apart from one thing.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.html [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*?)/?$ $1.html [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . / [L,R=301]
This is a site with language subfolders, e.g.:
/fr/about.html
/en/about.html
With the above htaccess rules these urls come out like:
/fr/about
/en/about
However this also means my index pages URLs look like:
/fr/index
/en/index
What I would like, is for /index the URL looks like
/fr
/en
Which would mean they respect the trailing slash part of my above htaccess but remove index from the URL.
Any help much appreciated!
Try to add (before RewriteCond %{THE_REQUEST} ^...):
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*?)/index(\.html)?[\s?] [NC]
RewriteRule ^ %1 [R=301,L]

Apache Rewrite if file not found to another file?

I am trying to rewrite my urls to another file if they do not already exist. I have an .htaccess file in the root of my site that looks like this.
RewriteEngine on
# Add slash to end of request
RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.*) %{REQUEST_URI}/ [R=301,L]
# API redirect
RewriteCond %{REQUEST_URI} ^/api
RewriteRule . api/v1.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{HTTP_HOST} ^ secondary\.
RewriteRule . sites/secondary [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . sites/main.php [L]
My intention is to serve two sites from the same folder and use the rewrites to point to the appropriate routers. The api redirect works great. However, the main and secondary redirect do not work unless I specify a route other than example.com (example.com/test/ correctly rewrites).
Any insight is greatly appreciated.
Use:
RewriteEngine on
# Add slash to end of request
RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule ^ %{REQUEST_URI}/ [R=301,L]
# API redirect
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^api api/v1.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{HTTP_HOST} ^ secondary\.
RewriteRule ^ sites/secondary [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ sites/main.php [L]
Because . is at least equal to one character.

Why does this not work, htaccess, capture domain ext and use in cond

Why does this rewrite rule not work?
RewriteCond %{HTTP_HOST} domain.(se|dk)/shop/$ [NC]
RewriteRule ^ https://domain.$1 [R=302,L,NE]
I am attempting to catch all requests to domain.dk/shop/ and domain.se/shop/ and redirect them to domain.dk, or domain.se.
What seems to be the issue?
Entire htaccess
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# Redirect everything to HTTPS
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
RewriteCond %{HTTP_HOST} domain.(se|dk)$ [NC]
RewriteRule ^shop$ https://domain.%1/ [R=302,L,NE]
</IfModule>
The HTTP_HOST doesn't have any path information, it is only "domain.se". The path information must be in the rule's regex match:
RewriteCond %{HTTP_HOST} domain.(se|dk)$ [NC]
RewriteRule ^shop$ https://domain.%1/ [R=302,L,NE]
Also, you need to use the %1 backreference, which references a grouping in the condition. The $1 backreference is one from the rule's grouping (which doesn't have one).

.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]