How to set FallbackResource by length of URL in .htaccess? - .htaccess

I want to set my FallbackResource url by the length of the url
for example if the url is 10 chars long then the FallbackResource will be
FallbackResource /index.php
else it will be
FallbackResource /other.php
how can I do that?

FallbackResource can be only one and is unconditional. For conditional presentation of a fall back resource it is better to use mod_rewrite rules but things will appear a bit complicated. Here is an example of such rules:
RewriteEngine On
# skip all files and directories from rewrite rules below
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# for URIs length >= 10
RewriteRule ^.{10} index.php [L]
# for all other URIs
RewriteRule ^ other.php [L]

Related

Rewrite rule in htaccess is not working

Here are the .htaccess rules:
RewriteEngine On
RewriteRule ^([^/]*)$ content.php?seourl=$1 [L]
RewriteRule ^pdf/([^/]*)$ content-single.php?seourl=$1 [L]
RewriteRule ^browsepdf$ browse.php [L]
RewriteRule ^browsepdf-([^/]*)$ browse.php?page=$1 [L]
RewriteRule ^download/([^/]*)$ download.php?pdf=$1 [L]
RewriteRule ^sitemap.xml$ xmlsitemap.php [L]
Options -Indexes
Here every URL is pointing to content.php?seourl=$1, even css, js and image files.
Here are some example URLs I need,
http://example.com/sjskjfsk21
http://example.com/asfasfasf43sf
http://example.com/pdf/fhfdhdh3432aaf
http://example.com/pdf/aisfyiahm2faf3
http://example.com/browsepdf
http://example.com/browsepdf-1
http://example.com/browsepdf-2
http://example.com/download/fjaskfjalsk3rs
http://example.com/download/usaydiy7aisydi
http://example.com/sitemap.xml
Can anyone please fix the .htaccess file.
Here every url is pointing to "content.php?seourl=$1"
Because your first (generic) rule catches all the requests. You need to change the order so you have the most specific rules first, and the most generic (catch-all) rules at the end. In your case you just need to move the first rule to the end. For example:
RewriteRule ^pdf/([^/]*)$ content-single.php?seourl=$1 [L]
RewriteRule ^browsepdf$ browse.php [L]
RewriteRule ^browsepdf-([^/]*)$ browse.php?page=$1 [L]
RewriteRule ^download/([^/]*)$ download.php?pdf=$1 [L]
RewriteRule ^sitemap\.xml$ xmlsitemap.php [L]
RewriteRule ^([^/]*)$ content.php?seourl=$1 [L]
NB: I backslash-escaped the dot in sitemap.xml to match a literal dot, otherwise it matches any character.
even css, js and image files.
You can make an exception for these static resources at the beginning of your file, before the existing directives. For example:
RewriteRule \.(js|css|png|jpg|gif)$ - [L]
For any URL that ends in any of the stated file extensions then stop processing the current mod_rewrite rules.
Alternatively (although perhaps marginally less efficient), you can prevent processing of requests for files that exist. Again, this goes before your existing mod_rewrite directives. For example:
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
However, this must now check every request for the existence of a file on the filesystem that maps to the request. (It could also be combined with the above rule if required.)
UPDATE: Bringing this together, we have:
# Exclude any existing files from being rewritten
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Specific rewrites
RewriteRule ^pdf/([^/]*)$ content-single.php?seourl=$1 [L]
RewriteRule ^browsepdf$ browse.php [L]
RewriteRule ^browsepdf-([^/]*)$ browse.php?page=$1 [L]
RewriteRule ^download/([^/]*)$ download.php?pdf=$1 [L]
RewriteRule ^sitemap\.xml$ xmlsitemap.php [L]
# Any other requests for the form "/<anything>"
RewriteRule ^([^/]*)$ content.php?seourl=$1 [L]

.htaccess rewrite if nothing specified

I'm trying to modify my .htaccess file to link to three different places, based on the input after the endpoint:
"/api" - Link to the API
"/ABCD123" - If it's a 7 character
alphanumeric string, link to a specific page
"/" - If nothing specified, or for any other inputs link to the homepage.
Here is my .htaccess file:
Options -Indexes
RewriteEngine On
RewriteRule ^api/(.*) ./api/index.php [R,L]
RewriteRule ^([a-zA-Z0-9]{7})$ index.php?l=$1 [L]
RewriteRule ^(.+)$ everythingelse.php [L]
Even though I have the [L] flag specified I always seem to get redirected to the everythingelse.php route, even if I have the 7 character string.
How can I rewrite to match this correctly?
Your rules are looping and executing more than once. L flag only breaks current loop but mod_rewrite can loop again and execute all the matching rules.
Options -Indexes
RewriteEngine On
# skip all files and directories from rewrite rules below
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
RewriteRule ^api/(.*)$ /api/index.php [R,L]
RewriteRule ^([a-zA-Z0-9]{7})$ index.php?l=$1 [L,QSA]
RewriteRule . everythingelse.php [L]

