.htaccess lowercase rewrite causes HTTP error - apache

I'm trying to write an .htaccess rewrite based on modified code from here that will convert URLs like this:
http://eXAMplE.CoM/sOMe-PatH/aNOTHer-PAth/FILEName.eXT
To this:
http://example.com/some-path/another-path/FILEName.eXT
Basically converting the entire URL to lowercase and excluding the filename.
[PROBLEM]
My .htaccess seems to be working OK with one exception: When anything beyond the initial path includes a capital letter, it results in no data from the server. I assume it's causing an infinite loop but can't be sure because I can't access the logs.
To clarify, this works:
http://eXAMplE.CoM/sOMe-PatH/FILEName.eXT
This does not:
http://eXAMplE.CoM/sOMe-PatH/aNOTHer-PAth/FILEName.eXT
Here is my code. Can anyone help?
RewriteEngine On
RewriteBase /
# Skip this entire section if no uppercase letters in requested URL
RewriteRule !.*?[A-Z].*\/.* - [S=28]
# Replace single occurance of CAP with cap, then process next Rule.
RewriteRule ^([^A]*)A(.*\/.*)$ $1a$2
RewriteRule ^([^B]*)B(.*\/.*)$ $1b$2
RewriteRule ^([^C]*)C(.*\/.*)$ $1c$2
RewriteRule ^([^D]*)D(.*\/.*)$ $1d$2
RewriteRule ^([^E]*)E(.*\/.*)$ $1e$2
RewriteRule ^([^F]*)F(.*\/.*)$ $1f$2
RewriteRule ^([^G]*)G(.*\/.*)$ $1g$2
RewriteRule ^([^H]*)H(.*\/.*)$ $1h$2
RewriteRule ^([^I]*)I(.*\/.*)$ $1i$2
RewriteRule ^([^J]*)J(.*\/.*)$ $1j$2
RewriteRule ^([^K]*)K(.*\/.*)$ $1k$2
RewriteRule ^([^L]*)L(.*\/.*)$ $1l$2
RewriteRule ^([^M]*)M(.*\/.*)$ $1m$2
RewriteRule ^([^N]*)N(.*\/.*)$ $1n$2
RewriteRule ^([^O]*)O(.*\/.*)$ $1o$2
RewriteRule ^([^P]*)P(.*\/.*)$ $1p$2
RewriteRule ^([^Q]*)Q(.*\/.*)$ $1q$2
RewriteRule ^([^R]*)R(.*\/.*)$ $1r$2
RewriteRule ^([^S]*)S(.*\/.*)$ $1s$2
RewriteRule ^([^T]*)T(.*\/.*)$ $1t$2
RewriteRule ^([^U]*)U(.*\/.*)$ $1u$2
RewriteRule ^([^V]*)V(.*\/.*)$ $1v$2
RewriteRule ^([^W]*)W(.*\/.*)$ $1w$2
RewriteRule ^([^X]*)X(.*\/.*)$ $1x$2
RewriteRule ^([^Y]*)Y(.*\/.*)$ $1y$2
RewriteRule ^([^Z]*)Z(.*\/.*)$ $1z$2
# If there are any uppercase letters, restart at very first RewriteRule in file.
RewriteRule .*?[A-Z].*\/.* - [N]
# Force a redirect with the new lowercase URL.
RewriteRule (.*) $1 [R=301,L]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteBase /
RewriteRule ^index\.php$ - [L]
# uploaded files
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]
</IfModule>

You'll be better off using RewriteMap instead. In the server configuration (or VHost configuration) add the following:
RewriteMap to_lower int:tolower
Now, you can use the function to_lower in your rewrite rules. Give the following a try:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^((?=[A-Z]).+)(/[^/]+)$ /${to_lower:$1}$2 [R=301,L]

Related

