rewrite error when one value is empty - .htaccess

I have this line here;
RewriteRule ^news/(.*)/(.*)/$ ./news.php?type=$1&number=$2 [L]
But when one of the 2 values is empty it shows an error that the page is not found. As example I did;
localhost/news/dgfgh
Is there a way to fix this?
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} "/admin/"
# Remove .php extension
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]
RewriteRule ^news/(.*)/(.*)/$ ./news.php?type=$1&number=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/(.+)/$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^(.*)/$ $1.php [L]
# Force trailing slash
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .*[^/]$ $0/ [L,R=301]

The Regular Expression in your rewrite rule does not match localhost/news/dgfgh
The rewrite rule is looking for news followed by exactly two groups, followed by a trailing slash. To do what you want, you need two rules.
RewriteRule ^news/(.*)/(.*)/?$ ./news.php?type=$1&number=$2 [L]
RewriteRule ^news/(.*)/?$ ./news.php?type=$1 [L]
The first one is yours with a simple ? before the trailing slash to indicate that the trailing slash is options. The second one is for the case when you don't have the number in the url as in your example

Related

Remove subdirectories from URL with mod_rewrite

I'm trying to get rid of some subdirectories on my website.
I tried this link Remove two subdirectories from url with mod_rewrite but it does not work with my case.
Actually i have this structure : www.mywebsite.com/fr/news/index.html and I want it to look like www.mywebsite.com/index.html.
In my root directory a have a htaccess file with the following:
Options -Indexes +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.html [L]
RewriteCond %{REQUEST_URI} !^/(en|es|pt)/
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+fr/([^\s]+) [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_URI} !^/(en|es|pt)/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (?!^fr/)^(.*)/$ /fr/$1 [L,NC]
RewriteCond %{REQUEST_URI} !^/(en|es|pt)/
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.]+\.html(\?[^\ ]*)?\ HTTP/
RewriteRule ^(([^/]+/)*[^.]+)\.html$ http://%{HTTP_HOST}/fr/$1 [R=301,L]
RewriteCond %{REQUEST_URI} !^/(en|es|pt)/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ http://%{HTTP_HOST}/fr/$1/ [R=301,L]
What would the change to do to make it work ?
Thank you in advance for your answers
I have this structure:
www.mywebsite.com/fr/news/index.html
and I want it to look like
www.mywebsite.com/index.html
Without knowing more, I'd suggest placing this in your root folder:
RewriteEngine on
RewriteRule ^[^\/]+\/[^\/]+\/(.*) http://www.mywebsite.com/$1
The regex reads as:
from the start, find one or more characters that aren't a forward slash
then a forward slash
then one or more characters that aren't a forward slash
then a forward slash
then capture all the remaining characters

generic solution for Rewriteurl for all URL's [duplicate]

