Detect if directory exists in .htaccess before using rule - .htaccess

I'm using this .htaccess rule to detect the username in the URL, and redirect the visitor to the user profile page:
# username handler
RewriteRule ^([a-z]{2,30})$ /user.php?username=$1 [L]
So that:
example.com/asantos opens user.php?username=asantos
I also have first level directories:
example.com/ajax/
example.com/static/
example.com/assets/
So, if I open any of those directories directly, they get detected by the htaccess rule, and thus is redirected to:
example.com/user.php?username=ajax
example.com/user.php?username=static
example.com/user.php?username=assets
How can I ignore that .htaccess rule when, and only when, the directory already exists?

You can do it like this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z]{2,30})$ /user.php?username=$1 [L]
Or, for better performance, list the directories to avoid polling the filesystem:
RewriteCond %{REQUEST_URI} !/(?:ajax|static|assets)$
RewriteRule ^([a-z]{2,30})$ /user.php?username=$1 [L]

Related

Htaccess for redirecting a directory to a file with the same name

After doing a quick lookup on how to manage sites with multiple language support, I find site.com/language/page/ the neatest url layout. (as I don't have the funds for site.language)
I have used htaccess to redirect the base site from site.com to site.com/language/
by using: RedirectMatch ^/$ /language/ where 'language' is language.html
But since I have a directory called /language/ so that all other pages in the given language can be put inside it, the site just shows up as the index of the directory.
How can I accomplish that kind of layout, if I want the main index page to show up in the url as site.com/language/ ?
Current htaccess that worked fine until I added the directory:
## Rewrite Defaults
RewriteEngine On
## Remove file extension + force trailing slash
RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule (.*)/$ $1.html [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule .* %{REQUEST_FILENAME}/ [R=301,L]
## Redirect to /en-gb
RedirectMatch ^/$ /en-gb/
With the root folder looking like:
/language
stuff.html
morestuff.html
language.html
...
I would really appreciate help as this is currently a nightmare situation. When I try compiling the htaccess with answers to similar questions, everyone has just parts of what I am looking to achieve and thus I break the layout with every modification...
Is it possible to change the back-end filenames and accomplish this layout using only htaccess for front-end url rewriting since the url bar is the only thing that matters?
If I understand correctly, you should be able to solve this by removing the line:
RewriteCond %{REQUEST_FILENAME} !-d
Let me know if that works.

What should I write in .htaccess file to rewrite this url?

I have a server parked on xyz.com. I have Wordpress installed on xyz.com/ and xyz.com/blog. I have created a new directory xyz.com/mamba.
In xyz.com/mamba. I want what that if user visits xyz.com/mamba/hello then the url should be rewritten to xyz.com/mamba/index.php?message=hello.
What should I write in .htaccess file in xyz.com/mamba/ directory?
Try:
RewriteEngine On
RewriteBase /mamba/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?message=$1 [L]
The first line turns on the rewrite engine for the /mamba/ directory. Without doing this, the rules won't get applied (and the rules in the parent directory gets applied instead). The RewriteBase tells the rules here that any relative URI in the target should have /mamba/ as a base URI. The 2 conditions say that the request must not point to an existing file or directory, and the rule rewrites the request and puts it in the message query string parameter for index.php.

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.

ignore specific directories in htaccess using mod_rewrite

I've got the following code in my .htaccess to strip out index.php from the urls in my CMS-based site.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
This code works great and it routes requests exactly how I want. For example, with URL: http://example.com/contact/ the directory contact doesn't actually exist if you look in the FTP; instead index.php handles the request and shows my contact info. Perfect. Well, almost perfect.
I want to modify this code to specify a couple directories in FTP that should be ignored. For example, if I've got a folder called assets, when I go to http://example.com/assets/ the default DirectoryIndex page is displayed. Instead, I want this directory to be ignored -- I want index.php to handle /assets/.
TL;DR: How can I modify the above code to explicitly ignore certain existing directories (so that index.php handles them instead of the DirectoryIndex)?
Why not adding this below or before your code?
RewriteRule ^(assets/.*)$ /index.php/$1 [L]

.htaccess stupid issue

I have a server where I can only configure httpd using .htaccess, a cannot access global configuration. I want to rewrite almost every non-existing path to index.php, so I did something like:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?path=$1 [L,QSA]
And that is ok. But another thing I want to do is to prevent access to path where I keep PHP files (I cannot store them somewhere else) which is for example /php. I would like that anything starting with /php rewrites to index.php?path=php... so I did something like:
RewriteCond %{REQUEST_URI} ^/php.*
RewriteRule ^(.*)$ /index.php?path=$1 [L,QSA]
And that also would work ok if I had access to global configuration. In case of per-directory configuration, when I access /php it rewrites it to index.php?path=php and than puts directory name before that: /php/index.php?path=php. I read documentation and I realize that it uses internal redirects when per-directory confoguration is used. How can I avoid this behavior?
You can use Deny from all instead of mod_rewrite, but if you really want it, you can force external redirects as noteed in the mod_rewrite docs:
If a substitution string starts with
http://, then the directory prefix
will not be added

Resources