.htaccess rewrite all URLs, even if path - php

I've made some PHP code that will direct the user based on the URL, and I've found some code for htaccess that gives the URL to the index page which lets my code work. However, it's also technically revealing what is a file/folder and what isn't.
If I go to website.com/somethingrandom/somethingelse, I'll get a 404 error, whereas going to website.com/cache/private will say forbidden.
How would I edit it so that it will act like no files exist, aside from a few select file types, such as images, css, and js files?
Here is the code as it currently stands:
RewriteBase /
RewriteEngine On
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-f
# This rule converts your flat link to a query
RewriteRule ^(.*)$ index.php?_page_location=$1 [L,NC,NE]

Have your rules like this:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L,NC]
# add trailing slash to directories
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301,NE]
# If the request is not for known file types
RewriteCond %{REQUEST_URI} !\.(?:jpe?g|gif|php|bmp|png|ico|tiff|css|js)$ [NC]
# This rule converts your flat link to a query
RewriteRule .* index.php?_page_location=$0 [L,QSA]

If you want to hide some file or directory, i.e. appear it as not existant, you might redirect with the R|redirect flag
RewriteRule ^cache/private - [R=404,L]
This tells the client, there is no such file named cache/private (404). Beware though, that this is for all clients, even yourself.
To restrict this, you must prefix the rule with some RewriteCond or wrap it in some conditional statement like If or similar.
If you want to hide all files, use a "broader" regular expression, like
RewriteRule ^ - [R=404,L]
This will return a "Not found" for all of your website's URLs. You can also give a set of URLs, like in this
RewriteRule ^(?:cache/private|secrets|database) - [R=404,L]
which will hide everything below
cache/private
secrets
database
See Apache - Regular Expressions and http://www.regular-expressions.info/ for details on how to customize your own pattern.

Related

Multiple Vanity URLs with different pages in different directories

I am trying to setup my .htaccess file to allow for multiple vanity URLs which is fine, but I'm running into issues with them with the pages being in different directories.
First vanity URL is setup and working fine, which works like this:
example.com/blognumber1 > example.com/inspiration/article.php?id=blognumber1
RewriteBase /inspiration/
RewriteCond %{REQUEST_FILENAME} !-d [NC]
RewriteCond %{REQUEST_FILENAME} !-f [NC]
RewriteRule ^(.*)$ article.php?id=$1 [QSA,L]
I am trying to add another one which would work like this:
example.com/supplier/test1 > example.com/profile.php?id=test1
Because the article.php page is in a different directory, I am having problems trying to code it, any help would be appreciated.
Don't use a RewriteBase directive (which applies to the entire file) and make sure the more specific /supplier/test1 rule is first. For example:
RewriteEngine On
# Abort early if a directory or file is requested directly
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Rewrite "/supplier/<test1>" to "profile.php?id=<test1>"
RewriteRule ^supplier/([^/]*)$ profile.php?id=$1 [QSA,L]
# Rewrite "/<blognumber1>" to "inspiration/article.php?id=<blognumber1>"
RewriteRule ^(.*)$ inspiration/article.php?id=$1 [QSA,L]
Note that the NC flag is not permitted on the RewriteCond directive when used with the filesystem checks -f and -d. If you check your error log you will probably see a stack of warnings.
On the /supplier/test1 rule, it only matches a single path segment after /supplier/, ie. it does not match /supplier/test1/something.
Your existing rule is rather generic as it literally matches anything. Perhaps restrict this to a single path segment also? Or restrict the regex to what constitutes a blognumber.
Optimisation
As a further optimisation you could also abort early if a .php file (or a URL that looks-like a .php file) is requested. Unless you have valid "supplier" or "blog" URLs that end in .php? For example, immediately after the RewriteEngine directive:
# Abort early if any `.php` URL is requested (includes rewritten URLs)
RewriteRule \.php$ - [L]
You can extend this for any URL that looks-like it contains a file extension, which should naturally include your static assets and therefore avoid the filesystem check. For example:
RewriteRule \.\w{2,5}$ - [L]

blocking crawlers on specific directory

