5

I have an index file that builds content based on n PATH_INFO variables.

Example:

site.com/A/B/n/

should use index.php at either:

site.com/index.php?var1=A&var2=B&varN=n
 - or - 
site.com/index.php/A/B/n/

instead of:

site.com/A/B/n/index.php || which doesn't exist ||

So far I've tried a number of variations of:

RedirectMatch ^/.+/.*$ /

with no success.

I have an inelegant and unscalable solution here:

RewriteEngine On 
RewriteRule ^([a-zA-Z0-9_-]+)/?$ index.php?p1=$1 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2&p3=$3 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2&p3=$3&p4=$4 [NC,L]

Problems with this solution:

  • Inelegant and unscalable, requires manual line for each subdirectory
  • Fails with non alphanumeric characters (primarily +,= and &) ex. site.com/ab&c/de+f/ (note, even changing the regex to ^([a-zA-Z0-9_-\+\=\&]+)/?$ does little to help and actually makes it error out entirely)

Can you help?

Ryan
  • 14,682
  • 32
  • 106
  • 179
  • So .. which do you prefer: `site.com/index.php?var1=A&var2=B&varN=n` (requires multiple rules) or `site.com/index.php/A/B/n/` (can be done with single rule) ? – LazyOne Jul 29 '11 at 20:56
  • I'm up for either. All being equal I'd prefer the one with one line. – Ryan Jul 29 '11 at 21:30

3 Answers3

8

Option 1: (site.com/index.php?var1=A&var2=B&varN=n):

Options +FollowSymLinks -MultiViews
RewriteEngine On

# do not do anything for already existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]

RewriteRule ^([^/]+)/?$ index.php?p1=$1 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2&p3=$3 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2&p3=$3&p4=$4 [QSA,L]

1. You had [NC] flag ... so there were no need to have A-Z in your pattern.

2. Instead of [a-zA-Z0-9_-\+\=\&] or [a-zA-Z0-9_-] I use [^/] which means any character except slash /.

3. [QSA] flag was added to preserve existing query string.

Option 2: (site.com/index.php/A/B/n/):

Options +FollowSymLinks -MultiViews
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/$1 [L]

In reality, if you do not plan to show that URL anywhere (like, 301 redirect etc), the last line can easily be replaced by RewriteRule .* index.php [L] -- you will look for original URL using $_SERVER['REQUEST_URI'] in your PHP code anyway.

LazyOne
  • 158,824
  • 45
  • 388
  • 391
  • Above and beyond, LazyOne. It's a thing of beauty. It even cures the plus sign mod_rewrite problem I've read so much about. Great work. – Ryan Jul 29 '11 at 22:16
  • what should I do if I have a sub-directory in the rott directory with the same name as the url? lets say i wish to access 'www.domain.com/preferences' but I have preferences folder – Tal Jan 21 '15 at 12:31
  • @Tal You have to add it to the "exclusion list" (additional condition) as right now it will/should treat it as access to existing folder by `RewriteCond %{REQUEST_FILENAME} !-d` part – LazyOne Jan 21 '15 at 12:47
  • @LazyOne And how do I create this condition/exclusion list? – Tal Jan 21 '15 at 13:08
  • @Tal You better create separate question describing your situation. Right now I have no access to any of the Apache servers to verify my ideas (and I need it as I have not used Apache for a few months and do not want to give you wrong advices -- have not been answering such htaccess/Apache questions for over a year now -- need some test environment to check my thoughts/ideas **before** answering). – LazyOne Jan 21 '15 at 13:28
  • @LazyOne [New Question Link](http://stackoverflow.com/questions/28069396/angular-spa-integration-with-apache) – Tal Jan 21 '15 at 14:17
  • Option 2 is best to build a simple RESTful API. THANK YOU! – 夏期劇場 Feb 28 '17 at 09:37
4

Adding the following will redirect all traffic (for files that do not exist) to the index page:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php [NC]

Then, you can make your decision in index.php by parsing the 'REQUEST_URI'

Scripty
  • 53
  • 1
0

RewriteRule ^/.+ / [R=301,L]

any url with any kind of path beyond root will be redirected to root.

^ = start of url
/ = a slash
.+ = 1 or more characters
Or Gal
  • 1,298
  • 3
  • 12
  • 20