Display particular (dynamicaly) URL without parent folder. Leave The Others Alone - .htaccess

I started learning rewrites today
First of all here are examples of my links
Index.php?action=pictures
Index.php?action=pictures&type=kitchen
Index.php?action=pictures&type=ceiling
Index.php?action=services
Index.php?action=services&type=shower
Index.php?action=services&type=windows
In my .htaccess file I have this
RewriteEngine On
RewriteBase /
#Do not Rewrite files or folders
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule ^(.*?)$ $1 [L]
#Ordinary
RewriteRule ^\.htaccess$ .htaccess [F]
RewriteRule ^(.*)/(.*)/?$ Index.php?action=$1&type=$2 [L]
RewriteRule ^(.*)/?$ Index.php?action=$1 [L]
Rewrites URLs to
localhost/pictures
localhost/pictures/kitchen
localhost/pictures/ceiling
localhost/services
localhost/services/shower
localhost/services/windows
//etc
I like to have ALL my links working as is with an exception of services where I don't need parent folder /services/.
Result:
localhost/pictures
localhost/pictures/kitchen
localhost/pictures/ceiling
localhost/services
localhost/shower
localhost/window
I tried to rewrite .htaccess but either I get only parentfolder to work or only subfolder.
I tried to add this but I do understand that this matches everything...
RewriteRule ^(.*)/?$ Index.php?action=services&type=$1 [L]
I can however hardcode it like this
RewriteRule ^window/?$ Index.php?action=services&type=window [L]
Would like to have something dynamical. If folder services -> show no folder yet still be able to see localhost/services!
Is it possible?

Think of it this way: How would Apache know if a particular string is an action, or a type of service?
Well, you have three options:
We hardcode the types of services. Anything that does not match a type must be an action.
We hardcode the actions. Anything that does not match an action must thus be a type of service.
Apache has no way of knowing: We feed it to a script, who might be able to do some magic to find out what this string is.
In your case hardcoding the actions seems like the best idea, at least when the actions are static.
RewriteRule ^(.*)/(.*)/?$ Index.php?action=$1&type=$2 [L]
RewriteRule ^(pictures|services)/?$ Index.php?action=$1 [L]
RewriteRule ^(.*)/?$ Index.php?action=services&type=$1 [L]

Related

Htaccess rule to make urls like this ?page=1 look like /page/1 in Codeigniter

This is how my urls currently look:
http://mysite.com/?page=1
How can I make this work?:
http://mysite.com/page/1
There is a post on StackOverflow that asks the same question. But the accepted solution isn't working for me. Because I am using Codeigniter and my page results in a 404 perhaps because since the url pattern of a CI site is:
domain/controller/method
The system is assuming that I am requesting a controller called "page" and a method called "1" both of which of course doesn't exist. Or maybye it's due to a conflict with the other code in my htaccess file (which I downloaded from the CI wiki, it gets rid of index.php and does a few security things). Here is my entire htaccess file:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
#Removes access to the system folder by users. Additionally this will allow you to create a System.php controller, 'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
#When your application folder isn't in the system folder. This snippet prevents user access to the application folder. Rename 'application' to your applications folder name.
RewriteCond %{REQUEST_URI} ^application.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
#Checks to see if the user is attempting to access a valid file, such as an image or css document, if this isn't true it sends the request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
#Pretty urls for pagination links
RewriteRule (.*) index.php?page=$1
</IfModule>
The non indented bit is the solution I got from that other SO question that isn't working for me.
Any solutions to this CI pagination issue?
UPDATE
Ok, read some of the docs and now I have this working:
http://mysite.com/home/index/2
What would be the htaccess rule to turn that into?:
http://mysite.com/page/2
You should make this configuration at /application/config/routes.php (and let the .htaccess just for hide the index.php as you are already doing).
$route['page/(:any)'] = 'home/index/$1';
Or better, like #zaherg remembered (ensures that only numbers could by matched):
$route['page/(:num)'] = 'home/index/$1';
This way all the requests to http://mysite.com/page/2 will be treated internally as http://mysite.com/home/index/2 and so forth.
I suggest you take a look at CodeIgniter User Guide - URI Routing and CodeIgniter User Guide - Tutorial − Introduction.
Good luck.
RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
from CodeIgniter docs
That will handle removing the index.php, but what happens after that depends how CodeIgniter's query string handling is set up: it can be configured to use a query string rather than a path. See the link for more details.

htaccess issue including period/fullstop (.)

I currently have this .htaccess rule the works fine:
RewriteRule ^instructor/([A-Za-z0-9-]+)$ instructor.php?username=$1 [NC,L]
However, when I attempt to add a period into the mix a lot of the rules on the site break so I am assuming the character isn't escaped correctly:
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
Anyone point me in the right direction please?
Update
It appears to be something to do with the directory structure.
Another selection of rules that apply to this site are the following:
## Registration
RewriteRule ^instructor/register/?$ instructor-form/index.php [L]
RewriteRule ^instructor/register/stage([1-5]+)$ instructor-form/stage$1.php [L]
These work fine (the directory here is instructor-form/
However, there is also a directory called instructor/ which these rules point to:
RewriteRule ^instructor/dashboard/?$ instructor/index.php [L]
RewriteRule ^instructor/account-details/?$ instructor/account-details.php [L]
RewriteRule ^instructor/change-password/?$ instructor/change-password.php [L]
These are the rules that are affected when adding the . into the first rule. The rules are all in order and work fine without the . in the [A-Za-z0-9-] char block. When added the physical instructor/ folder seems inaccessible.
You wrote so much text in your question but forgot to mention important details: what is actually broken? Because I do not have clear answer for that I will be speculating here based on the information you have provided so far.
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
The problem with this rule is that it will also rewrite already rewritten php files: instructor/index.php, instructor/account-details.php, instructor/change-password.php etc.
I think you are relaying on [L] flag too much .. or do not really know how mod_rewrite and [L] flag work. And that is why you are having this issue -- your rule with a dot in pattern rewrites already rewritten URLs.
Useful link: RewriteRule Last [L] flag not working?
You need to add some condition (global rule or condition specific to this rule only) to prevent rewriting already rewritten URLs or existing files.
1. Global rule -- place it somewhere on the top before other rules. Keep in mind that this may not work as intended depending on your website structure and rewrite logic (e.g. when you need to actually rewrite requests to already existing files or folders):
# do not do anything for already existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
2. Condition specific to that rule only:
a) do not rewrite if requested URI is physical file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
OR
b) do not rewrite .php files
RewriteCond %{REQUEST_URI} !.+\.php$
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]

How do you add a second possible variable to a clean url?

I have created a htaccess rewrite code for URLs so when a user goes to myurl.com/testing/ it shows them index.php?page=testing however I would like to have a second or maybe third page so it could look like myurl.com/testing/2832/9283 and would show users index.php?page=testing&var1=2832&var2=9283.
This is the code I currently have:
RewriteRule ^([^\/]+)/([^\/]*)/$ index.php?page=$1&var1=$2
RewriteRule ^([^\/]+)/([^\/]*)$ index.php?page=$1&var1=$2
This works but I want to make the variables optional. If I do not have a second variable (i.e. just myurl.com/testing/) then it says it cant find the file.
# 3-level deep parameters
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)(/([^/]+))?(/([^/]+))?(/)?$ /index.php?page=$1&var1=$3&var2=$5 [QSA,L]
This rule will not touch already existing files and folders.
This rule will rewrite:
/help/tracking/123456/ => /index.php?page=help&var1=tracking&var2=123456
/help/tracking => /index.php?page=help&var1=tracking&var2=
/help => /index.php?page=help&var1=&var2=
You were having page=index.php because your rule rewrites already rewritten URLs (A lot of people forgetting, that when rewrite happens, it goes to next iteration and starting to test all rules again). This rule has conditions (extra checks) to ignore already existing files and folders.
Why not just set multiple RewriteRules for each case?
RewriteRule ^([^/]+)/?$ index.php?page=$1
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?page=$1&var1=$2
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?page=$1&var1=$2&var2=$3

Rewrite htaccess old oscommerce links

