Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Both RewriteRule's works fine, except when used together.

1.Remove all queries except query ?callback=.*:

# /api?callback=foo       has no rewrite
# /whatever?whatever=foo  has 301 redirect  /whatever
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^?#\ ]*)\?[^\ ]*\ HTTP/ [NC]
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
RewriteRule .*$ %{REQUEST_URI}? [R=301,L]

2.Rewrite index.php queries api and url=$1:

# /api           returns data  index.php?api&url=
# /api/whatever  returns data  index.php?api&url=whatever
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
RewriteRule ^([^.]*)$ index.php?url=$1 [QSA,L]

Any valid combination to this RewriteRule's on keeping its functionality?

This combination will return Server Error 404 to /api/?callback=foo:

# Remove all queries except query "callback"
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^?#\ ]*)\?[^\ ]*\ HTTP/ [NC]
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
RewriteRule .*$ %{REQUEST_URI}? [R=301,L]

# Rewrite index.php queries
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
# Server Error 404 on /api/?callback=foo and /api/whatever?callback=foo
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
RewriteRule ^([^.]*)$ index.php?url=$1 [QSA,L]
share|improve this question

migrated from stackoverflow.com Sep 27 '12 at 8:16

This question came from our site for professional and enthusiast programmers.

    
So what happens when you go to http://your.domain/index.php?url=api/whatever? –  Jon Lin Sep 24 '12 at 16:36
    
@JonLin, no idea why you are pointing on that URL. It removes query with 301 redirects to /index.php, since query is not ?callback=.*. –  Binyamin Sep 24 '12 at 17:31
    
Because that's what the second rule is rewriting to, if you comment out the first rule, then go to http://your.domain/index.php?url=api/whatever do you get a 404? Does index.php exist in your document root? If it does, is index.php returning a 404? –  Jon Lin Sep 24 '12 at 17:34
    
.htaccess and index.php are located in same path. Removing line 8 (second line from bottom) will redirect your mentioned URL to /index.php has redirect to /?callback=foo to /. But all queries must be removed except !/api(/.*)?\?callback=.*. –  Binyamin Sep 24 '12 at 17:57
    
Do you have something in /api/ that's handling the callback? –  Jon Lin Sep 24 '12 at 18:22

2 Answers 2

I guess I have to actually spell it out, after 3 comments asking you to remove the ! from your condition:

# Rewrite index.php queries
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
# Server Error 404 on /api/?callback=foo and /api/whatever?callback=foo
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]

This is the rule that you have that apparently tries to handle the /api requests, and this is what is happening:

  1. You request /api?callback=foo
  2. Check against condition RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
  3. Doesn't match because /api?callback=foo doesn't match !/api(/.*)?\?callback=.*. The ! says "the URI MUST NOT BE /api`
  4. Rule ends, nothing happens because condition fails

Another example

  1. You request /blah/
  2. Check against condition RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
  3. Condition matches because /blah is not /api?callback=
  4. Try to apply rule RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
  5. Rule fails because the regex says: the URI MUST START WITH /api, since URI is /blah, rule doesn't get applied, nothing happens.

So as you can see, no matter what, your rule will never do anything, ever. You need to change your condition so that it doesn't negate the /api, because YOU WANT the /api, it's the whole point of the rule to begin with. Just match against the query string:

RewriteCond %{QUERY_STRING} callback=
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]

Simply removing the ! is good enough, but it's redundant because you're matching against /api in the rule anyways:

# This works too
# Look! no more ! here -------------------v
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} /api(/.*)?\?callback=.*
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
share|improve this answer
    
Both your RewriteRule's returns Server Error 404 on accessing /whatever –  Binyamin Sep 27 '12 at 7:32
    
@Binyamin neither of them are supposed to handle /whatever, you've already got a rule for that, this is specifically to handle /api. It's supposed to replace the excerpt that I've taken out of the htaccess that you've posted in your question. –  Jon Lin Sep 27 '12 at 8:10
    
What I am saying - either /api will return Server Error 404. Your RewriteRule's does not work. –  Binyamin Sep 27 '12 at 8:42
up vote 0 down vote accepted

To enable RewriteRule for index.php, need to add in query rewrite exceptions.

This rules works fine and fixes this issue:

# Remove question mark and parameters
RewriteCond %{QUERY_STRING} .+
# Query rewrite exceptions
RewriteCond %{REQUEST_FILENAME} !index.php
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
RewriteRule .*$ %{REQUEST_URI}? [R=301,L]

# index.php query rewrite
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
RewriteRule ^([^.]*)$ index.php?url=$1 [QSA,L]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.