My website runs a script called -> WSS wallpaper script
My Problem -> I have been trying to force remove or add trailing slash to the end of my URL to prevent duplicated content and also to clean up my URLs.
I have tried all sorts and tried everything I could think of and loads from the interwebs but no such luck yet! It might be a quick fix but I have looked at it so much I am probably blind to something dead obvious.
So I present you with all my .htaccess code:
DirectoryIndex index.php
RewriteEngine on
RewriteRule ^download/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) image.php?id=$1&width=$2&height=$3&cropratio=$4&download=1 [L]
RewriteRule ^file/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) image.php?id=$1&width=$2&height=$3&cropratio=$4 [L]
RewriteRule ^preview/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) wallpaper_preview.php?id=$1&width=$2&height=$3&name=$4 [L]
RewriteRule ^thumbnail/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+)/([^/\.]+)/([^/\.]+)/([^/]+) image.php?wallpaper_id=$1&width=$2&height=$3&cropratio=$4&align=$5&valign=$6&file=$7 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/p([0-9]+) index.php?task=category&id=$1&name=$2&page=$3 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/([0-9a-zA-Z?-]+)/p([0-9]+) index.php?task=category&id=$1&name=$2&sortby=$3&page=$4 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/([0-9a-zA-Z?-]+)-([0-9]+) index.php?task=category&id=$1&sortby=$3&page=$4 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+) index.php?task=category&id=$1&name=$2 [L]
RewriteRule ^tag/([^/\.]+)/([0-9a-zA-Z?-]+)/([0-9]+) index.php?task=tag&t=$1&sortby=$2&page=$3 [L]
RewriteRule ^tag/([^/\.]+) index.php?task=tag&t=$1 [L]
RewriteRule ^profile/([0-9]+)?/([^/\.]+) index.php?task=profile&id=$1&name=$2 [L]
RewriteRule ^profile/comments/([0-9]+)?/([^/\.]+) index.php?task=users_comments&id=$1&name=$2 [L]
RewriteRule ^page/([0-9]+) index.php?task=view_page&id=$1 [L]
RewriteRule ^register index.php?task=register [L]
RewriteRule ^lost-password index.php?task=lost_pass [L]
RewriteRule ^links index.php?task=links [L]
RewriteRule ^news/item/([0-9]+)/([^/\.]+) index.php?task=news&id=$1 [L]
RewriteRule ^news/page([0-9]+) index.php?task=news&page=$1 [L]
RewriteRule ^members/([^/\.]+)-([^/\.]+)/page([0-9]+)? index.php?task=member_list&sort=$1&order=$2&page=$3 [L]
RewriteRule ^members index.php?task=member_list [L]
RewriteRule ^messages index.php?task=messages [L]
RewriteRule ^submit index.php?task=submit [L]
RewriteRule ^search/([^/\.]+) index.php?task=search&q=$1 [L]
RewriteRule ^search index.php?task=search [L]
RewriteRule ^submit index.php?task=submit [L]
RewriteRule ^r-([0-9]+)?-([0-9]+)? go.php?id=$1&ref=$2 [L]
RewriteRule ^r-([0-9]+)? go.php?id=$1 [L]
RewriteRule ^([^/\.]+)/([0-9]+)/([^/\.]+) index.php?task=view&id=$2&name=$3 [L]
RewriteRule ^news/([^/\.]+) index.php?task=news&name=$1 [L]
RewriteRule ^profile/([^/\.]+) index.php?task=profile&name=$1 [L]
RewriteRule ^news index.php?task=news [L]
RewriteRule ^page/([^/\.]+) index.php?task=view_page&name=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([0-9a-zA-Z'?-]+)/([0-9]+) index.php?task=category&name=$1&sortby=$2&page=$3 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([^/\.]+) index.php?task=view&name=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+) index.php?task=category&name=$1 [L]
## www reslove ##
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
## www reslove ##
## index reslove ##
Options +FollowSymLinks
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ http://www.epicwallpaper.net/$1 [R=301,L]
## index reslove ##
Right below the RewriteEngine On line, add:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]
to enforce a no-trailing-slash policy.
To enforce a trailing-slash policy:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R] # <- for test, for prod use [L,R=301]
EDIT: commented the R=301 parts because, as explained in a comment:
Be careful with that R=301! Having it there makes many browsers cache the .htaccess-file indefinitely: It somehow becomes irreversible if you can't clear the browser-cache on all machines that opened it. When testing, better go with simple R or R=302
After you've completed your tests, you can use R=301.
To complement Jon Lin's answer, here is a no-trailing-slash technique that also works if the website is located in a directory (like example.org/blog/):
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
For the sake of completeness, here is an alternative emphasizing that REQUEST_URI starts with a slash (at least in .htaccess files):
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /(.*)/$
RewriteRule ^ /%1 [R=301,L] <-- added slash here too, don't forget it
Just don't use %{REQUEST_URI} (.*)/$. Because in the root directory REQUEST_URI equals /, the leading slash, and it would be misinterpreted as a trailing slash.
If you are interested in more reading:
PR 3145 for Laravel
A discussion on commit 343c31e
(update: this technique is now implemented in Laravel 5.5)
This is what I've used for my latest app.
# redirect the main page to landing
##RedirectMatch 302 ^/$ /landing
# remove php ext from url
# https://stackoverflow.com/questions/4026021/remove-php-extension-with-htaccess
RewriteEngine on
# File exists but has a trailing slash
# https://stackoverflow.com/questions/21417263/htaccess-add-remove-trailing-slash-from-url
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?(.*)/+$ /$1 [R=302,L,QSA]
# ok. It will still find the file but relative assets won't load
# e.g. page: /landing/ -> assets/js/main.js/main
# that's we have the rules above.
RewriteCond %{REQUEST_FILENAME} !\.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^/?(.*?)/?$ $1.php
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
## hide .html extension
# To externally redirect /dir/foo.html to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+).html
RewriteRule ^ %1 [R=301,L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)/\s
RewriteRule ^ %1 [R=301,L]
## To internally redirect /dir/foo to /dir/foo.html
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^([^\.]+)$ $1.html [L]
<Files ~"^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</Files>
This removes html code or php if you supplement it. Allows you to add trailing slash and it come up as well as the url without the trailing slash all bypassing the 404 code. Plus a little added security.

Remove index.php AND trailing slashes from URL

