URL rewriting : Apache configuration to prevent loading default folder index.html - apache

With the exact same .htaccess file, my local LAMP server (via mamp pro) and the production server behave differently. I suppose there is a different configuration at stake, but which one?
On my local server, http://domain.com/section/item/ redirects correctly to http://domain.com/index.php?section=$1&item=$2
On my production server, http://domain.com/section/item/ gives access to http://domain.com/section/item/index.html
What can i do to make the production server behave like the development server?
Here is the htaccess file content in case it helps.
<IfModule mod_rewrite.c>
RewriteEngine on
Options +FollowSymLinks
#--------------------------------------------
# PRETTY URLS
#--------------------------------------------
# if the following conditions are met, SKIP the rewriteRules.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [L]
# Externally redirect to add missing trailing slash
RewriteRule [^/]$ %{REQUEST_URI}/ [R,L]
# SIX PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2&menu=$3&content=$4&id=$5&title=$6 [NC,L,QSA]
# FIVE PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2&menu=$3&content=$4&id=$5 [NC,L,QSA]
# FOUR PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2&menu=$3&content=$4 [QSA,L]
# THREE PARAMS : projects/touch/texts/
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2&menu=$3 [QSA,L]
# TWO PARAMS: downloads
RewriteRule ^downloads/([^/]+)/$ index.php?section=downloads&item=$1 [QSA,L]
# TWO PARAMS:
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2 [QSA,L]
# TAG URL : index.php?tag=url+encoded+keyword
RewriteRule ^tag/([\w-]+)/$ index.php?tag=$1 [NC,L,QSA]
# ONE PARAM
RewriteRule ^([\w-]+)/$ index.php?section=$1 [L,QSA]
#--------------------------------------------
# END PRETTY URLS
#--------------------------------------------
</IfModule>

Try making 2 changes.
Add this line on top of your .htaccess file:
DirectoryIndex index.php
Then change your 1st rule to this:
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
EDIT: Also try this:
Options +FollowSymLinks -MultiViews

yes, both file directory structures are exactly the same
I don't know how exactly you've got everything setup, but it's possible that the order of modules being loaded is different between development and production (a long-shot), which could influence the order modules are being applied in the URL processing pipeline. It the order or something like mod_autoindex or mod_dir is different, thus causing a request for /section/item/ to get resolved to /section/item/index.html before mod_rewrite gets a chance to do anything. That means this condition becomes true:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [L]
And none of your other rules get applied, and thus /section/item/index.html gets served.
As to how to fix something like this, I suppose you can try turning off directory index in your server config (by commenting it out, everywhere), or set it to something non-existent in the directories that they are getting served:
DirectoryIndex _index.php

Related

Convert Query Parameters to Pretty URL

I have script file post.php which I'm using without .php extension using code below
Options -Indexes
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
I want to use a pretty URL. For example, when I request the URL /post/12 it should give me $_GET parameter 12 like I'm using with a query string: post?id=12.
Is it possible? Also, I don't want to direct all requests to index.php. Only requests that are made to posts.php script.
Handle requests of the form /post/12 with a separate rule, before your generic rewrite that appends the .php extension.
Try it like this:
Options -Indexes -MultiViews
RewriteEngine On
# Remove trailing slash if not a directory
# eg. "/post/" is redirected to "/post"
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ /$1 [R=301,L]
# Rewrite "/post/<id>" to "/post.php?id=<id>"
RewriteRule ^(post)/(\d+)$ $1.php?id=$2 [L]
# Rewrite "/post" to "/post.php" (and other extensionless URLs)
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
Notes:
MultiViews needs to be disabled for the second rule to work.
Your initial rule that appends the .php extension was not quite correct. It could have resulted in a 500 error under certain conditions. However, the first condition was superfluous - there's no point checking that the request does not map to a file before checking that the request + .php does map to a file. These are mutually inclusive expressions.
Without the first rule that removes the trailing slash (eg. /post/ to /post) it raises the question of what to do with a request for /post/ (without an id) - should this serve /post.php (the same as /post) or /post.php?id= (empty URl param)? Both of which are presumably the same thing anyway. However, these would both result in duplicate content (potentially), hence the need for a redirect.

