Bloco de localização Nginx - corresponde apenas aos arquivos reais

2

Eu tenho a seguinte configuração do nginx:

server {
    listen 8080;

    root /site_root/web;
    index index.html;

    server_name www.mysite.com;

    location / {
        try_files $uri @rewriteapp;
    }

    location @rewriteapp {
        rewrite ^(.*)$ /app.php/$1 last;
    }

    # add headers to static files
    location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ {
        expires 365d;
        add_header Pragma public;
        add_header Cache-Control "public";
    }

    location ~ \.php {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS $https;
        fastcgi_pass unix:/var/run/php-fpm-www.sock;
    }
}

Problema Este é um aplicativo php padrão com front controller e alguns ativos estáticos (js / css etc) como arquivos no sistema de arquivos (para argumentos, a localização desses arquivos é '/ site_root / web / assets').

A intenção da configuração acima é adicionar cabeçalhos 'max-age' a esses arquivos estáticos para permitir que os navegadores os armazenem em cache. Isso funciona para todos os arquivos que existem no sistema de arquivos. No entanto tenho alguns recursos que são gerados dinamicamente e precisam passar pelo php ('/site_root/web/assets/dynamic/file.uk.js', '/ site_root / web / assets / dynamic / file.us.js ',' /site_root/web/assets/variable/variable.uk.js ').

A questão é que a inclusão da diretiva de localização 'adicionar cabeçalhos a arquivos estáticos' está causando esses arquivos dinâmicos para o 404. Como eu posso (na ordem de quão desejável cada solução é):

  • Altere a diretiva location para excluir arquivos que não existem no servidor (usando try_files / internal?)

  • Altere a diretiva de localização para excluir os caminhos correspondentes (uma lista de permissões, por exemplo, "variável dinâmica")

por calumbrodie 03.06.2015 / 19:26

2 respostas

2

O Nginx usa apenas um bloco de localização

Isso se resume ao fato de que O nginx usará apenas um bloco de localização . Qualquer coisa em outros blocos de localização é ignorado. Na pergunta, qualquer solicitação que corresponda ao bloco de localização "arquivos estáticos", independentemente de o arquivo existir ou não, será processada apenas por esse bloco de localização. Sempre que há alguma ambigüidade, eu acho uma técnica útil para depuração:

location /something-else {
    add_header "section" "something else location"; 
    # ^ if this location block is used, that header is in the output
    ...
}

Nos cabeçalhos de uma resposta, o cabeçalho adicionado do bloco correspondente será incluído:

$ curl -I "http://nginx.h5bp.dev/something"
...
section: something location # <- like so

Soluções

Existem muitas soluções, e você pode encontrar este material de referência útil para ler. Uma coisa a ter em mente é que o nginx se destina a ser usado com roteamento de prefixo - o que torna a vida fácil para o nginx e para você.

Roteamento de prefixo

Então, se você puder fazer isso:

location ~ ^/(css|images|js)/ {
    expires 365d;
    add_header Pragma public;
    add_header Cache-Control "public";
}

location ~ \.php {
    ...
}

Essa seria a solução ideal. Uma extensão para isso usando blocos de localização aninhados também pode ser usada, se for necessário:

location ~ ^/(css|images|js)/ {
    location ~* \.(?:whatever|ext)$ {
        expires 365d;
        add_header Pragma public;
        add_header Cache-Control "public";
    }
}

location ~ \.php {
    ...
}

Coloque os arquivos try em todos os blocos de localização

Na questão, há um bloco de localização - então esta é uma alternativa óbvia, como mencionado por Micheal:

location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ {
    try_files $uri @rewriteapp; # <- added
    expires 365d;
    add_header Pragma public;
    add_header Cache-Control "public";
}

location ~ \.php {
    ...
}

Se você tem vários blocos de localização, isso fica muito entediante (embora, provavelmente, também indique não usar o nginx como projetado)

404 Controlador Frontal

A configuração will-always-work, independentemente de como são seus blocos de localização, é usar um front controller 404. No seu caso, isso significaria:

server {
    listen 8080;

    root /site_root/web;
    index index.html;

    server_name www.mysite.com;

    try_files $uri $uri/ @rewriteapp;
    error_page 404 = @rewriteapp

    location @rewriteapp {
        rewrite ^ /app.php/$request_uri last;
    }

    # add headers to static files
    location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ {
        expires 365d;
        add_header Pragma public;
        add_header Cache-Control "public";
    }

    location ~ \.php {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS $https;
        fastcgi_pass unix:/var/run/php-fpm-www.sock;
    }
}

Ou similar. Escolha a solução que funciona para você e é a mais simples.

    
por 04.06.2015 / 11:10
1

Por que você não apenas os passa para sua inscrição?

location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ {
    try_files $uri @rewriteapp;
    #...everything else
    
por 03.06.2015 / 19:39