RewriteRule for unknown directory - apache

So I'm trying to get a mod_rewrite rule to redirect requests to a php-script with an .htaccess file. The thing is, I want it to work regardless of where I put the project on a webserver (the .htaccess file and the php-script are always in the same folder).
The rewrite itself is very simple. If the script and the .htacess are in the directory /path/to/project and the user visits:
/path/to/project/somestring
it should be rewritten to:
/path/to/project/index.php?t=somestring
This should work for every subdirectory at any level in the webserver. So:
If the php-script and the .htaccess files are in the root:
/somestring2
should be rewritten to:
/index.php?t=somestring2
If the php-script and the .htaccess file are in /subdirectory:
/subdirectory/somestring3
should be rewritten to:
/subdirectory/index.php?t=somestring3
So the RewriteRule should perform the same rewrite action regardless of where the project lives within the server. The string that is to become a GET-parameter can consist of those characters: [a-zA-Z0-9]. If there are other GET-parameters in the requested URL, they should be appended as well (hence the QSA flag). This is what I've tried:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*/)([a-zA-Z0-9])/? $1index.php&t=$2 [L,QSA]
However, this results in a 404 error. How can I alter it to do what I want?

Try :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*/)?([A-Za-z0-9]+)/?$ /$1index.php?t=$2 [NC,L,QSA]
Note that a leading slash in rewrite pattern is not required in the RewriteRule context.

Related

Redirecting all urls, including no path, to a file in subdirectory

I have checked a large amount of existing answers regarding .htaccess redirects. However none of them have helped me.
What I want to accomplish is redirecting all request urls to /api/init.php. However I've only gotten so far to where my index page www.example.com simply gives me a file listing because of the missing index.php file, while every url request with a path is working.
How can I accomplish this with .htaccess without ending up with a directory listing on my landing page?
This is as far as I got:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /api/init.php?path=$1 [NC,L,QSA]
Well your site root is a directory, so this rule you have excludes existing directories. What you could do is only exclude existing files, and allow existing directories to be handled by the PHP script. Like this:
RewriteEngine on
RewriteCond %{REQUEST_URI} !=/api/init.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /api/init.php?path=$1 [L,QSA]
I removed the NC flag as it's not needed. I added a condition to prevent an unnecessary file-system check.
You don't have to pass the path on in a URL parameter, as you could get it from $_SERVER['REQUEST_URI'] in PHP (not the same as REQUEST_URI in mod_rewrite, in PHP it always has the original URI). If you wanted to do that then your rule becomes nice and simple:
RewriteEngine on
RewriteCond %{REQUEST_URI} !=/api/init.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /api/init.php [L]
Because the query string will just be passed on unaffected (so QSA is not needed).

Authorize only 2 files in .htaccess

I would like to authorize only 2 things in .htaccess:
/favicon.ico -> deliver the file
/<anythingelse> -> index.php
Therefore, /logs/mylog.log and /hello.py should go to index.php, instead of displaying the raw content of these files (that do exist!).
How to do such a .htaccess?
I tried:
Solution #1 (seems to create an infinite loop):
RewriteEngine On
RewriteCond %{REQUEST_URI} !favicon\.ico$
RewriteRule ^(.*)$ index.php
Solution #2 (delivers the /logs/mylog.log and /hello.py file, this should not happen!):
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !favicon\.ico$
RewriteRule ^(.*)$ index.php
This will do it:
RewriteEngine On
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule ^ index.php
Removed the lines checking if it was an existing file or directory, since you want those to get rewritten too.
Added a check that it is not already index.php to avoid a loop.
Changed the RewrieCond syntax to a simple comparison which is more legible.
Added forward slash at the start of the request uri matches or they wouldn't match.
Removed the capturing in the RewriteRule which you're not using.
Update
On further discussion in comments, this should work when a copy of the .htaccess file is placed in a subdirectory. Here is an update so that will work:
RewriteEngine On
RewriteRule !^(?:favicon\.ico|index\.php)$ index.php [END]
The RewriteCond directives couldn't be used without adding the directory name to them, since /index\.php$ was an option but would also match the file in a subdirectory. The above acheives the goal without having to be updated when copied around, albeit not very pretty.