apache redirects with different destination depending on whether one of several files exists

I have a static website (served by Apache) where one can download software packages. These packages first appear in the "devel" section of the site and then at some point they become available in the "release" section as well. The packages can live in one of several "repositories", but each package is guaranteed to have a unique name across all repositories. Let's say that my repository names are repos1, repos2, and repos3.
So currently I have URLs like this:
/packages/release/repos1/html/mypkg.html
/packages/devel/repos1/html/mypkg.html
I want to set up redirects such that a user can go to:
/packages/mypkg/
...and the rewrite rule will try all the following URLs and redirect to the first one that exists (or to the 404 page if none do). So for the request /packages/mypkg/:
/packages/release/repos1/html/mypkg.html
/packages/release/repos2/html/mypkg.html
/packages/release/repos3/html/mypkg.html
/packages/devel/repos1/html/mypkg.html
/packages/devel/repos2/html/mypkg.html
/packages/devel/repos3/html/mypkg.html
It's not clear to me how to do this with mod_rewrite. I know there is the special RewriteCond pattern -f, but it seems before I can use it I have to process the REQUEST_FILENAME in such a way that I can parse out the package name with a backreference.
Just to make things more complicated, if the user knows whether they are looking for a release or devel package I want to honor that, so /packages/devel/mypkg/ should redirect to /packages/devel/X/html/mypkg.html where X is the first repository where Apache finds the file. Any ideas?
There's no elegant way of doing this with mod_rewrite.
Anyway, you can put this code in your /packages/.htaccess
Options -Indexes
RewriteEngine On
RewriteBase /packages/
################################################################################
# /packages/release/xxx or /packages/devel/xxx are internally rewritten to
# /packages/release/reposX/html/xxx.html or /packages/devel/reposX/html/xxx.html
# Note: (reposX) X is the first repos where xxx is found
################################################################################
RewriteCond %{DOCUMENT_ROOT}/packages/$1/repos1/html/$2\.html -f
RewriteRule ^(release|devel)/([^/]+)/$ $1/repos1/html/$2.html [L]
RewriteCond %{DOCUMENT_ROOT}/packages/$1/repos2/html/$2\.html -f
RewriteRule ^(release|devel)/([^/]+)/$ $1/repos2/html/$2.html [L]
RewriteCond %{DOCUMENT_ROOT}/packages/$1/repos3/html/$2\.html -f
RewriteRule ^(release|devel)/([^/]+)/$ $1/repos3/html/$2.html [L]
################################################################################
# /packages/xxx is internally rewritten to
# /packages/release/reposX/html/xxx.html or /packages/devel/reposX/html/xxx.html
# Note: all release repos are fetch first, then devel ones
# (reposX) X is the first repos where xxx is found
################################################################################
RewriteCond %{DOCUMENT_ROOT}/packages/release/repos1/html/$1\.html -f
RewriteRule ^([^/]+)/$ release/repos1/html/$1.html [L]
RewriteCond %{DOCUMENT_ROOT}/packages/release/repos2/html/$1\.html -f
RewriteRule ^([^/]+)/$ release/repos2/html/$1.html [L]
RewriteCond %{DOCUMENT_ROOT}/packages/release/repos3/html/$1\.html -f
RewriteRule ^([^/]+)/$ release/repos3/html/$1.html [L]
RewriteCond %{DOCUMENT_ROOT}/packages/devel/repos1/html/$1\.html -f
RewriteRule ^([^/]+)/$ devel/repos1/html/$1.html [L]
RewriteCond %{DOCUMENT_ROOT}/packages/devel/repos2/html/$1\.html -f
RewriteRule ^([^/]+)/$ devel/repos2/html/$1.html [L]
RewriteCond %{DOCUMENT_ROOT}/packages/devel/repos3/html/$1\.html -f
RewriteRule ^([^/]+)/$ devel/repos3/html/$1.html [L]