I've got the following rewrite rules in my .htaccess, the first 4 lines are supposed to deal with allowing to access the site without index.php, and works fine, until I add the last bit which I'm trying to use to remove trailing slashes from the sites URLs.
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1 !^(uploads|cache|themes|default|admin\.php|favicon\.ico|robots\.txt|index\.php) [NC]
RewriteRule ^(.*)$ /index.php/$1
# Remove trailing slashes
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
When I add the last line, and I visit the root of my site, the index.php part gets appended to the URL, why is this?
When I add the last line, and I visit the root of my site, the index.php part gets appended to the URL, why is this?
This is because the rules are applied sequentially. You want the redirect to happen before you route stuff to /index.php. Just swap those rules around:
# Remove trailing slashes
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1 !^(uploads|cache|themes|default|admin\.php|favicon\.ico|robots\.txt|index\.php) [NC]
RewriteRule ^(.*)$ /index.php/$1 [L]
Following rules are work for me.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
#Removing trailing slash
RewriteRule ^(.*)/$ /$1 [L,R]
#Removing index.php
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=302,NE,L]

How can I redirect all sub-directories to root using htaccess or httpd.conf?

I have an index file that builds content based on n PATH_INFO variables.
Example:
site.com/A/B/n/
should use index.php at either:
site.com/index.php?var1=A&var2=B&varN=n
- or -
site.com/index.php/A/B/n/
instead of:
site.com/A/B/n/index.php || which doesn't exist ||
So far I've tried a number of variations of:
RedirectMatch ^/.+/.*$ /
with no success.
I have an inelegant and unscalable solution here:
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)/?$ index.php?p1=$1 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2&p3=$3 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2&p3=$3&p4=$4 [NC,L]
Problems with this solution:
Inelegant and unscalable, requires manual line for each subdirectory
Fails with non alphanumeric characters (primarily +,= and &) ex. site.com/ab&c/de+f/
(note, even changing the regex to ^([a-zA-Z0-9_-\+\=\&]+)/?$ does little to help and actually makes it error out entirely)
Can you help?
Option 1: (site.com/index.php?var1=A&var2=B&varN=n):
Options +FollowSymLinks -MultiViews
RewriteEngine On
# do not do anything for already existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
RewriteRule ^([^/]+)/?$ index.php?p1=$1 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2&p3=$3 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2&p3=$3&p4=$4 [QSA,L]
1. You had [NC] flag ... so there were no need to have A-Z in your pattern.
2. Instead of [a-zA-Z0-9_-\+\=\&] or [a-zA-Z0-9_-] I use [^/] which means any character except slash /.
3. [QSA] flag was added to preserve existing query string.
Option 2: (site.com/index.php/A/B/n/):
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/$1 [L]
In reality, if you do not plan to show that URL anywhere (like, 301 redirect etc), the last line can easily be replaced by RewriteRule .* index.php [L] -- you will look for original URL using $_SERVER['REQUEST_URI'] in your PHP code anyway.
Adding the following will redirect all traffic (for files that do not exist) to the index page:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php [NC]
Then, you can make your decision in index.php by parsing the 'REQUEST_URI'
RewriteRule ^/.+ / [R=301,L]
any url with any kind of path beyond root will be redirected to root.
^ = start of url
/ = a slash
.+ = 1 or more characters

URL Rewrite Including Trailing Slash If Not Present

I've got this RewriteRule to work.
RewriteBase /my/path/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /my/path/index.php [L]
So URLs with a trailing slash work. http://localhost/my/path/foo/bar/
The problem is that URLs without the trailing slash will break relative links. Plus it dosen't look good.
This reaches the maximum number of internal redirects.
RewriteRule ^/my/path/(.*[^/])$ $1/ [R]
RewriteRule . /my/path/index.php [L]
And this will do... http://localhost/my/path/index.php/bar/
RewriteRule . /my/path/index.php
RewriteRule ^/my/path/(.*[^/])$ $1/ [R,L]
Any Ideas or solutions?
The confusing feature of mod_rewrite is that, after an internal redirect, even one qualified with [L], the entire set of rules is processed again from the beginning.
So you redirect a nonexistent path to index.php, but then the rules for adding a slash kick in and you don't get the result you want.
In your case you simply need to put the file nonexistence condition on both of the redirect rules:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /my/path/index.php [L]
Or maybe move this condition to the top of the file:
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L] # redirect to same location to stop processing
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R]
RewriteRule ^ /my/path/index.php [L]
There's also an undocumented trick to stop processing after an internal redirect which should make more complex rulesets easier to write – using the REDIRECT_STATUS environment variable, which is set after an internal redirect:
RewriteCond %{ENV:REDIRECT_STATUS} . # <-- that's a dot there
RewriteRule ^ - [L] # redirect to same location to stop processing
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R]
RewriteRule ^ /my/path/index.php [L]

Resources