4

I have a .htaccess rule that basically points all access through one page, and I have PHP handling it from that point. So, no matter what directory it is in, it'll pass all URLs to this script.

If my root was /project/ ( example.com/project/some/page/where ), /some/page/where would get redirected to @frontend.php

RewriteRule !\.(js|ico|gif|jpg|png|css|pdf|swf|doc)$ @frontend.php

I've reached a point however, where I want to be able to push a subset of pages through to a different handler, like so ( example.com/project/api/page/where, not example.com/project/some/api/where ):

RewriteRule ^/api?$ @api.php

Problem is, this does not work, no matter if this rule is above or below the other one. Can anyone suggest how I would be able to do this?

I have also tried:

RewriteRule ^/api(/.*)? @api.php [L]

RewriteCond %{REQUEST_URI} !/api
RewriteRule !\.(js|ico|gif|jpg|png|css|pdf|swf|doc)$ @frontend.php [L]

And while this works in that http://example.com/project/api/page/where doesn't get pushed to @frontend.php, it doesn't get it to @api.php, and produces:

[Wed Apr 18 10:46:12 2012] [error] [client 127.0.0.1] File does not exist: /www/project/api

EDIT:

My latest attempt is:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^api(/.*)? @api.php [L]

RewriteCond %{REQUEST_URI} ^api
RewriteRule !\.(js|ico|gif|jpg|png|css|pdf|swf|doc)$ @frontend.php

The problem with this one is that if the URL starts with anything except api/, like ( example.com/project/test/page/where ) it throws the error:

[Sat Apr 21 10:50:13 2012] [error] [client 127.0.0.1] File does not exist: C:/xampp/www/projects/frame3/test
Ben Dauphinee
  • 4,061
  • 8
  • 40
  • 59

3 Answers3

1

the problem is that the second request is tested against the htaccess as well, so you have two requests in fact. As there is no js/ico/gif whatsoever the rule fits. You can manage this either with RewriteConds or regileros (better) approach using Apache's {ENV:REDIRECT_STATUS} mechanism. See this question for further information.

EDIT: I've set up a little example at http://playground.rexbooks.com/stack. If you type in, f.e. http://playground.rexbooks.com/stack/api/123456 it will redirect you to api.php. Any other query will be redirected to frontend.php. The clue was to check if a file really exists. I've split up your other rule as well. RewriteBase is only for my setting, you will need to adjust it. To not make the uris transparent, remove the rewrite (R) flag. Is this what you were after?

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^api(/.*)? /api.php [L,R]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !api
RewriteCond %{REQUEST_URI} !\.(js|ico|gif|jpg|png|css|pdf|swf|doc)$
RewriteRule (.*) /frontend.php [L,R]
Community
  • 1
  • 1
Jan
  • 42,290
  • 8
  • 54
  • 79
  • That's close. It has to work without RewriteBase though. To this point, that's why the @frontend.php rule worked so well was that I didn't have to set RewriteBase. – Ben Dauphinee Apr 20 '12 at 21:14
  • I have to admit, that I don't really know what the at-sign before fronted.php does (does it anything at all?). Obviously, you can have the rules without RewriteBase, you will only have to write down relative paths. I've edited my example in order to have it without RewriteBase. – Jan Apr 21 '12 at 06:02
  • Thanks. The @ sign does nothing other than make the file more obscure so that most people won't just trip over it. It serves no URL rewrite purpose at all. I could have used _, ~, or = if I wanted. – Ben Dauphinee Apr 21 '12 at 13:34
  • Also, first rule works, second rule breaks. This is of course if I change to @frontend instead of /frontend, since /frontend pushes the user to the root of the site. – Ben Dauphinee Apr 21 '12 at 13:40
1

Place a .htaccess in the directory containing the "@frontend.php" and "@api.php" files with the following content :

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^api @api.php [QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ @frontend.php [QSA,L]

The !-f will prevent the rewrite for any existing file. To deny the rewrite only for the specified extensions use the following .htaccess instead

RewriteEngine On

RewriteCond %{REQUEST_URI} !\.(js|ico|gif|jpg|png|css|pdf|swf|doc)$
RewriteRule ^api @api.php [QSA,L]

RewriteCond %{REQUEST_URI} !\.(js|ico|gif|jpg|png|css|pdf|swf|doc)$
RewriteRule ^ @frontend.php [QSA,L]

Of course the following line should also work, but what is the point of capturing what comes after api if we don't use it after...

RewriteRule ^api(/.*)? @api.php [L]
smrtl
  • 604
  • 5
  • 7
0

Here you go. These types of rules have worked for me:

  # redirect Drupal urls straight to Drupal (or in your case api.php)
  RewriteRule ^admin/(.*)$ api.php?q=admin/$1 [L,QSA]
  RewriteRule ^admin_menu/(.*)$ api.php?q=admin_menu/$1 [L,QSA]
  RewriteRule ^node/(.*)$ api.php?q=node/$1 [L,QSA]
  RewriteRule ^content/(.*)$ api.php?q=content/$1 [L,QSA]

  # Another way to redirect based on query strings    
  RewriteCond %{QUERY_STRING} ^q=([^&]+)$
  RewriteRule . api.php?q=$1 [L,QSA]

  # if a directory or a file exists, use it directly
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico

  # otherwise forward it to index.php
  RewriteRule . index.php

I've got this running to integrate a Drupal / Yii framework setup and it's working quite smoothly. The combination of rules above should help you get going.

Let me know if you want me to clarify it further for your exact setup.

acorncom
  • 5,975
  • 1
  • 19
  • 31