several conditions in apache mod rewrite to make custom URLs - php

In my domain example.com , I want to put all page files in a directory at root for example named file. So for example I put about.php the file directory and want to let users to access this page with this URL : example.com/about
or for example put user directory in the file directory and put login.php in it , and want to let users to access it with : example.com/user/login
In fact I want to remove .php and the file from the URLs.
AND
If those files don't exist , it should load a default file like index.php at root. for example the URL example.com/blabla should be mapped to the index.php
In fact , I want to make two conditions in mod rewrite with the mentioned priority.
notice : of course I should be able to use variables like $_GET at files like about.php
UPDATE : in summary , it should work with this logic :
if the URI isn't a file or directory{
if file/URI.php is a file
load file/URI.php
else
load index.php
}
some body gave an answer to use ErrorDocument 404 index.php , but it's a really bad idea (and now has deleted his answer !)
Thanks for your help...

A conditional rewrite (if the pages exist) sounds like a bad and complicated idea, if it even is possible.
I would rewrite everything to /index.php and control everything from there:
If the components of the url lead to an existing page, use / include that content;
If no valid page is found, present your original index content.
Example redirect rules for your situation:
RewriteEngine on
RewriteBase /
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^.*$ /index.php?id=$1 [QSA,L]
Will include the requested path in id and append the variables from the original query string (the QSA flag).
More specific for your /user/login example would be:
RewriteRule ^([\w-]+)/([\w-]+)$ /index.php?path=$1&file=$2 [QSA,L]
[\w-+] : any word character (including _) and the -

Related

Having some issues with htaccess mod rewrite

Hello everyone wondering if i can pick your brains and il be as descriptive as possible.
So i am trying to create a page that will load a title and category (dynamic from database) based upon the selection that is picked by the user
sitename used as my domain name
So to be a little clearer i have a file and variables named sitename/2017/slot.php?gp=category&sn=title
the category and title are stored in the database for each row what i want to do is make a clean URL to look like this sitename/2017/slot/category/title/
So when viewing the page like this sitename/2017/slot.php?gp=category&sn=title the page loads everything in and displays correctly and the variables are being set as i can see them in my title in the browser tab
my error comes when i use the mod rewrite to make it clean, once the .htaccess has been changed and uploaded and i navigate to the new clean URL sitename/2017/slot/category/title/ it shows me the variables havent been set as they no longer appear in the title tab of the browser and also the page doesnt use my css. Below i have added my htaccess rule, any help and feedback is greatfully appreciated
#change this sitename/2017/slot.php?gp=category&sn=title
#to this sitename/2017/slot/category/title/
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^slot/([a-z-]+)/([a-z-]+)/ slot.php?gp=$1&sn=$2 [NC,L]
just incase here is the php code im using in slot.php i am connecting to my database fine no issues there and after the code below im running a while loop to get out the data for the row the user clicked on
if($_GET['gp'] && $_GET['sn']){
$gp = preg_replace('#[^a-zA-Z-]#i', '', $_GET['gp']);
$sn = preg_replace('#[^a-zA-Z-]#i', '', $_GET['sn']);
}
here is the full code i have in my htaccess
#make custom page not found
#ErrorDocument 404 /filenotfound.php
#stop directory file listing in all folders
IndexIgnore *
#make pages have www. in them
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.org
RewriteRule ^(.*)$ http://www.example.org/$1 [R=permanent,L]
#change this slot.php?gp=category&sn=title
#to this sitename/2017/slot/category/title/
Options -MultiViews +FollowSymLinks
RewriteRule ^slot/([a-z-]+)/([a-z-]+)/ /2017/slot.php?gp=$1&sn=$2 [R=302]
If your URL starts with 2017 you must include it in your RewriteRule.
RewriteRule ^2017/slot/([a-z-]+)/([a-z-]+)/ slot.php?gp=$1&sn=$2 [NC,L]
You're misusing the ^, which matches the very start of the path (the part after sitename/. That is, a rule starting with ^slot/ will match only sitename/slot/, not sitename/2017/slot/. Your rule should look like this:
#change this sitename/2017/slot.php?gp=category&sn=title
#to this sitename/2017/slot/category/title/
RewriteRule ^2017/slot/([a-z-]+)/([a-z-]+)/ slot.php?gp=$1&sn=$2 [NC,L]
May I join the party?
RewriteRule ^sitename/2017/slot/([a-z-]+)/([a-z-]+)/ /slot.php?gp=$1&sn=$2 [NC,L]
If the sitename the domain name, I will change my answer to :
RewriteRule ^2017/slot/([a-z-]+)/([a-z-]+)/ /slot.php?gp=$1&sn=$2 [NC,L]
Which is almost the same as Dekel's, but not exactly :)
#example.com/2017/slot.php?gp=category&sn=title
#example.com/2017/slot/category/title/
You'll need to disable MutliViews. Near the top of your .htaccess file:
Options -MultiViews
With MultiViews enabled (part of mod_negotiation) /2017/slot is being implicitly rewritten to /2017/slot.php (without any query string paramaters) before your mod_rewrite directives are being processed.
Although it's still not clear where your .htaccess file is located. So, there may still be some work to do... If your .htaccess file is located at example.com/2017/.htaccess then your existing mod_rewrite directives should be sufficient.
However, if your .htaccess file is in the document root (ie. example.com/.htaccess) then you will need to modify your RewriteRule:
RewriteRule ^2017/slot/([a-z-]+)/([a-z-]+)/ 2017/slot.php?gp=$1&sn=$2 [NC,L]