htacces redirect for SEO friendly URLs

I have my htaccess file setup, so that the pages remove extensions. Now, I am trying to make the pages that transfer variables, into SEO friendly urls ... so, for example...
http://www.example.com/art-gallery?page=2 ... which is actually "art-gallery.php?page=2", would turn into... http://www.example.com/art-gallery/page/2
Or... http://www.example.com/art-piece?id=3 ...would go to... http://www.example.com/art-piece/id/3
... and so on ...
I have alot in my htaccess file, and am not sure how to do the above (there are plenty of tutorials on going from www.example.com/index.php?page=2 to www.example.com/page/2/ but none that do exactly what I need). Ideally, I'd like to be able to do this for all similar pages...
# enable the rewrite engine
RewriteEngine On
# Set your root directory
RewriteBase /
# Force www:
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301,NC]
# Remove the .php extension
RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP
RewriteRule (.*)\.php$ $1 [R=301]
# Remove index and reference the directory
RewriteRule (.*)/index$ $1/ [R=301]
# Remove trailing slash if not a directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*)/ $1 [R=301]
# Forward request to html file, **but don't redirect (bot friendly)**
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
# Disable Directory Browsing
Options -Indexes
# Disable Hotlinking of Images
# with forbidden or custom image option
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?google.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ – [NC,F,L]
# Protect htaccess File
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>
You can transfer parameters with the variable QUERY_STRING.
Consider the following rule:
RewriteRule ^index.html index.php?%{QUERY_STRING}&m=main&a=index
This rule would transform
index.html?something=value
into
index.php?something=value&m=main&a=index
You should use the RewriteEngine.
You could also use a 301 redirect either alone or in conjunction with the RewriteEngine to redirect SEs.
Generally, though redirecting SEs to a different page than what users will see is not a good practice, and may result in your pagerank decreasing. Instead, try migrating all your pages to the second URL format, and consider using 301 redirects to help the transition.
Generally: Use 301 redirects for SE-friendly page changes. See this SO for additional reference.
You can insert this rule just before Forward request to html file rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/])/([^/])/([^/])/?$ $1.php?$2=$3 [L,QSA]
This is quite old but why not do the following:
RewriteEngine On
RewriteRule ^([^?]*) index.php?route=$1 [L,QSA]
Then in your index.php you can handle it like such;
if (isset($_GET['route'])) {
$route = explode('/', $_GET['route']);
if (iconv_strlen((end($parts)), 'UTF-8') == 0) {
array_pop($parts);
}
}
From here your main level would be handled with $route[0], second level $route[1]
For example;
http://example.com/art-gallery/2
$route[0] would equal 'art-gallery'
$route[1] would equal '2'

multiple slashes on url: how to remove?

