Подтвердить что ты не робот

Nginx add_header не работает

У меня есть интригующая проблема, когда всякий раз, когда я использую add_header в моей конфигурации виртуального хоста на сервере ubuntu, использующем nginx с PHP и php-fpm, он просто не работает, и я понятия не имею, что я делаю неправильно. Вот мой файл конфигурации:

server {
    listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80 default ipv6only=on; ## listen for ipv6

    root /var/www/example.com/webroot/;
    index index.html index.htm index.php;

    # Make site accessible from http://www.example.com/
    server_name www.example.com;

    # max request size
    client_max_body_size 20m;

    # enable gzip compression
    gzip             on;
    gzip_static      on;
    gzip_min_length  1000;
    gzip_proxied     expired no-cache no-store private auth;
    gzip_types       text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
    add_header PS 1

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to index.html
            try_files $uri $uri/ /index.php?$query_string;
            # Uncomment to enable naxsi on this location
            # include /etc/nginx/naxsi.rules
    }


    location ~* \.(css|js|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|$
            # 1 year -> 31536000
            expires 500s;
            access_log off;
            log_not_found off;
            add_header Pragma public;
            add_header Cache-Control "max-age=31536000, public";
    }
    # pass the PHP скриптs to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

            # With php5-cgi alone:
            #fastcgi_pass 127.0.0.1:9000;
            # With php5-fpm:
            fastcgi_pass unix:/var/run/example.sock;
            fastcgi_index index.php?$query_string;
            include fastcgi_params;

            # instead I want to get the value from Origin request header
    }

    # Deny access to hidden files
    location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
    }

    error_page 403 /403/;
}

server {
    listen 80;
    server_name example.com;
    rewrite     ^ http://www.example.com$request_uri? permanent;
}

Я попытался добавить заголовки к другим разделам местоположения, но результат тот же.

Любая помощь приветствуется!!

4b9b3361

Ответ 1

Оказывается, что попытка обновления nginx к самой новой версии вызывала это. Я ранее пытался переустановить, который, похоже, правильно переустановил его, но на самом деле Ubuntu не удалял nginx должным образом. Поэтому мне пришлось только переустановить сервер Ubuntu и установить все заново, используя только стандартные репозитории ubuntu.

Ответ 2

У меня было две проблемы.

Во-первых, nginx обрабатывает только последний add_header, который указывает на дерево. Поэтому, если у вас есть add_header в контексте server, затем другой в вложенном контексте location, он обрабатывает только директиву add_header внутри контекста location. Только самый глубокий контекст.

Из документов NGINX на add_header:

Может существовать несколько директив add_header. Эти директивы наследуются от предыдущего уровня тогда и только тогда, когда нет указателей add_header, определенных на текущем уровне.

Вторая проблема заключалась в том, что блок location / {}, который у меня был на месте, фактически отправлял nginx в другой блок location ~* (\.php)$ (потому что он возвращал все запросы через index.php, и это фактически заставляет nginx обрабатывать этот блок php). Итак, мои директивы add_header внутри первой директивы местоположения были бесполезны, и он начал работать после того, как я поместил все директивы, которые мне нужны в директиве местоположения php.

Наконец, здесь моя рабочая конфигурация, позволяющая CORS в контексте MVC-инфраструктуры, называемой Laravel (вы можете легко ее изменить, чтобы она соответствовала любой фреймворку PHP, который имеет index.php как единую точку входа для всех запросов).

server {
    root /path/to/app/public;
    index index.php;

    server_name test.dev;

    # redirection to index.php
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # pass the PHP скриптs to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

        # With php5-fpm:
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;

        # cors configuration
        # whitelist of allowed domains, via a regular expression
        # if ($http_origin ~* (http://localhost(:[0-9]+)?)) {
        if ($http_origin ~* .*) { # yeah, for local development. tailor your regex as needed
             set $cors "true";
        }

        # apparently, the following three if statements create a flag for "compound conditions"
        if ($request_method = OPTIONS) {
            set $cors "${cors}options";
        }

        if ($request_method = GET) {
            set $cors "${cors}get";
        }

        if ($request_method = POST) {
            set $cors "${cors}post";
        }

        # now process the flag
        if ($cors = 'trueget') {
            add_header 'Access-Control-Allow-Origin' "$http_origin";
            add_header 'Access-Control-Allow-Credentials' 'true';
        }

        if ($cors = 'truepost') {
            add_header 'Access-Control-Allow-Origin' "$http_origin";
            add_header 'Access-Control-Allow-Credentials' 'true';
        }

        if ($cors = 'trueoptions') {
            add_header 'Access-Control-Allow-Origin' "$http_origin";
            add_header 'Access-Control-Allow-Credentials' 'true';

            add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since';

            add_header 'Content-Length' 0;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            return 204;
        }
    }

    error_log /var/log/nginx/test.dev.error.log;
    access_log /var/log/nginx/test.dev.access.log;
}