I have a situation similar to a previous question that uses the following in the accepted answer:
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (googlebot|bingbot|Baiduspider) [NC]
RewriteRule .* - [R=403,L]
It just seems the rules provided from URL above block access to everything (including homepage level)
www.example.com/tbd_templates/
www.example.com/custom_post/
what I really need is to block access to the directories I specified (/tbd_templates/ ,/custom_post/ etc with status code 403) but allow access to the rest of the site structure.
My .htaccess is:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
anyone can help me?
RewriteCond %{HTTP_USER_AGENT} (googlebot|bingbot|Baiduspider) [NC]
RewriteRule .* - [R=403,L]
As mentioned in the linked answer, this code would need to go in the .htaccess file inside the directory you are trying to protect - so that it only applies to everything in that directory (denoted by the .* regex).
However, that is impractical if you need to protect several directories. In this case you should change the RewriteRule pattern to target the specific subdirectories you want to protect (touched on in the linked answer, but no example given).
For example, the following would need go before the WordPress code block (ie, before the # BEGIN WordPress comment marker). (You do not need to repeat the RewriteEngine directive, which already occurs later in the file.)
RewriteCond %{HTTP_USER_AGENT} (googlebot|bingbot|Baiduspider) [NC]
RewriteRule ^(tbd_templates|custom_post)($|/) - [F]
The first argument to the RewriteRule directive (the pattern) is a regular expression that matches against the requested URL-path, less the slash prefix.
The regex ^(tbd_templates|custom_post)($|/) matches requests for /tbd_templates or /custom_post (using regex alternation) or /tbd_templates/<anything> or /custom_post/<anything>.
The F flag is short for R=403. The L flag is not required here, it is implied when using F (or R=403).

How to redirect static to dynamic URL's using .htaccess (on Wordpress site)

I've taken over a former site/domain, and set up a new site using Wordpress. The WP installation rewrites URL's to static ones, as you'd expect it to.
At the same time I want to preserve the former pages, as they have incoming links. I'm not interested in 301'ing them to "new" pages.
The old URL structure is /index.php?id=123, which I suspect is causing the problem with the WP .htaccess file. For reference, this is what it looks like:
# 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've tried adding the following:
RewriteRule ^([0-9]+).html index.php?id=$1 [R,L]
Doesn't work. Just redirects to site.com/?id=123 and shows the front page.
I should add that I plan on just adding these new pages as regular static HTML files in the format of 123.html, 321.html etc.
How do I use .htaccess to make this work together with the WP installation and what WP puts into the .htaccess file?
To clarify:
I want to have my 123.html static HTML page be index.php?id=123. When you access index.php?id=123 it should bring up 123.html, but show index.php?id=123 in the address bar. If you access 123.html it should 301 to index.php?id=123.
To map an URL with a querystring up to an actual file you'll need to use a RewriteCond to match the querystring itself (as RewriteRule doesn't):
Something along these lines ought to do it:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# retrieve X.html when index.php?id=X is requested
RewriteCond %{REQUEST_FILENAME} index\.php
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteCond %1.html -F
RewriteRule .* %1.html? [L]
# standard WordPress routing
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
This will first check to see if you've got a request for index.php with a querystring like id=X.
Then it'll check to see if a file called X.html actually exists; I'm not 100% happy about having to use the more system hungry subrequest file check -F rather than the standard -f but I can't see a way around it in .htaccess in this case.
If X.html actually exists, it'll fetch that file whilst leaving the URL as index.php?id=X.
However if that file doesn't exist it'll fall back to standard WordPress no file, no directory routing to index.php
I'm not a WordPress expert but that should work; I guess the main WordPress controller uses $_SERVER['REQUEST_URI'] to determine the action.
Note: This won't, however, prevent people from accessing 123.html directly by going to the URL www.site.com/123.html - I kept falling into infinite loops and Apache 500 errors trying to prevent that :|

cant figure out mod_rewrite for php query string =/

here is my website
http://www.coolcodez.net/ios/nicucalc
notice when you click on pages on the nav you get urls like
http://www.coolcodez.net/ios/nicucalc/index.php?page=features
I put an .htaccess file in my nicucalc directory. I want the urls to look like this
http://www.coolcodez.net/ios/nicucalc/features
even better would be
http://www.coolcodez.net/nicucalc/features
here is my htaccess file. It's never working properly..
RewriteEngine on
RewriteCond %{QUERY_STRING} ^page=(.*)$
RewriteRule ^index\.php$ /%1/? [R=301,L]
what am i doing wrong. explanation as well please
also note: this folder is located inside of a wordpress installation folder. not sure if that htaccess file would be affecting mine somehow
The rule that you have redirects requests for index.php to /features/ (or whatever the "page" is). This is fine in and of itself but you need something that rewrites it internally back to index.php. Because of that you need 2 rules, one to redirect (matches request) and one to internally rewrite (matches URI):
RewriteEngine On
RewriteBase /ios/nicucalc/
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /ios/nicucalc/index\.php\?page=([^&\ ]+)&?([^\ ]*)
RewriteRule ^ /ios/nicucalc/%1?%2 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1 [L,QSA]
The first rule matches against the request, this looks like:
GET /ios/nicucalc/index.php?page=features HTTP/1.1
The "features" is captured and backreferenced in the rule using %1. The second rule first checks if the request points to an existing file or directory. If it doesn't then the URI is captured and then rewritten to index.php and the URI gets passed to the script via the "page" parameter.