Based on code found here: remove multiple trailing slashes mod_rewrite
I have the following htaccess
Options +FollowSymLinks
DirectorySlash Off
RewriteEngine on
RewriteOptions inherit
RewriteBase /
#
# remove multiple slashes from url
#
RewriteCond %{HTTP_HOST} !=""
RewriteCond %{THE_REQUEST} ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$ [OR]
RewriteCond %{THE_REQUEST} ^[A-Z]+\s(.*/)/+\sHTTP/[0-9.]+$
RewriteRule .* http://%{HTTP_HOST}/%1 [R=301,L]
#
# Remove multiple slashes anywhere in URL
#
RewriteCond %{THE_REQUEST} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
Yet i found out the G-Bot has crawled this url: http://www.example.com/aaa/bbb/////////bbb-ccc/bbb-ddd.htm. (aaa, bbb, ccc, ddd, are keywords in url, not to be taken litraly - i jut show the pattern of the url)
Testing the above url in by live server i found out that the slash removal does not work.
Anyone can offer any tips or improvement to the the existing code? Thank you
EDIT 1
#Sylwester provided the following code
# if match set environment variable and start over
RewriteRule ^(.*?)//+(.*)$ $1/$2 [E=REDIR:1,N]
# if done at least one. redirect with 301
RewriteCond %{ENV:REDIR} 1
RewriteRule ^/(.*) /$1 [R=301,L]
It is not working either. I still see the ////// inside the url.I have put this set of rules at the very top of my htaccess file, right below the " RewriteBase /", so as not to be affected by other rules, yet... nothing.
Any other suggestion?
Per directory and .htaccess is tricky since apache actually have removed redundant slashed for us. Eg. there is no match for //+ anymore so we check the %{REQUEST_URI} since it has the original URI while the rewrite rule need to match anything:
# NB: Only works for per directory and .htaccess
# Needs "AllowOverride All" in global config for .htaccess
RewriteEngine On
RewriteBase "/"
Options +FollowSymlinks
# Check if the REQUEST_URI has redundant slashes
# and redirect to self if it has (which apache has cleaned up already)
RewriteCond %{REQUEST_URI} //+
RewriteRule ^(.*) $1 [R=301,L]
If you can add global config I would have prefered this in the virtual host instead:
RewriteEngine On
# if match set environment variable and start over
RewriteRule ^(.*?)//+(.*)$ $1/$2 [E=REDIR:1,N]
# if done at least one. redirect with 301
RewriteCond %{ENV:REDIR} 1
RewriteRule ^/(.*) /$1 [R=301,L]

.htaccess rewrite file uri to either file-name.html or file-name.php - whichever exists

OBJECTIVE: To cause the browser to rewrite to file-name.php, if it exists; else return file-name.html - whether the visitor has typed the url as any one of the following:
http://mydomain.com/file-name
http://mydomain.com/file-name.html
http://mydomain.com/file-name.php
Had good success with the following rules in my .htaccess file at root:
# REWRITE FILE URI TO file.php IF EXISTS
Options Indexes +FollowSymLinks +MultiViews
Options +ExecCGI
RewriteEngine on
RewriteBase /
# parse out basename, but remember the fact
RewriteRule ^(.*).html$ $1 [C,E=WasHTML:yes]
# rewrite to document.php if exists
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [S=1]
# else reverse the previous basename cutout
RewriteCond %{ENV:WasHTML} ^yes$
RewriteRule ^(.*)$ $1.html
However, I have since installed WP at root, alongside pre-existing website, and these rules are no longer working.
WHAT DOES WORK: file-name is rewritten to either file-name.html or file-name.php - whichever file exists.
WHAT DOES NOT WORK: file-name.html is not rewritten to file-name.php even when there is no file-name.html and file-name.php is there. Also, file-name.php is not rewritten to file-name.html when there is no file-name.php but there is file-name.html.
The entire .htaccess as it is now:
# BEGIN WP MULTISITE RULES
RewriteEngine On
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).*) $1 [L]
RewriteRule ^[_0-9a-zA-Z-]+/(.*\.php)$ $1 [L]
RewriteRule . index.php [L]
# END WP MULTISITE RULES
# REWRITE FILE URI TO file.php IF EXISTS
Options Indexes +FollowSymLinks +MultiViews
Options +ExecCGI
RewriteEngine on
RewriteBase /
# parse out basename, but remember the fact
RewriteRule ^(.*).html$ $1 [C,E=WasHTML:yes]
# rewrite to document.phtml if exists
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [S=1]
# else reverse the previous basename cutout
RewriteCond %{ENV:WasHTML} ^yes$
RewriteRule ^(.*)$ $1.html
Any advices?
Quick overview tells that your original rules most likely will never get reached as WP rules should intercept all requests.
This line RewriteRule ^ - [L] with those conditions will abort rewriting for any already existing files or folders, while this line RewriteRule . index.php [L] will intercept/redirect all requests to index.php.
If you move your rules above WordPress one, then it will work again.
To rewrite request for non-existing .php file to .html file use this rule:
# rewrite non-existing .php file to existing .html
RewriteCond %{DOCUMENT_ROOT}/$1.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule ^(.+)\.php$ $1.html [L,PT]
Place it below your rules (but above WP). The rule will check if .php files does not exist and rewrite will only occurs if .html file is present. If both files are unavailable then nothing will happen.
Keep in mind that because of these checks and the fact that rule is on the top of rewrite chain, this rule will be evaluated for every request to .php file (even WP pages) which may put extra pressure on very busy server. Ideally you would like to have proper URLs in first place so there will be no need for such manipulations.

Resources