Remove slash on redirect without .htaccess [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.

Rewrite partial URL to specific page with .htaccess mod_rewrite

Couldn't really figure out a title for this, so it's not the best, sorry.
I'm looking to rewrite URLs like this:
https://awesomechristianmusic.com/song-list?artist=dc-talk
To look like this:
https://awesomechristianmusic.com/dc-talk
Or for genres/topics:
https://awesomechristianmusic.com/song-list?genre=rock
https://awesomechristianmusic.com/song-list?topic=forgiveness
To look like this:
https://awesomechristianmusic.com/genre/rock
https://awesomechristianmusic.com/topic/forgiveness
Unfortunately, there seem to be some issues with my .htaccess file and I can't figure it out. Here's what I'm working with:
RewriteEngine on
RewriteBase /
# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,QSA,R=301]
# Remove www.
RewriteCond %{HTTP_HOST} ^www\.(.*)$
RewriteRule ^(.*)$ https://%1/$1 [R=301,L,QSA]
# Remove trailing slashes
RewriteCond %{REQUEST_URI} ^.*/$
RewriteRule ^(.*)/$ https://%{HTTP_HOST}/$1 [R=301,L,QSA]
# This is where I'm currently working
RewriteRule ^/([^/]+)$ /song-list?artist=$1 [NC,L,QSA]
RewriteRule ^/genre/([^/]+)$ /song-list?genre=$1 [NC,L,QSA]
RewriteRule ^/topic/([^/]+)$ /song-list?topic=$1 [NC,L,QSA]
# Redirect everything through index.php
RewriteCond %{REQUEST_URI} !(/(api|edit)/?.*) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [NC,L,QSA]
# long list of 301 redirects
Currently, the three rewrites I'm working on don't do anything. If I remove the slashes at the beginning of their regexes, I get a 500 Internal Server Error. Any ideas what might be going wrong or how to fix it?
Swap out these three rules:
# This is where I'm currently working
RewriteRule ^/([^/]+)$ /song-list?artist=$1 [NC,L,QSA]
RewriteRule ^/genre/([^/]+)$ /song-list?genre=$1 [NC,L,QSA]
RewriteRule ^/topic/([^/]+)$ /song-list?topic=$1 [NC,L,QSA]
To these three rules:
# If not /genre/* and not /topic/*
# Convert /dc-talk to /song-list?artist=dc-talk
RewriteCond %{REQUEST_URI} !^/genre/(.*)$ [NC]
RewriteCond %{REQUEST_URI} !^/topic/(.*)$ [NC]
RewriteRule ^(.*)$ song-list?artist=$1 [NC,L,QSA]
# Convert /genre/rock to /song-list?genre=rock
RewriteRule ^genre/(.*)$ song-list?genre=$1 [NC,L,QSA]
# Convert /topic/forgivenessto /song-list?topic=forgiveness
RewriteRule ^topic/(.*)$ song-list?topic=$1 [NC,L,QSA]
You can view these rules in action here: https://htaccess.madewithlove.be/?share=763f7107-f056-5ebe-ae0a-7f53a17b225a

htaccess issue in accessing the directory

My Blog link is http://www.example.com/blog when i am trying to access it it converts the url into http://www.example.com/blog/?ID=blog which is not correct. But when i put the backslash at the end of the blog it works fine but i don't want this back slash at the end
I try to change every thing inside htaccess file but failed.
Here is my htaccess file
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d [OR]
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^ - [L]
RewriteRule ^products products.php
RewriteRule ^websitemap sitemap.php
RewriteRule ^aboutus aboutus.php
RewriteRule ^clients clients.php
RewriteRule ^shoppingcart inq.php
RewriteRule ^contactus contact.php
RewriteRule ^finished finished.php
RewriteRule ^product/([a-zA-Z0-9_-]+)$ product_large.php?ID=$1
RewriteRule ^([a-zA-Z0-9_-]+)$ category.php?ID=$1
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$ products.php?ID=$2&MID=$1
ErrorDocument 404 http://www.example.co.uk/error404.php
RewriteCond %{HTTP_HOST} ^example.co.uk$
RewriteRule ^/?$ "http\:\/\/www\.example\.co\.uk\/" [R=301,L]
Insert this rule after RewriteRule ^ - [L] to force a trailing slash:
DirectorySlash On
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} \s/+(.*?)[^/][?\s]
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301]
RewriteRule ^blog(/.*)?$ - [L,NC]
# your rest of the rules

Add custom rewrite rule so wordpress won't overide it

This is my htaccess file, wordpress multisite htacces. I need to put my custom rule in there and not let wordpress aoverride it. How can i do that? The bold one is my custom rewrite rule.
RewriteEngine On
RewriteBase /
**MY CUSTOM RULE RewriteRule ^/\?currentpage=(\d+)$ currentpage/$1.html [NC,L]**
RewriteRule ^index\.php$ - [L]
# uploaded files
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]
With RewriteRule you can only check the URI path and not the query. You need to use RewriteCond and QUERY_STRING for the URI query:
RewriteCond %{QUERY_STRING} ^currentpage=(\d+)$
RewriteRule ^$ currentpage/%1.html [NC,L]

.htaccess rewrite without www AND redirect to subdirectory

I'd like to redirect
www.example.com/* to example.com/*
And at the same time redirect
example.com/* to example.com/forum/*
But I also have /wiki/ and /blog/ and /style/, so I don't want to redirect
example.com/style/* to example.com/forum/style/*
This is what I have at the moment, which is not working quite correctly:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/forum/
RewriteRule ^(.*)$ forum/$1 [R=301,L]
Clarification: my question can be asked in a simpler way.
I'd like to redirect an empty REQUEST_URI or /, or a non-existent file only if it is in the root directory to /forum/.
Try this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com
RewriteRule ^(.*)$ http://example.com/$1 [R=301,QSA,L]
RewriteCond %{REQUEST_URI} !^/(wiki|blog|style|forum)
RewriteRule ^(.*)$ http://www.example.com/forum/$1 [R=301,QSA,L]
I would use these rules:
# redirect www.example.com to example.com
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule ^ http://example.com%{REQUEST_URI} [L,R=301]
# prefix everything but /forum/, /wiki/, /blog/, /style/ with /forum/ and rediret to it
RewriteRule !^(forum|wiki|blog|style)/ /forum%{REQUEST_URI} [L,R=301]
The second rule could additionally be replaced by this one to check the existence of the first path segment for every request.
# check if first segment of requested URI path is either missing
RewriteCond $0 ^$ [OR]
# or cannot be mapped to an existing directory
RewriteCond %{DOCUMENT_ROOT}$0/ !-d
RewriteRule ^[^/]* /forum%{REQUEST_URI} [L,R=301]
I'd say this should work.
RewriteEngine on
RewriteRule ^forum/(.*)$ forum/$1 [L]
RewriteRule ^wiki/(.*)$ wiki/$1 [L]
RewriteRule ^blog/(.*)$ blog/$1 [L]
RewriteRule ^style/(.*)$ style/$1 [L]
RewriteRule ^(.*)$ forum/$1 [L]
RewriteCond %{HTTP_HOST} ^www.example\.com$
RewriteRule ^(.*)$ http://example.com/$1
I don't have the answer for everything but for your www/no www problem you could try this :
# Enforce www
# If you have subdomains, you can add them to
# the list using the "|" (OR) regex operator
RewriteCond %{HTTP_HOST} !^(www|subdomain) [NC]
RewriteRule ^(.*)$ /exemple/$1 [L,R=301]
# Enforce NO www
RewriteCond %{HTTP_HOST} ^www [NC]
RewriteRule ^(.*)$ http://exemple.com/$1 [L,R=301]