www I added to HTTP_HOST via htaccess file disappears when redirecting to second htaccess file

I am struggling with an htaccess file. Actually, it is two files.
But first things first, so my questions are:
1) Why does my .htaccess(1) file add the www at the beginning of the HTTP_HOST and the slash at the end of folder REQUEST_URI IF AND ONLY IF the .htaccess(2) file is not there (deleted or renamed)?
2) What is wrong with the RewriteRule and conditions that I wrote in .htaccess(2) to redirect the REQUEST_URI to /publicfolder/REQUEST_URI? Conditions doesn't seem to work and when I surf to domain.com/nonpublicfolder it goes to domain.com/domainfolder/publicfolder/nonpublicfolder.
My website is structured as follows:
/
.htaccess(1)
domainfolder/
.htaccess(2)
publicfolder/
genericfolder/
index.extention
file.extention
nonpublicfolder/
So I have one htaccess file in the root folder ( .htaccess(1) ) where I:
add 'www' at the beginning of the HTTP_HOST;
add '/' at the end of REQUEST_URI if it does not end with a file extension;
redirect domain.com/anyfolder/anyfile.extention to domain.com/domainfolder/anyfolder/anyfile.extention;
like so:
<IfModule mod_rewrite.c>
# System symbolic links are allowed.
Options +FollowSymlinks
# Runtime rewriting engine enabled.
RewriteEngine On
# HTTP_HOST starts with 'www'.
RewriteCond %{HTTP_HOST} ^(?!www\.) [NC]
RewriteRule ^.*$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,NC]
# Folder requests end with '/'.
RewriteCond %{REQUEST_URI} ![^/]+\.[a-zA-Z0-9]+$ [NC]
RewriteRule [^/]$ %{REQUEST_URI}/ [R=301,NC]
# Files and folders are in the 'domainfolder' folder.
RewriteCond %{REQUEST_URI} !^/?domainfolder/ [NC]
RewriteRule ^.*$ /domainfolder%{REQUEST_URI} [R=301,NC]
</IfModule>
And then I have my .htaccess(2) file - in the domainfolder folder - where I redirect files and folders requests to the publicfolder folder IF AND ONLY IF they are not pointing to the notpublicfolder folder or to the Google Site Verification file:
<IfModule mod_rewrite.c>
# Runtime rewriting engine enabled.
RewriteEngine On
# Public files and folders are in the 'publicfolder' folder.
RewriteCond %{REQUEST_URI} !^/?domainfolder/publicfolder/ [NC]
RewriteCond %{REQUEST_URI} !^/?domainfolder/nonpublicfolder/ [NC]
RewriteCond %{REQUEST_URI} !^/?domainfolder/googlexxx.html$ [NC]
RewriteRule ^/?(.+)$ /publicfolder/$1 [R=301,NC,L]
</IfModule>
Thank you very much for your time and patience.
(1) mod_rewrite does multiple passes and on each by default it will only open the first .htaccess file it finds walking up the folder hierarchy from the requested file. read my Tips for debugging .htaccess rewrite rules for more discussion of this. Yes you can use a Options setting to change this behaviour but this has a performance hit and I would suggest that you avoid doing so.
(2) When using hierachical .htaccess files, mod_rewrite has to associate URI path to the current directory and can get this wrong. The RewriteBase directive tells mod_rewrite what the true association is, so use this.
Rule order is important. If you don't have a local Apache instance where you have root privilege and can enable rewrite logging, you need to build up your access file(s) incrementally rule-by-rule, testing at each step because you only get a work/doesn't work return. Again my tips explains how to do this.

Mediawiki Subdirectory Installation