how to change the URL from a GET-variable to imaginary directory

All the links in the website are a get-variable. The user opens always the index.php and gives different get-variables, which defines the different content.
Example:
The home page is example.com/?p=1
The contact page is example.com/?p=7
Now I want the URLs to look like example.com/contact. And because the number of pages is not static I can't create a directory for every page.
Probably I need a way to import the content of my index.php (example.com?p=3) to a path, which doesn't exist (example.com/new-path).
I've heard there is a way to solve that using the .htaccess file.
I'm not .htaccess / mod_rewrite expert, but just found this one may be useful for you. Note that you'll have to provide an entry for each page you are redirecting as the system will not know the relationships between the numbers and the pages by itself. You may have to fiddle around with it a bit to try and remove index.php.
# Original URL:
# http://www.example.com/index.php?p=1
# Desired destination URL:
# http://www.example.com/path-to-new-location/
# .htaccess syntax:
RewriteEngine on
RewriteCond %{QUERY_STRING} p=1
RewriteRule ^index\.php$ /path-to-new-location/? [L,R=301]
# Redirect URLs with query parameters (files placed in subdirectory)
Note, # is a sign for comments, anything on that line (in gray) will be ignored, it's sole purpose is to provide you information / comments on the code.
Source (line 52-63): Common .htaccess Redirects - Gist

Pretty URLs from DB

I am working on creating page links from DB like the following example.
Current page:
www.example.com/page.php?pid=7
In the DB it is saved as title "contact-us" under category "Company Info"
I want it to be like:
www.example.com/company-info/contact-us.html
I have tried different solution and answers but did not got any luck. I am not sure, where will be the PHP part and which rules to write for .htaccess files.
In apache (or .hataccess) do something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /proxy.php?_url=$1 [QSA,L]
So in a nutshell, if the resource being requested doens't exist, redirect it to a proxy.php file. From there $_REQUEST['_url'] will be the url the user was requesting.
Then create proxy.php in your home directory and add whatever logic you'd like to load the correct content.
If you use this from .htaccess, then you may need to add RewriteBase / to your config.
If you want to find this page by url, you will probably do this through php and .htaccess. Make a .htaccess that calls page.php for each and every request. You don't need the pid=7, because, well, how should the .htaccess know it is 7, right? :)
In page.php, you take the original url and split it on the slashes, so you get the category (company-info) and the page itself (contact-us.html). Then, you can look these up in the database. This is in a nutshell how many software works, including Wikipedia (MediaWiki) and CodeIgnitor.
Mind that 'company-info' isn't the same as 'Company Info'. You'll have to specify the url-version in the database to be able to use it for look-up.

how can i get my htaccess to make my url look like foo.bar/user with this snippet i have

