1

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]
12
  • So what happens when you go to http://your.domain/index.php?url=api/whatever?
    – Jon Lin
    Sep 24, 2012 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, 2012 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, 2012 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, 2012 at 17:57
  • Do you have something in /api/ that's handling the callback?
    – Jon Lin
    Sep 24, 2012 at 18:22

2 Answers 2

0

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]
3
  • Both your RewriteRule's returns Server Error 404 on accessing /whatever
    – Binyamin
    Sep 27, 2012 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, 2012 at 8:10
  • What I am saying - either /api will return Server Error 404. Your RewriteRule's does not work.
    – Binyamin
    Sep 27, 2012 at 8:42
0

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]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .