简体   繁体   中英

Nginx and Laravel: How to restrict “location” block to from “/” to “/api”?

I have a Laravel application that I would like to use only for its /api routes. When / , /login , /profile , etc are accessed, I would like nginx to serve the index file located in the base root, /var/www/html/index.html .

Here's my current default.conf . The /api routes work, but it also serves / from the backend, which I don't want. If I simply change location / to location /api , then the /api routes become inaccessible, and trying to access them returns the index file located in the base root, /var/www/html/index.html . This is the opposite of what I am trying to achieve. Haha.

How can I keep the /api routes accessible, while also preventing / from being served by the backend?

server {

    listen  80;
    root /var/www/html;
    server_name _;
    index index.php index.html index.htm;

    # API routes should be handled by the backend (Laravel).
    ##### I want to change the following line from "/" to "/api".
    location / {
        root /var/www/backend/public;
        try_files $uri $uri/ /index.php?$query_string;

        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param SCRIPT_NAME $fastcgi_script_name;
            fastcgi_index index.php;
            include fastcgi_params;
        }

    }

}

According to your configuration, that should already be happening.

the directive:

try_files $uri $uri/ /index.php?$query_string;

Will attempt first to locate the static file, and if the static file exists and is not a php file, it will be served by nginx directly. Only if it is a php file will it be served with the php backend.

If you want to prevent .php files from being executed at all, you can modify to separate the / location from the /api location:

location ~ ^/api/.*\.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    fastcgi_index index.php;
    include fastcgi_params;
}

I accomplished this, but somewhat inelegantly. I have 2 location blocks:

  • location ~ "^(?!/api).*$" matches all routes except those that begin with /api .
  • location / matches all other routes. The reason that it does not match all routes is simply that nginx matches location blocks with regular expressions first.

Strangely, using a regular expression for the second block to match all routes that do begin with /api did not work. I still don't understand why.

server {
  listen  80;
  root /var/www/html;
  server_name _;
  index index.php index.html index.htm;

  # All non-API routes should be handled by the frontend.
  # Use a regular expression to identify all requests
  # that do NOT begin with "/api".
  location ~ "^(?!/api).*$" {
    root /var/www/frontend/public;
    try_files $uri $uri/ /index.html =404;
  }

  # API routes should be handled by the backend (Laravel).
  # (Since regex-based location blocks are matched first,
  # this will be a fallback to the above location block).
  location / {
    root /var/www/backend/public;
    try_files $uri $uri/ /index.php?$query_string;

    location ~ \.php$ {
      fastcgi_split_path_info ^(.+\.php)(/.+)$;
      fastcgi_pass unix:/var/run/php-fpm.sock;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param SCRIPT_NAME $fastcgi_script_name;
      fastcgi_index index.php;
      include fastcgi_params;
    }

  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM