wordpress.htaccessmod-rewritewordpress-json-api

How to rewrite Rule in apache for wordpress json API v1 and v2


I'm trying to develop a vuejs frontend site with wordpress as headless CMS.

so far everything is fine, but one thing worries me.

the frontend is served at domain.com/index.html so I renamed the wordpress root document index.php to _index.php. For reading the /wp-json/v2/ API I added

RewriteRule ^wp-json/(.*) /_index.php [L] 

to the apache .htaccess file to redirect the call.

However, if I now also want to call the old json API with ?json=, the

RewriteRule ?json(*) /_index.php [L]   

or

RewriteRule ^?json=(.*) /_index.php [L] 

does not work.

how can I use both APIs, no idea why the rewriteRule doesn't work.

this is how mine looks

<IfModule mod_rewrite.c>
   RewriteEngine On
   RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
   RewriteBase /
   RewriteRule ^wp-json/(.*) /_index.php [L]
   #RewriteRule ^?json(*) /_index.php [L]
   RewriteRule ^index\.html$ - [L]
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteRule . /index.html [L]
</IfModule>

by the way: is there a way with the json API V2 to output the pages recursively as Parent/Child tree?


Solution

  • so I renamed the wordpress root document index.php to _index.php

    Why? If you are having issues with index.php taking priority when requesting the root directory then reset the DirectoryIndex. For example:

    DirectoryIndex index.html
    

    Now, only index.html will be checked for when requesting a directory. (It was probably set to something like DirectoryIndex index.php index.html previously, so index.php would take priority.)

    RewriteRule ^?json=(.*) /_index.php [L] 
    

    The RewriteRule pattern matches against the URL-path only, which notably excludes the query string. To match the query string you need to use a separate condition (RewriteCond directive) and check against the QUERY_STRING server variable.

    For example:

    RewriteCond %{QUERY_STRING} ^json=
    RewriteRule ^$ index.php [L]
    

    The regex ^$ ensures that only requests for the document root are matched and not any URL-path.

    ^json= matches any query string that starts json=. The (.*) part is not required. The QUERY_STRING server variable does not include the ? delimiter itself.

    NB: The regex ?json(*) (in your first example) is not valid and you'd expect to get a 500 response (if on Apache), since the regex would fail to compile.

    The / prefix on the substitution string is not required and should be avoided. (This now makes use of the RewriteBase directive - which isn't actually required here anyway.)

    So, in summary, it would look like this, with a few minor tweaks:

    # Limit the directory index to "index.html" only
    DirectoryIndex index.html
    
    RewriteEngine On
    
    # Pass Authorization header to backend on CGI
    RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    
    # Stop early if the front-controllers are already reached
    RewriteRule ^index\.(html|php)$ - [L]
    
    # WordPress API
    RewriteRule ^wp-json/ index.php [L]
    RewriteCond %{QUERY_STRING} ^json=
    RewriteRule ^$ index.php [L]
    
    # VueJS
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . index.html [L]