I am trying to rewrite all the old oscommerce links to a new website. But I am having trouble with part of the URL I need to rewrite.
The link looks like this:
http://www.domain.com/product_info.php?cPath=3_72&products_id=129&osCsid=6j3iabkldjcmgi3s1344lk1285
This rewrite works for the above link:
RewriteCond %{REQUEST_URI} ^/product_info\.php$
RewriteCond %{QUERY_STRING} ^cPath=3_72&products_id=129&osCsid=([A-Za-z0-9-_]+)$
RewriteRule ^(.*)$ http://www.domain.com/apple/air.html? [R=301,L]
But will not work for:
http://www.domain.com/product_info.php?cPath=3_72&products_id=129
My problem is that I want the rewrite to work no matter if the &osCsid=6j3iabkldjcmgi3s1344lk1285 part is included or not.
I think you can achieve this by not specifying the closing delimiter ($)
Give this a try:
RewriteCond %{REQUEST_URI} ^/product_info\.php$
RewriteCond %{QUERY_STRING} ^cPath=3_72&products_id=129
RewriteRule ^(.*)$ http://www.domain.com/apple/air.html? [R=301,L]
By not putting the $ at the end of the regex string you are basically saying: match any string that starts with ..., no matter what comes after
Hope this helps :)
This should do the job just fine:
RewriteCond %{QUERY_STRING} ^cPath=3_72&products_id=129
RewriteRule ^product_info\.php$ http://www.domain.com/apple/air.html? [R=301,L]
There is no need for separate condition RewriteCond %{REQUEST_URI} ^/product_info\.php$ -- this part can be (actually, SHOULD BE, for better performance) moved to RewriteRule.
This is enough ^cPath=3_72&products_id=129 -- it tells "When query strings STARTS with ...". No need to include optional/non-important parameters osCsid=([A-Za-z0-9-_]+).
This rule is to be placed in .htaccess file in website root folder. If placed elsewhere some small tweaking may be required.

.htacces RewriteRule not working

Hi people#stackoverflow,
Maybe I have a fundamental misconception about the working of RewriteRule. Or maybe not. Nevertheless, I'm trying to figure this out now for two days, without any progress.
This is the currrent situation:
I have a Joomla website with SEF and mod_rewrite turned on.
This results in the URL:
mysite.com/index.php?option=com_remository&Itemid=7
being rewritten to:
mysite.com/sub-directory/sub-directory/0000-Business-files/
These are the lines that are currently used in my .htaccess (all standard Joomla)
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([^\-]*)\-(.*)$ $1 $2 [N]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC]
RewriteRule (.*) index.php
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
This is what I want to achieve:
When a visitor uses this URL
mysite.com/sub directory/sub directory/0000 Business files/
it should lead him to the right page.
Although I know it's not the best idea to use spaces in a URL, I'm confronted with the fact that these 'spacious' URL's are used in a PDF, that's already been issued.
I thought I could use mod_rewrite to rewrite these URL's. But all I get is 'page not found'
I've added this rule on top of the .htaccess file:
RewriteRule ^([^\-]*)\-(.*)$ $1 $2 [N]
But this is not working. What am I doing wrong? Or, also possible, am I missing the point on when and how to use mod_rewrite?
rgds, Eric
First off, the default behavior of apache is usually to allow direct URLs that map to the underlying file system (relative to the document root), and you should use RewriteRule when you want to work around that. Looking at your question, it seems like you want to browse the filesystem and so you should not use a RewriteRule.
If mysite.com/sub+diretory/sub+directory/0000+Business+files/ doesn't work (without your rule), I'm wondering: do you have that directory structure on your server? I.e. does it look like this?
[document root]/index.php
[document root]/sub directory/sub directory/0000 Business files/
If not, I'm not sure I understand what you're trying to achieve, and what you mean by the visitor being "lead to the right page". Could you provide an example URL that the user provides, and the corresponding URL (or file system path) that you want the user to be served.
Regarding your rewrite rule, I'm not even sure that it is allowed, and I'm surprised you don't get a 500 Internal Server Error. RewriteRule takes two arguments (matching pattern and substitution) and optionally some flags, but because of the space between $1 and $2 you're supplying three arguments (+ flags).
EDIT: I got the pattern wrong, but it still doesn't make much sense. It matches against any URL that has at least one dash in it, and then picks out the parts before and after the first dash. So, for a URL like "this-is-a-url-path/to-a-file/on-the-server", $1 would be "this" and $2 would be "is-a-url-path/to-a-file/on-the-server". Again, if I had some example URLs and their corresponding rewrites, I could help you find the right pattern.
On a side note, spaces aren't allowed in URLs, but the browser and server probably does some work behind the scenes, allowing your PDFs to be picked up correctly.

Resources