Possible Duplicate: MediaWiki on SubDirectory and SubDomain (However doesn't have an answer, nor any replies offering help)
Alright, I'm trying to configure MediaWiki to be installed to a sub-directory. I previously had it installed to a primary domain on http://www.example.com/ with a mod_rewrite using a Short URL of /wiki/Main_Title.
As a note, I'm also on HostGator shared hosting which has special rules for short urls.
My directory structure is as such:
/ (site root; location of .htaccess)
/wiki/ (mediawiki root; location of LocalSettings.php)
Here's what I tried,
.htaccess:
RewriteEngine on
RewriteBase /
RewriteRule ^(.*)\&(.*)$ $1\%26$2
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^wiki/(.+)$ ./wiki/index.php?title=$1 [PT,L,QSA]
/wiki/LocalSettings.php:
## The URL base path to the directory containing the wiki;
## defaults for all runtime URL paths are based off of this.
## For more information on customizing the URLs please see:
## http://www.mediawiki.org/wiki/Manual:Short_URL
##
$wgScriptPath = "/wiki";
$wgScriptExtension = ".php";
$wgArticlePath = "$wgScriptPath/$1";
However, I do not get anything. I simply get a 403/Forbidden error; no 500 Internal Server Error, just a 403 - url http://www.example.com/. It's as if there's nothing being done. I've banged my head against the wall trying to figure this out. Any help is appreciated.
Thanks in advance!
What is the purpose of
RewriteRule ^(.*)\&(.*)$ $1\%26$2
You've lost me entirely on this one. Any URI with a second parameter will loop indefinitely and generate a 500 status return.
If you read the Rewrite documentation:
What is matched?
...If you wish to match against the ... query string, use a RewriteCond with the ... %{QUERY_STRING} variables
The & is normally part of the query parameter. It can appear in the RewriteRule pattern in the case of malformed URI (e.g. fred&q=1). By default, mod_rewrite will treat this as fred?q=1, but this converts it to the escaped %26 variant so this would be passed as a title fred&q=1 to MW (which is an invalid MW title by the way). I think that you should get rid of it or at least understand what you are trying to do here.
The last line should be
RewriteRule ^wiki/(.+) wiki/index.php?title=$1 [PT,L,QSA]
and keep the RewriteBase otherwise mod_rewrite can get confused.
This should work OK:-)
You're on the right track... if you're on a shared environment, then try this:
RewriteEngine on
# Comment to force base to be the subdir:
# RewriteBase /
RewriteRule ^(.*)\&(.*)$ $1\%26$2
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^wiki/(.+)$ ./wiki/index.php?title=$1 [PT,L,QSA]
Two hints:
If you're not in a hosted environment (= if it's your own server and you can modify the virtual hosts, not only the .htaccess files), try to use the RewriteLog directive: it helps you to track down such problems:
# Trace:
# (!) file gets big quickly, remove in prod environments:
RewriteLog "/web/logs/mywebsite.rewrite.log"
RewriteLogLevel 9
RewriteEngine On
My favorite tool to check for regexp:
http://www.quanetic.com/Regex (don't forget to choose ereg(POSIX) instead of preg(PCRE)!)
My ticket to HostGator resolved the issue, albeit un-helpfully. I was hoping for a single .htaccess solution, rather than a double .htaccess redirect/rewrite. However, here's my solution.
/:
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^.*$ http://www.example.com/wiki/
/wiki/:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?title=$1 [L,QSA]
I tried different solutions and what worked for me was changing .htaccess in mediawiki subfolder to
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wikifolder/index.php [L]
</IfModule>

How can I make my .htaccess skip rules conditionally?

