Назад | Перейти на главную страницу

nginx http redirect ошибочно удваивает параметры (через AWS ELB)

Например, когда я просматриваю

http://example.com/foo?x=1&y=2

nginx перенаправляет меня на

https://example.com/foo?x=1&y=2?x=1&y=2

Теперь, если я продолжу перенаправлять, я получаю

https://example.com/foo?x=1&y=2?x=1&y=2?x=1&y=2?x=1&y=2

Он постоянно удваивает параметры, не уверен, что я сделал не так.

Моя конфигурация nginx:

server {
  listen 80;
  listen 443 ssl;

  server_name {{ .SERVER_NAME }} www.{{ .SERVER_NAME }};

  ssl_certificate     /etc/ssl/nginx.crt;
  ssl_certificate_key /etc/ssl/nginx.key;

  if ($http_x_forwarded_proto != "https") {
      rewrite ^(.*)$ https://$server_name$REQUEST_URI permanent;
  }

  # Nginx will reject anything not matching /
  location / {
    # Reject requests with unsupported HTTP method
    if ($request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE|PATCH)$) {
      return 405;
    }

    # Only requests matching the whitelist expectations will
    # get sent to the application server
    proxy_pass http://site_container:5000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_redirect     off;
    proxy_set_header   Host                 $http_host;
    proxy_set_header   X-Real-IP            $remote_addr;
    proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto    $http_x_forwarded_proto;
    proxy_set_header   X-Forwarded-Port     $http_x_forwarded_port;
    proxy_cache_bypass $http_upgrade;
  }
}

Это архитектура ECS с контейнерами nginx и приложений в одном экземпляре EC2.

В rewrite Директива добавляет строку запроса к замещающему URL-адресу по умолчанию, аналогично Apache [QSA]. Из документация:

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

rewrite ^/users/(.*)$ /show?user=$1? last;

Но это не как решить проблему.

Есть еще одна проблема, заключающаяся в том, что перенаправление с http на https неэффективно. это if должен быть оценен на каждый запрос, а rewrite имеет бесплатное регулярное выражение. Видеть Налогообложение переписчиков Чтобы получить больше информации.

Вместо этого у вас должен быть полностью отдельный server блокировать для HTTP по сравнению с HTTPS и удалить if/rewrite с HTTPS server заблокировать полностью.

server {
  listen 80;
  listen [::]:80; # You also forgot this...

  server_name {{ .SERVER_NAME }} www.{{ .SERVER_NAME }};

  return 301 https://{{ .SERVER_NAME }}$request_uri;
}