htaccess rewrite url and check for 404

I`ve got an internet shop and want to use htaccess to shorten links
there are 3 cases of urls:
shop.com/shop/18 (number) - products.php?categoryid=$1
shop.com/shop/18/page-2 (number)/(page+number) - products.php?categoryid=$1&page=$2
shop.com/shop/18/9877 (number)/(number) - description?categoryid=$1&productid=$2
my try
RewriteRule ^shop/?$ shop.php
RewriteRule ^shop/(.*)/([0-9]+)/?$ description.php?categoryid=$1&productid=$2
RewriteRule ^shop/(.*)/page-(.*)/?$ products.php?categoryid=$1&page=$2
RewriteRule ^shop/(.*)/?$ products.php?categoryid=$1
With my try - 1 (works), 2 (works), 3 (doesn`t work)
How can I rewrite urls so?
How can I redirect to 404 page if e.g. there is no such number of
category or such product (guess check with php and mysql and then
redirect) ?
There are a number of ways that this can be dealt with;
All in htaccess (gets messy with multiple depths)
Combined htaccess and server side code
The best approach is the one that suits you based on how your store is coded. I personally feel that handling it in the server side code is better, it simplifies the htaccess file, and gives you more control with regards to validating data, and how you handle what is sent, to where, and how its processed when it gets there.
For example, in my htaccess file I have;
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine on
#
# Do not apply rewrite rules for non required areas
RewriteCond %{REQUEST_URI} "/hidden-areas/" [OR]
RewriteCond %{REQUEST_URI} "/other-areas/"
RewriteRule (.*) $1 [L]
# Do Not apply if a specific file or folder exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# The rules on how to rewrite the urls
RewriteRule (.*) /index.php?url=$1 [QSA,L]
</IfModule>
Basically, to explain this in a nutshell, I DONT rewrite anything for certain folders, I forward them straight on. This is to stop calls to scripts externally, or extra added systems being able to be accessed without issue.
I then, forward the entire url as a string through to my index page, and deal with what comes through using PHP, an example is below.
// collect the passed url
$url = $_GET['url'];
// split the url into parts
$url_parts = explode('/', $url);
/*
* start sorting what is what in the url
*/
// count how many parts there are
$url_parts_count = count($url_parts);
// determine the class/module
$class = $url_parts[0]; // generally the class/method/module depending on your system, thgough could be a category so run some checks
// determine the last part in the array
$last_url_part = ($url_parts_count - 1);
// set the last part of the url to be used
$slug = $url_parts[$last_url_part]; // generally the slug and will be empty if theres a trailing slash
etc etc etc
This is just a summary, i do far more, as this is taken from a CMS I wrote, but it should give you a very good starting point should you wish to get your hands dirty. Of course, Im happy to elaborate further if necessary.
The caveat of course, is if you are using an off-the-shelf system, they should provide you with this code already ;)
I have added below something based on your updated question, this will help if you do still plan to go the way you are :)
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
#
# Do not apply rewrite rules for non required areas
RewriteCond %{REQUEST_URI} "/hidden-areas/" [OR]
RewriteCond %{REQUEST_URI} "/other-areas/"
RewriteRule (.*) $1 [L]
# Do Not apply if a specific file or folder exists
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# The rules on how to rewrite the urls
RewriteRule ^([a-zA-Z0-9_-]+)$ /index.php?slug=$1 [QSA,L]
RewriteRule ^([a-zA-Z0-9_-]+)/$ /index.php?type=$1 [QSA,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$ /index.php?type=$1&slug=$2 [QSA,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/$ /index.php?type=$1&cat=$2 [QSA,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$ /index.php?type=$1&cat=$2&slug=$3 [QSA,L]
</IfModule>
Thanks, ended with
RewriteRule ^shop$ shop.php [L]
RewriteRule ^shop/([0-9]+)$ products.php?categoryid=$1 [L]
RewriteRule ^shop/([0-9]+)/(page-[0-9]+)$ products.php?categoryid=$1&page=$2 [L]
RewriteRule ^shop/([0-9]+)/([0-9]+)$ description.php?categoryid=$1&productid=$2 [L]

Categories