1

I have an .htaccess file that looks like the following:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.+?)/(\d+?)/?$ index.php?cmd=$1&num=$2 [L]
  RewriteRule ^(.+?)/?$ index.php?cmd=$1 [L]
</IfModule>

Basically, I'm trying to write an API that can handle requests like get_all/ or get/123/.

The problem is, when I try to go to either of the above URLs, the cmd parameter is always set to index.php and the num parameter is not set at all.

If I comment out either of the RewriteRule lines, then requests work for the remaining, uncommented out RewriteRule, but I need to be able to handle both cases.

I am aware of the looping that occurs with mod_rewrite, but in this case, I have no clue how to stop it. I can't even understand why the above rules are causing cmd to be set to index.php.

Can anyone please explain what is happening here and how to fix it?
Thank you.

Machavity
  • 30,841
  • 27
  • 92
  • 100
HartleySan
  • 7,404
  • 14
  • 66
  • 119
  • Maybe just by adding "RewriteBase /" under RewriteEngine On if you are in a subfolder and use a subdomain? – NVRM Dec 30 '14 at 03:17

1 Answers1

1

Rules are behaving because RewriteCond is only applied to very next RewriteRule. Due to this your last RewriteRule is running without conditions and hence running twice by mod_rewrite loop.

Use this code to fix it:

<IfModule mod_rewrite.c>
  RewriteEngine On

  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.+?)/(\d+?)/?$ index.php?cmd=$1&num=$2 [L]

  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.+?)/?$ index.php?cmd=$1 [L]
</IfModule>

If you want to avoid repetition of Rewriteond then use:

<IfModule mod_rewrite.c>
  RewriteEngine On

  # skips files and directories from rewrite rules
  RewriteCond %{REQUEST_FILENAME} -d [OR]
  RewriteCond %{REQUEST_FILENAME} -f
  RewriteRule ^ - [L]

  RewriteRule ^(.+?)/(\d+?)/?$ index.php?cmd=$1&num=$2 [L]

  RewriteRule ^(.+?)/?$ index.php?cmd=$1 [L]
</IfModule> 
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • Once again, you saved the day! Thank you so much. I get why the first one works, but how does the `RewriteRule ^ - [L]` in the second one work? – HartleySan Dec 30 '14 at 04:08
  • `RewriteRule ^ - [L]` means do nothing if above conditions work i.e. file or directory check. – anubhava Dec 30 '14 at 04:11
  • anubhava, thanks again for all your help and explanations. Unfortunately, the second solution (the one without the duplicate `RewriteCond` lines) does not work. Any clue why? Thanks. – HartleySan Dec 30 '14 at 13:16
  • The first works great, but when I copy and paste the second one into my `.htaccess` file, it doesn't work. I can't test it this very second, but I'll note the error later (I believe it's a 404). – HartleySan Dec 30 '14 at 13:55
  • Did you have 2 `RewriteCond` lines before `RewriteRule ^ - [L]`? I have been using it on my live website without any problem. – anubhava Dec 30 '14 at 13:59
  • 1
    Sorry about the confusion. It did work. I must have not copied and pasted it correctly the first time, as it didn't work before, but now it does. Not sure why, but works great now. Thanks again. – HartleySan Dec 30 '14 at 16:27