NGINX: map e try_files não funcionam

Oct 08 2020

Estou usando o nginx para detectar suporte webp no navegador:

# Check if client is capable of handling webp
map $http_accept $webp_suffix {
       default "";
       "~*webp" ".webp";
}

este código funciona bem e atribua .webp a $ webp_suffix quando o cliente suporta image / webp

então, algumas linhas depois, estou usando essa variável na seguinte configuração:

        location ~ ^/imgs/([0-9]*)/(.*?)(\..+)$ {
                add_header X-webp $webp_suffix; try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
        }

e SEMPRE resulta em e404, mesmo se os dois arquivos existirem. O cabeçalho X-webp está definido como ".webp", portanto, o mapa está funcionando bem.

O que é mais estranho - se eu trocar a ordem dos argumentos try_files de:

try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;

para

try_files /imgs/$1$3 /imgs/$1$webp_suffix =404;

então funcionou e enviou o arquivo / imgs / $ 1 $ 3 para o navegador. Como isso é possível ? Estou faltando alguma coisa nesta lógica?

EDIT1: Complete nginx.conf para reproduzir:

events {
    use           epoll;
    worker_connections  128;
}

http {

    # Check if client is capable of handling webp
    map $http_accept $webp_suffix { default ""; "~*webp" ".webp"; } server { listen *:8888; server_name test; root /srv; location ~ ^/imgs/([0-9]*)/(.*?)(\..+)$ {
                    add_header X-webp $webp_suffix; try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
            }

    }
}

EDIT2: O que é ainda mais estranho - se eu mudar:

try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;

para:

try_files /imgs/$1.webp /imgs/$1$3 =404;

então try_files funciona conforme o esperado (mas não estamos verificando o suporte webp no cliente agora, simplesmente assumindo que ele oferece suporte). Lembre-se de que:

add_header X-webp $webp_suffix;

no mesmo local resulta no cabeçalho adicionado: X-webp .webp

então por que / imgs / $ 1$webp_suffix does not work and /imgs/$1.webp funciona?

O que eu testei:

  1. $ webp_suffix = ".webp" (testado e funciona)
  2. try_files / imgs / $ 1$webp_suffix /imgs/$1 $ 3 = 404 - NÃO funciona e retorna 404
  3. try_files /imgs/$1.webp / imgs /$1$3 = 404 - funciona e retorna o arquivo webp
  4. try_files / imgs /$1$3 / imgs /$1$webp_suffix = 404 - funciona e retorna arquivo jpg

o que não faz sentido algum

EDIT3:

Para o teste, estou abrindo: http: // test: 8888 / imgs / 10 / qualquer que seja.jpg

Os arquivos /srv/imgs/10.jpg e /srv/imgs/10.webp existem.

Respostas

7 RichardSmith Oct 08 2020 at 00:50

A try_filesinstrução está usando capturas numéricas da expressão regular na locationinstrução. O problema com as capturas numéricas é que elas são substituídas sempre que uma expressão regular é avaliada. O mapcontém uma expressão regular que é avaliada entre locatione as try_filesinstruções.

A solução é usar capturas nomeadas:

Por exemplo:

location ~ ^/imgs/(?<prefix>[0-9]*)/(.*?)(?<suffix>\..+)$ { add_header X-webp $webp_suffix;
    try_files /imgs/$prefix$webp_suffix /imgs/$prefix$suffix =404;
}