How to configure Apache2 to pretend a directory does not exist, except under a specific URI?

How do I make Apache2 treat a directory as if it doesn't exist, in order to prevent someone from finding out that it exists?
The directory will still be accessible under a different URI. For example, in the following .htaccess file, I would like any attempt to access example.com/admin (or a subdirectory or file inside of /admin/) to continue down to the index.php rewrite rule, unless it was accessed via /MySecretPath:
RewriteEngine On
RewriteBase /
RewriteRule ^MySecretPath$ admin/ [L,QSA]
RewriteRule ^MySecretPath/(.*)$ admin/$1 [L,QSA]
# all remaining requests - sent to the script
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
If you want to disable external access to the dir, put this rule above your existing rules :
RewriteCond %{THE_REQUEST} /admin/ [NC]
RewriteRule ^ - [F,L]
You can change the F "forbidden" to R=404 if you want the engine to return a 404 not found error for the request

htaccess rewrite rules to remove multiple subfolders from a URL

Due file system sub-directory constraints I will most likely reach I want to separate the /users folder into /users/a/username, /users/b/username, /users/c/username, etc.
So the data on the server for a user would be in:
www.domain.com/users/a/username/, www.domain.com/users/b/username/, etc
I want the URL to be:
www.domain.com/users/username/
Optionally to avoid duplicate content a 301 redirect from www.domain.com/users/a/username/ to www.domain.com/users/username/ would also be good.
Currently I have a rewrite for a single sub-directory (see below) but I'm confused how this can be done efficiently for all of the alphabetical sub-directories.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^users/(.*)$ users/a/$1 [L,NC]
I have checked this site and all seem to hide the first sub-directory e.g. domain.com/folder1/filename.html => domain.com/filename.html but nothing in more depth.
Put this code in your htaccess (which has to be in root folder)
Options -Indexes -MultiViews
RewriteMap lowercase int:tolower # this line in your apache file configuration
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/users/[a-z]/([^/\s]+)\s
RewriteRule . /users/%1/? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^users/([A-Za-z])([^/]+)/$ /users/${lowercase:$1}/$1$2/ [L]

.htaccess rewrite rule doesn't append path to query string

I'm trying to write an htaccess file and I'm having trouble getting it to work properly. There's a directory on my site called 'gpio'. The htaccess file that I'm writing is in /var/www/gpio.
When someone requests the URL http://domain.com/gpio, I want the request to be redirected to a script, with 'gpio' appended to the query string. This is what I've got in my htaccess file:
# .htaccess
#DirectoryIndex index.html
RewriteEngine on
# I changed domain name a few months ago...
RewriteCond %{HTTP_HOST} ^olddomain.com/*$
RewriteRule ^(.*)$ http://newdomain.com/$1 [R=301,L]
# handle the case where the directory exists
RewriteCond %{REQUEST_FILENAME} -d
# this is the part that doesn't work
RewriteRule ^(.*)$ /cgi-bin/pyindex.cgi?q=$1 [L,QSA]
# handle the case where a file is requested
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /cgi-bin/pyindex.cgi?q=$1 [L,QSA]
The problem is that when I visit this URL, I get redirected to the script, but the requested path doesn't get appended to the query string. In pyindex.cgi, when the query string is printed, it just contains 'q='. The end result is that I'm seeing my home page when I should be seeing a page representing a category of posts.
Any thoughts on what I'm doing wrong would be appreciated.
Either have that rule inside /var/www/.htaccess or modify it as
RewriteRule ^$ /cgi-bin/pyindex.cgi?q=gpio [L,QSA]
RewriteRule ^(.+)/?$ /cgi-bin/pyindex.cgi?q=gpio/$1 [L,QSA]
And, the following rule tests if the request is not a file (and hence would match directories as well)
RewriteCond %{REQUEST_FILENAME} !-f # remove ! to match files