3

I'm trying to configure nginx in front of HHVM to serve up an API which has a landing page listing available versions at / and the actual installed API versions at /api/[version]/.

My nginx config so far is as follows:

server {
    listen *:80;
    server_name api.domain.com;

    # Character Set
    charset utf-8;

    # Logs
    access_log /www/vhosts/api.domain.com/logs/access_log.nginx;
    error_log /www/vhosts/api.domain.com/logs/error_log.nginx;

    # Directory Indices
    index index.php;

    # Document Root
    root /www/vhosts/api.domain.com/public;

    # Location
    location /assets {
        try_files $uri $uri/ =404;
    }
    location /api/1.0 {
        root /www/vhosts/api.domain.com/api/1.0/public;
        rewrite ^/api/1.0(.*)$ /index.php$1;
        try_files $uri $uri/ /index.php?$query_string;
    }
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt  { log_not_found off; access_log off; }

    # Error Pages
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;

    location ~ \.(hh|php)$ {
        fastcgi_keep_conn on;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    # Block access to .htaccess
    location ~ \.ht {
        deny all;
    }
}

Requests to http://api.domain.com/ serve up the landing page correctly, however requests to http://api.domain.com/api/1.0/foo are still sent through to the index.php at /www/vhosts/api.domain.com/public/index.php instead of the one at /www/vhosts/api.domain.com/api/1.0/public/index.php.

Does anyone know how I can solve this problem? The Apache configuration I am switching across from is below for reference:

<VirtualHost *:80>
    ServerAdmin tech@domain.com
    ServerName api.domain.com

    DocumentRoot /www/vhosts/api.domain.com/public/
    <Directory /www/vhosts/api.domain.com/public/>
        Options -Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        allow from all
    </Directory>

    ErrorLog /www/vhosts/api.domain.com/logs/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog /www/vhosts/api.domain.com/logs/access.log combined
    ServerSignature Off

    Alias /api/1.0 "/www/vhosts/api.domain.com/api/1.0/public/"
    <Directory /www/vhosts/api.domain.com/api/1.0/public/>
        Options -Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        allow from all
    </Directory>

    Alias /api/latest "/www/vhosts/api.domain.com/api/1.0/public/"

    SetEnv APPLICATION_ENV testing
</VirtualHost>

On an unrelated note, can someone please tag this with hhvm for me? I need at least 300 reputation to create the tag, and apparently no-one's ever asked any hhvm-related questions on here yet. :/

EDIT:

As per krisFR's suggestion below, I've tried modifying the location /api/1.0 block as follows:

    location /api/1.0 {
        alias /www/vhosts/api.domain.com/api/1.0/public;
        try_files $uri $uri/ /index.php?$query_string;
    }

However, this loads the code from /www/vhosts/api.domain.com/public/index.php instead of the code I want it to load at /www/vhosts/api.domain.com/api/1.0/public/index.php. Any further ideas?

  • I think the main caveat has to do with the location ~ \.(hh|php)$ block that always run $document_root$fastcgi_script_name... – krisFR Aug 5 '14 at 20:52
  • Hmm… Shouldn't the root /www/vhosts/api.domain.com/api/1.0/public; in location /api/1.0 override that, though? – Benjamin Nolan Aug 6 '14 at 10:11
1

Source https://stackoverflow.com/questions/20426812/nginx-try-files-alias-directives

This is a long standing bug in nginx. But you can work around by using the root directive again. Kind of a hack, but at least it works.

At same time I would add a slashes to the locations directives.

location /api/1.0/ {
    root /www/vhosts/api.domain.com/api/1.0/public/;
    try_files $uri $uri/ /index.php?$query_string;
}
1

NGinx also has an alias directive.

Give it a try :

location /api/1.0/ {
    alias /www/vhosts/api.domain.com/api/1.0/public/;
    ...
}

Edit :

You could try this :

location ^~ /api/1.0/ {
    alias /www/vhosts/api.domain.com/api/1.0/public/;
    ...
}
  • Hmm… location /api/1.0 { alias …etc…; try_files …etc…; } loads up the code from /www/vhosts/api.domain.com/public. Any ideas? – Benjamin Nolan Aug 5 '14 at 17:44
  • @TwoWholeWorms I've edited my answer – krisFR Aug 5 '14 at 17:54
  • Nope. :( Still loads the code from /. :/ – Benjamin Nolan Aug 5 '14 at 17:59
  • tried using root not alias root /www/vhosts/api.domain.com/api/1.0/public in location block? – Antony Gibbs May 28 '16 at 12:22
  • did it work ? <!--> – Jigar Joshi Sep 11 '16 at 17:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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