Суть выше: https://gist.github.com/adityamenon/6753574

Ответ 3

Когда я тестирую приведенные выше настройки add_header с помощью:

# nginx -t && service nginx reload

Я получаю

nginx: [emerg] directive "add_header" is not terminated by ";" in
/etc/nginx/enabled-sites/example.com.conf:21

nginx: configuration file /etc/nginx/nginx.conf test failed

Таким образом, жалоба повторяет эту строку:

add_header PS 1

отсутствует точка с запятой (;)

Чтобы проверить заголовки, мне нравится использовать

# curl -I http://example.com

В соответствии с руководством ngx_http_headers_module

syntax: add_header name value;
default:     —
context:    http, server, location, if in location

Я еще пробовал

add_header X-test-A 1;
add_header "X-test-B" "2";
add_header 'X-test-C' '3';

в контексте http, server и location, но он появился только в контексте server.

Ответ 4

У меня возникла проблема не получить заголовок ответа из-за кода ответа не в пределах допустимого диапазона, если вы не укажете ключевое слово "всегда" после значения заголовка.

Из официальных документов:

Добавляет указанное поле в заголовок ответа при условии, что код ответа равен 200, 201, 204, 206, 301, 302, 303, 304, 307 или 308. Значение может содержать переменные.

Ответ 5

Во-первых, позвольте мне сказать, что, оглянувшись по Сети, я нашел этот ответ повсюду:

location ~* \.(eot|ttf|woff|woff2)$ { add_header Access-Control-Allow-Origin *; }

Тем не менее, я решил ответить на этот вопрос отдельным ответом, так как мне удалось получить это конкретное решение, работая после того, как заработало еще десять часов, чтобы найти решение.

Похоже, что Nginx по умолчанию не определяет никаких [правильных] шрифтов MIME. Следуя этот tuorial, я обнаружил, что могу добавить следующее:

application/x-font-ttf ttc ttf; application/x-font-otf otf; application/font-woff woff; application/font-woff2 woff2; application/vnd.ms-fontobject eot;

В мой etc/nginx/mime.types файл. Как было указано, вышеупомянутое решение затем работало. Очевидно, что этот ответ направлен на совместное использование шрифтов, но стоит отметить, что типы MIME не могут быть определены в Nginx.

Ответ 6

Что говорит ваш журнал ошибок nginx?

Знаете ли вы, какие строки add_header нарушают конфигурацию? Если нет, прокомментируйте их все, а затем включите их 1 на 1, перезагрузите nginx, чтобы увидеть, какая из них является/является проблемой. Я бы начал с комментариев блока:

add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header PS 1

Проблема может заключаться в том, что вы устанавливаете заголовки, не поддерживаемые основным модулем httpHeaders. Может оказаться полезным установка NginxHttpHeadersMoreModule.

Кроме того, попробуйте заменить две строки add_header int location ~* \... на следующее:

add_header Pragma '';
add_header Cache-Control 'public, max-age=31536000'

Есть ли причина, по которой у вас есть конфигурация gzip, а не в вашем глобальном nginx.conf?

Ответ 7

Очевидно, что quirk/getcha наследования add_header применяется также к восходящему слою.

У меня были предварительные авторизационные запросы script, предназначенные для другой службы, и поэтому возвращали все заголовки из другой службы.

Как только я начал добавлять запись "Access-Control-Allow-Origin" вместе с этими ретранслируемыми заголовками, браузер фактически получит запись и разрешит запрос.