I have been trying to get my urls to be more user friendly and I have come up with this set up
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ userpage?user=$1 [NC,L]
I added this to my .htaccess but I'm now i'm confused as to how to access these urls.
in my index.php when a user logs in i have tried to redirect the user using
userpage.php?user=s2xi
but the url parses as www.foo.bar/userpage.php?user=s2xi and not www.foo.bar/s2xi
and also tried this as a check to see if user exists (is there a better way?)
if($_GET['user'] != $_SESSION['username']){
header("Location: no_user.php");
}else{
//load page
}
I am using the Smarty template engine on my site and I have my 'themes' in directories that belong to members file
www.foo.bar/users/s2xi/themes
but i want www.foo.bar/s2xi to point to the persons profile page that is viewable by everyone else and not their accounts page.
You're missing the .php in your RewriteRule, if that's verbatim - eg, userpage? => userpage.php?.
However, you're going to run into some problems with this unless you're using a framework to help you distinguish between routes. If you switched to using a separate URI format for user pages (eg /user/foo) you wouldn't have conflicts; but as it stands currently, using .htaccess to rewrite your URLs in that format could potentially cause problems with many other parts of your app.
To do it with a separate URI format, change your last .htaccess line (the RewriteRule) to:
RewriteRule ^user/(.+)/?$ userpage.php?user=$1 [NC,L]
may want to consider adding QSA as well.

How to stop direct execution of a php page using htaccess rules?

In my .htaccess file I have defined the following rule to make my register page URL as http://example.com/register/
RewriteRule register/ /register.php
The above rule is perfectly fine but I can access my register page from http://example.com/register/ as well as from http://example.com/register.php.
I don't want that user will be able to access the URL from http://example.com/register.php URL, is there any RULE which I can define in .htaccess to stop execution of register.php URL or simply redirect any direct register.php request to /register/
If you are doing this to avoid getting multiple links to the same content, you can simply don't use "register.php" anywhere on your page. I think no search engine will "guess" for a certain file type and if there are no security concerns you are on the safe side, because in my opinion no user will link to this file either. However if you want to be certain just reroute all your functionality through an index.php via one line in your .htaccess which should be placed inside your www-root directory:
RewriteEngine on
RewriteRule ^(.*?)$ index.php?file=$1
In your index.php you can then simply choose which function/file to invoke by breaking down and checking the $_GET["file"] parameter. To make 100% certain no one can access your register.php file directly just move it (and all your others) to a separate directory and include a .htaccess file with the following line:
DENY from all
There are a couple of other options to prevent direct access. Just define() a variable somewhere in your index.php and at the top of your register.php just put
defined('access') or die('Intruder alert!');
at the top. Another way could be to be honest and simply tell search engines that your content has been moved and that they no longer should use the old link:
header("Status: 301"); /* Content moved permanently */
header("Location: http://yourserver/Register/");
exit;
Update
Just one more thing that crossed my mind, you can also check $_SERVER["REQUEST_URI"], whether the user attached any ".php" and act accordingly by either denying access completely or just redirecting to the new location.
It is true that you cannot use location directive, but you can actually paste .htaccess file into any directory.
Just if you put this into it, say:
Options -Indexes
order allow,deny
deny from all
you can copy paste this file into any (root) directory you want to protect from external execution.
To check the initial requested URL path, you need to use the request line. So try this rule:
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php[/?\s]
RewriteRule (.+)\.php$ /$1 [L,R=301]
And then again your rule (in a slightly modified way):
RewriteRule ^register/$ register.php
If you want to completely block /register.php by using mod_rewrite, use a variant of SleepyCod's answer:
RewriteCond %{REQUEST_FILENAME} register\.php [NC]
RewriteCond %{IS_SUBREQ} false
RewriteRule .* - [F,L]
Explanation:
[NC]: Makes the condition case-insensitive, just in case you're on a windows box.
Condition 1: The requested filename is 'register.php', and
Condition 2: The request is no subrequest (this is important, since every new round through RewriteRules actually creates subrequests).
Rule: essentially do nothing
Flags: [F]: Send an 403 Forbidden header, [L]: This is the last rule to apply, skip all following rewrite rules
Rewriting correctly is an art by itself. I suggest you carefully read http://httpd.apache.org/docs/2.2/rewrite/.
Cheers,
Try this.
RewriteCond %{REQUEST_FILENAME} ^register\.php$ [NC]
RewriteRule ^/register register.php
Or this
Redirect register.php /register
Ignoring the user-experience part, you can implement the new rel=canonical link to sort out the search engines.
Although, for this case you should probably just use a 301 redirect from /register.php to /register/
In register.php
if ( stristr( $_SERVER['REQUEST_URI'], '.php' ) )
{
header ('HTTP/1.1 301 Moved Permanently');
header ('Location: /register');
}

Categories