问题
I have a versioned Symfony API instance that I want to configure in the following manner:
- api.com/api/v1 -> /srv/api-v1/public/index.php
- api.com/api/v2 -> /srv/api-v2/public/index.php
I've tried to approach this using nginx location and aliases, as it's Symfony we use try_files (as recommended) to check for an actual file prior to defaulting to index.php
.
Problem
It seems there is a known nginx bug that breaks the $uri
variable with an alias
and try_files
.
How can I get around this bug to achieve my desired outcome?
nginx conf
server {
listen 443 http2;
listen [::]:443 http2;
server_name api.com;
root /srv/default/public/; # default root when no version
location /api/v1 {
alias /srv/api-v1/public/;
try_files $uri /index.php$is_args$args;
}
location /api/v2 {
alias /srv/api-v2/public/;
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
include /etc/nginx/fastcgi.conf;
fastcgi_pass unix:/run/php-fpm-php7.2.socket;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
internal;
fastcgi_read_timeout 300;
}
}
Attempted fix
Going by this hacky fix I have created the following which does work but generates a huge config file, not ideal:
upstream v1 {
server 127.0.0.1;
}
upstream v2 {
server 127.0.0.1;
}
server {
listen 443 http2;
listen [::]:443 http2;
server_name api.com;
location /api/v1 {
proxy_pass http://v1;
}
location /api/v2 {
proxy_pass http://v2;
}
}
server {
server_name v1;
root /srv/api-v1/public/;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
include /etc/nginx/fastcgi.conf;
fastcgi_pass unix:/run/php-fpm-php7.2.socket;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
internal;
}
}
server {
server_name v2;
root /srv/api-v2/public/;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
include /etc/nginx/fastcgi.conf;
fastcgi_pass unix:/run/php-fpm-php7.2.socket;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
internal;
}
}
回答1:
There is another workaround exists which can be used when an alias
directive is used in conjunction with the try_files
one (see this answer for an example). Can you try the following config?
server {
listen 443 http2;
listen [::]:443 http2;
server_name api.com;
root /srv/default/public/; # default root when no version
location ~ ^/api/v1(?<v1route>/.*)? {
alias /srv/api-v1/public;
try_files $v1route /api/v1/index.php$is_args$args;
location ~ ^/api/v1/index\.php$ {
internal;
include /etc/nginx/fastcgi.conf;
fastcgi_param SCRIPT_FILENAME /srv/api-v1/public/index.php;
fastcgi_read_timeout 300;
fastcgi_pass unix:/run/php-fpm-php7.2.socket;
}
}
location ~ ^/api/v2(?<v2route>/.*)? {
alias /srv/api-v2/public;
try_files $v2route /api/v2/index.php$is_args$args;
location ~ ^/api/v2/index\.php$ {
internal;
include /etc/nginx/fastcgi.conf;
fastcgi_param SCRIPT_FILENAME /srv/api-v2/public/index.php;
fastcgi_read_timeout 300;
fastcgi_pass unix:/run/php-fpm-php7.2.socket;
}
}
}
回答2:
In the "hacky fix" you are missing the trailing /
to your proxy_pass
directives.
Here is a repo to easily test your implementation: https://github.com/MelwinKfr/nginx-workaround97
See this thread if you want more info about the trailing slash.
来源:https://stackoverflow.com/questions/65093486/nginx-alias-breaks-due-to-try-files-uri-alias-bug