How come that none of these solutions work on my Apache servers:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/{2,} [NC]
RewriteRule ^(.*) $1 [R=302,L]
or
RewriteCond %{REQUEST_URI} ^(.*)/{2,}(.*)$
RewriteRule . %1/%2 [R=302,L]
or
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=302,L]
among others that I tried.
I tried ALL solutions from this page: Issue In Removing Double Or More Slashes From URL By .htaccess
and other pages as well.
The problem is that the rule in the htaccess does not match the double slashes within these above patterns.
I tried also "literal" patterns, with exact urls without regex patterns. Still nothing. But with a single slash - all work.
It seems like Apache has a problem when it finds: "//" - the url is clearly not recognized and the rule is ommited.
The idea is simple: to get rid of double slashes and replace them with one slash:
http://demo.codesamplez.com/html5//audio -> http://demo.codesamplez.com/html5/audio
Do you know how can I redirect URL with double slash "//" to a single onen "/"?
Here's htaccess (removed the longest comments in the file):
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/test//slash
RewriteRule ^(.*)$ /test/slash [R=302,L]
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Rewrite all other queries to the front controller.
RewriteRule ^ %{ENV:BASE}/app.php [L]
</IfModule>
Try the following instead, near the top of the root .htaccess file, before any existing rewrites:
# Remove multiple slashes anywhere in the URL-path
RewriteCond %{THE_REQUEST} \s[^?]*//
RewriteRule (.*) /$1 [R=302,L]
This uses the fact that multiple slashes have already been reduced in the URL-path matched by the RewriteRule pattern. And the check against THE_REQUEST (which contains the first line of the request headers and does not change throughout the request) ensures that multiple slashes were initially present somewhere in the URL-path (excluding the query string).
Another potential issue is if you have a proxy server (or load balancer) in front of your application (Apache) server and this is perhaps normalizing the request (reducing multiple slashes, removing trailing space, etc) as it forwards the request to your application (Apache) server. The application server then never sees the original request (with multiple slashes) that you see in the browser.
Looking at your attempts...
RewriteCond %{REQUEST_URI} ^/test//slash
RewriteRule ^(.*)$ /test/slash [R=302,L]
This "should" work, with the limited example as posted. However, the REQUEST_URI server variable is modified throughout the request, so if the URL has already been modified (perhaps in the server config) then this may not match.
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/{2,} [NC]
RewriteRule ^(.*) $1 [R=302,L]
This only matches multiple slashes at the start of the URL-path, not anywhere in the URL-path. This would also result in a malformed redirect if used in .htaccess (unless you also had a RewriteBase directive set). Without the slash prefix on the substitution string this rule is probably intended for a server or virtualhost context, not .htaccess.
RewriteCond %{REQUEST_URI} ^(.*)/{2,}(.*)$
RewriteRule . %1/%2 [R=302,L]
The same issue with the use of REQUEST_URI as mentioned above. Otherwise, this should work. However, it results in multiple redirects if there are more than 1 group of multiple slashes. eg. //foo//bar.
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=302,L]
The same as above, except this only matches double slashes, rather than groups of two or more slashes. So if there are more than two slashes in a group it will result in multiple redirects.
Related
I have multiple domains running on a Wordpress installation, with other sites also hosted on the same space that are pure html.
I want to create a set of htaccess rewrite rules that prepend "www" to a URL if it doesn't have it already, and then redirect to https for specific domain names, but not others.
I had written the following code, which seems logically correct to me, but causes issues when I deploy it:
# Check to see if the hostname begins with www. If not, add "www" then move to the next Rule
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1
# Check to see if the hostname is one of three different domains, using RegEx
# If they are, then change to "https",permanently redirect and stop processing rules
RewriteCond %{HTTP_HOST} ^www\.(domain1\.co|domain2\.co|domain3)\.uk [NC]
RewriteRule (.*) https://%{HTTP_HOST}/$1 [L,R=301]
# Check to see if the protocol is https AND if the hostname is not one of the https domains
# If they are, then change to "http", permanently redirect and stop processing rules
RewriteCond %{HTTPS} on [NC]
RewriteCond %{HTTP_HOST} !^www\.(domain1\.co|domain2\.co|domain3)\.uk [NC]
RewriteRule (.*) http://%{HTTP_HOST}/$1 [L,R=301]
#BEGIN WordPress
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) web/$1 [L]
RewriteRule ^(.*\.php)$ web/$1 [L]
RewriteRule . index.php [L]
# END WordPress
The errors I am getting seem to suggest I am getting a redirect loop which results in none of the Wordpress sites being available. Any clues?
The following is my solution.
The first Rewrite says:
GIVEN THAT the URL is http and not https THEN rewrite the URL so that
it starts with "https://" followed by the URL and any folder/file
request.
The second Rewrite says:
GIVEN THAT the URL starts with one or more characters, followed by a
dot, followed by either "co.uk", "org.uk", "uk", "com" or "org"
THEN rewrite the URL so that it starts with "https://www." followed by the
domain name and any folder/file request.
# BEGIN RewriteRules
<IfModule mod_rewrite.c>
RewriteEngine On
# Check if URL is http and redirect to https
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTP:X-Forwarded-SSL} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]
# Check if Host is the root domain and prepend www if it hasn't (e.g. example.com > www.example.com; test.example.com > test.example.com)
RewriteCond %{HTTP_HOST} ^[^.]+\.(co\.uk|org\.uk|uk|com|org)+$
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]
</IfModule>
# END Rewrite Rules
Please help me to write the correct RewriteRule for the 301 redirect (.htaccess under subdomain blog.example.com) for the links like:
from
https://blog.example.com/?source=tag_archive---------0-----------
redirect to
https://example.com/blog/
I use these lines in .htaccess:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^blog\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^source=tag_archive---------0-----------(&.*)?$ [NC]
RewriteRule ^(.*)$ https://example.com/blog/ [R=301,NE,NC,L]
With the example above I got
https://example.com/blog/?source=tag_archive---------0-----------
but need
https://example.com/blog/
(without part ?source=tag_archive---------0-----------)
On Apache 2.4+ you need to add the QSD (Query String Discard) flag to the RewriteRule directive:
RewriteRule ^ https://domainname.com/blog/ [QSD,R=301,L]
(Alternatively, if you are still on Apache 2.2, then append a ? to the end of the substitution string - effectively an empty query string. The ? itself will not be in the redirect response.)
^(.*)$ (the RewriteRule pattern) - since you are matching any URL-path and not using the backreference, this can be simplified to ^.
The NC and NE flags are not required here.
However, as noted above, this redirects any URL-path. If you specifically want to redirect https://blog.example.com/?source=tag... only then change the RewriteRule pattern to ^$ (an empty URL-path). For example:
RewriteRule ^$ https://domainname.com/blog/ [QSD,R=301,L]
I currently have a static HTML file hosted in the root folder of my Wordpress install. I can access the URL http://example.com/er_trends_download but get an internal server error when the trailing slash is added to the URL: http://example.com/er_trends_download/
I have added lines to the .htaccess file to drop the .html from my static file and my permalink settings in WordPress are set to drop the trailing slash also. I don't have a preference on keeping the trailing slash or not, I would just like to not get the internal server error whether it is part of the URL or not. I've included my full .htaccess file below:
# Use PHP5.6 as default
AddHandler application/x-httpd-php56 .php
php_value memory_limit 512M
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]
</IfModule>
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]
The problem with this code, is that when the request ends in a slash (eg. http://example.com/er_trends_download/) then the REQUEST_FILENAME server variable does not include the trailing slash, but the REQUEST_URI variable does. So, you end up rewriting to /er_trends_download/.html (which is clearly wrong), but then this results in a rewrite loop... /er_trends_download/.html.html to /er_trends_download/.html.html.html, etc. and the server eventually breaks with a 500 error.
Try the following instead:
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+?)/?$ /$1.html [L]
This makes the trailing slash optional and the non-greedy pattern .+? ensures we grab everything up to, but not including, the trailing slash (if there is one). The NC flag is not required here.
So, this allows URLs with and without a trailing slash (which may or may not be desirable).
I recently switched over my website to Wordpress. My old files were www.example.com/about.php and now its www.example.com/about/. I need to redirect incoming links from the .php extension to just the / for ALL my pages preferably using .htaccess.
What I have:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
Whats in my .htaccess file:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
I guess I don't know where I'd put it in my .htaccess file either.
Thanks!
The code you have does not redirect anything. It takes a request that might be for a php file and internally appends the .php extension. Nothing happens on the browser because you've not told it to do anything. This is a 2 step process here. See the top part of this answer for a short explanation.
In order to redirect, you need to match against the incoming request, not the URI (which could have been rewritten be previous rules or iterations):
RewriteCond %{THE_REQUEST} ^(GET|HEAD|POST)\ /(.*)\.php($|\ )
RewriteCond %{REQUEST_URI} !wp-admin
RewriteRule ^ /%2/ [L,R=301]
So when someone types http://www.example.com/about.php in their browser's URL address bar, the request will look like:
GET /about.php HTTP/1.1
and the %2 backreferences about and redirects the browser to http://www.example.com/about/ (note the trailing slash) and the address bar changes.
What happens then is the browser makes ANOTHER request but this time for http://www.example.com/about/ and the server gets the URI /about/. Now you need your rule to internally rewrite it back to the php file. Unfortunately, your rule doesn't handle the trailing slash, so you need something like this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/(.*?)/?$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^ /%1.php [L]
These would all go before your wordpress rules. The wordpress rules route everything to index.php and that would wreck any URI you are trying to rewrite.
You are doing things the wrong way around. You are actually rewriting urls that end end without php to files that do end in .php.
You'd need to do something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*).php$ $1/ [NC]
I also removed the check if the file you are redirecting to exists as well as the [L] flag, because it's likely that wordpress is also doing its own rewriting, which means that you don't want this to be the last rule processed and that you won't be able to find the file on the filesystem.
Depending on my value IS_HTTP, I decide after the code below, whether URL should be https or http.
I want always http (redirected from https) for http://mydomain.com (has an empty QUERY_STRING), http://mydomain.com/?q=home, http://mydomain.com/?qq=home.
And the code below works fine for such URLs, it sets up IS_HTTP to 1. Everything is perfect. But I want also URLs to administration folder always to be httpS, so I want to exclude such URLs from that block.
That's why I added the second string to the code below, but it doesn't stop such URLs from applying RewriteRule ^ - [E=IS_HTTP:1]. Why?
#determine if page is supposed to be http
RewriteCond %{REQUEST_URI} !^administration [NC]
#if it has q=home or qq=home in querystring
RewriteCond %{QUERY_STRING} (^|&)(q=home|qq=home)(&|$) [NC,OR]
#or if query string is empty
RewriteCond %{QUERY_STRING} ^$
#set env var to 1
RewriteRule ^ - [E=IS_HTTP:1]
Again, I want https://mydomain.com/administration/index.php and all other files from the folder /administration to be stopped before RewriteRule ^ - [E=IS_HTTP:1]
Why the code above does NOT stop them?
The second string I've tried was:
RewriteCond %{REQUEST_URI} !^administration [NC]
RewriteCond %{REQUEST_URI} !^/administration [NC]
but none of them works. (I believe / is not needed here as REQUEST_URI doesn't start from /, but I could be wrong).
Thank you.
Instead of this condition:
RewriteCond %{REQUEST_URI} !^administration [NC]
have this condition:
RewriteCond %{REQUEST_URI} !^/+administration [NC]
Remember that %{REQUEST_URI} always starts with a slash and can have multiple slashes if it is typed that way in browser.