I want to redirect all URLs that do not contain "_js","_css", "_img", etc., to my dispatch script. Somehow it doesn't work.
For instance, all files inside my /_js/ folder are unaccessible (meaning: they are sent to index.php instead of getting to the physical files residing in that folder).
Here is my htaccess:
IndexIgnore *
Options +FollowSymLinks
RewriteEngine on
# if the following conditions are met, SKIP the rewriteRules.
RewriteCond %{REQUEST_URI} ^/(_admin/¦_css/¦_js/¦_img/)
RewriteRule . - [S=9]
# Externally redirect to add missing trailing slash
RewriteRule ^(([a-z0-9._\-]+/)*[a-z0-9_\-]+)$ http://%{HTTP_HOST}/$1/?%{QUERY_STRING} [NC,R,L]
# SIX PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&menu=$3&content=$4&id=$5&title=$6&%{QUERY_STRING} [NC,L]
# FIVE PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&menu=$3&content=$4&id=$5&%{QUERY_STRING} [NC,L]
# FOUR PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&menu=$3&content=$4&%{QUERY_STRING} [NC,L]
# THREE PARAMS : projects/touch/texts/
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&menu=$3&%{QUERY_STRING} [NC,L]
# TWO PARAMS: downloads
RewriteRule ^downloads/([^/]+)/$ index.php?section=downloads&item=$1&%{QUERY_STRING} [NC,L]
# TWO PARAMS:
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&%{QUERY_STRING} [NC,L]
# TAG URL : index.php?tag=space%2C+navigable+music#5
RewriteRule ^tag/([a-z0-9_\-]+)/$ index.php?tag=$1&%{QUERY_STRING} [NC,L]
# ONE PARAM
RewriteRule ^([a-z0-9_\-]+)/$ index.php?section=$1&%{QUERY_STRING} [NC,L]
Edit:
Note my folder structure. Could it be the problem source?
I have a "v1" and "v2" folder structure. This .htaccess sits in the "v2" folder. one level above, i have a .htaccess that redirects all requests to "v2".
root
L.htaccess << dispatch between v1 and v2 folders
L v1 L v2 L.htaccess << the .htaccess code posted above
L _admin L all my website files & folders
You’re using the wrong character, ¦ (broken bar, U+00A6) instead of | (vertical line, U+007C), and wrong pattern for REQUEST_URI.
RewriteCond %{REQUEST_URI} ^/v2/(_admin/|_css/|_js/|_img/)
RewriteRule . - [S=9]
Or for the .htaccess file in your v2 directory just:
RewriteRule ^_(admin|css|js|img)/ - [S=9]
Here are some random fixes that may or may not fix the actual problem, which is not totally clear (see my comment) and which could be helped if you control the server and enable the RewriteLog, via:
RewriteLog "/tmp/rewrite.log"
RewriteLogLevel 9
but you have to put this in main server configuration.
That said, two main problems:
Lack of use of QSA flag (not really relevant)
Excessive use of slashes (probably relevant in the actual problem, see new version of the skipping rule)
Here goes the modified file
IndexIgnore *
Options +FollowSymLinks
RewriteEngine on
# if the following conditions are met, SKIP the rewriteRules.
RewriteCond %{REQUEST_URI} ^(_admin¦_css¦_js¦_img)
RewriteRule . - [L]
# Externally redirect to add missing trailing slash. Not really needed, AFAICS
# RewriteRule ^(([^/]+/)*[^/]+)$ http://%{HTTP_HOST}/$1/ [NC,R,L,QSA]
# SIX PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&menu=$3&content=$4&id=$5&title=$6 [NC,L,QSA]
# FIVE PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&menu=$3&content=$4&id=$5 [NC,L,QSA]
# FOUR PARAMS
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&menu=$3&content=$4 [NC,L,QSA]
# THREE PARAMS : projects/touch/texts/
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2&menu=$3 [NC,L,QSA]
# TWO PARAMS: downloads
RewriteRule ^downloads/([^/]+)/?$ index.php?section=downloads&item=$1 [NC,L,QSA]
# TWO PARAMS:
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2 [NC,L,QSA]
# TAG URL : index.php?tag=space%2C+navigable+music#5
RewriteRule ^tag/([^/]+)/?$ index.php?tag=$1 [NC,L,QSA]
# ONE PARAM
RewriteRule ^([^/]+)/?$ index.php?section=$1 [NC,L,QSA]
EDIT: Given the folder structure explained, try adding to the v2 .htaccess at the beginning the following:
RewriteBase /
You still haven't explained if you can or cannot use RewriteLog (I presume you can't)