Configure Apache to rewrite API calls

Christian Dreher asked:

I have a project constisting of two parts. First, the API, where all data requests are handled. Second, a web client, so that users can use the tool conveniently. The web client therefore just makes API calls.

The project structure is the following:

/var/www
    /myproject
        /api
            /v1
                Controller.php /* this is the API v1 controller */
        /webclient
            /views /* just some templates ... */
            /public /* all public stuff, like css, html, images, ... */
                index.php /* index file for web client */

I configured Apache to have /var/www/myproject/webclient/public as document root, and I had an Alias so that calls to myproject.host.loc/api/v1/Controller.php?<much-params> would be redirected to /var/www/myproject/api/v1.

I now wanted to have ‘prettier’ API calls, like:

myproject.host.loc/api/v1/add-item?name=fubar&api-key=4234&token=6344

Instead of:

myproject.host.loc/api/v1/Controller.php?request=add-item&name=fubar&api-key=4234&token=6344

Therefore, I wanted to map every URI which requests /api/v1 to Controller.php and let the script do the rest. I don’t want any other resource or script in /var/www/myproject/api/v1 to be accessed directly.

I tried to do that with the following Apache virtual host:

<VirtualHost *:80>

    DocumentRoot /var/www/myproject/webclient/public
    ServerName myproject.host.loc

    Alias /api/v1 /var/www/myproject/api/v1
    <Directory /var/www/myproject/api/v1>
        RewriteBase    /api/v1/
        RewriteEngine  On
        RewriteCond    %{REQUEST_FILENAME} !-f
        RewriteCond    %{REQUEST_FILENAME} !-d
        RewriteRule    api/v1/(.*)$ api/v1/Controller.php?request=$1 [QSA,NC,L]
    </Directory>

</VirtualHost>

The webclient shows up, but the intended way I would like to call the API does not work. If I open myproject.host.loc/api/v1 in the browser, it just shows me the Index of /api/v1, containing every file. It seems like the rewrite rule is completely ignored. I can also access the API in the ‘old’ way, but I want to replace it with the new, ‘prettier’ call. (Also for security reasons, so that only the controller is callable from the outside)

How can I accomplish this? I tried several ways to do so, including:

  • Completely remove Alias and replace it with Rewrite. This resulted in infinite loops or I would have to use the webclient with the URL myproject.host.loc/webclient/public
  • With or without RewriteBase. Seems like this is ignored, too. Does not change anything
  • Appended or removed every trailing / in any possible combination. (I was desperate)

While searching for a solution, I have found a resource where someone says, that you can’t use Alias with Rewrite, but I have also found people saying that it is possible… I am quite confused now.

I hope someone can help me with this

My answer:


This appears to be a problem:

        RewriteBase    /api/v1/
        RewriteRule    api/v1/(.*)$ api/v1/Controller.php?request=$1 [QSA,NC,L]

Remember that RewriteBase is prepended to the condition in the RewriteRule. So you’ve asked for rewriting URLs that begin with /api/v1/api/v1/.

Simply remove the duplication.


View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.