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

Управление прокси-сервером Nginx с помощью файла cookie?

Я пытаюсь преобразовать обратный прокси-сервер, используя интересную настройку Apache mod_rewrite, чтобы вместо этого использовать Nginx (из-за внешних проблем мы переходим с Apache на Nginx, и почти все работает нормально, кроме этой части).

Моя первоначальная установка заключалась в том, чтобы читать HTTP-файл cookie (установленный каким-либо приложением) и, в зависимости от его значения, направлять обратный прокси-сервер на разные серверы. Это было примерно так:

RewriteCond %{HTTP_COOKIE}  proxy-target-A
RewriteRule ^/original-request/ http://backend-a/some-application [P,QSA]

RewriteCond %{HTTP_COOKIE}  proxy-target-B
RewriteRule ^/original-request http://backend-b/another-application [P,QSA]

RewriteRule ^/original-request http://primary-backend/original-application [P,QSA]

Я пытаюсь добиться того же с помощью Nginx, и моя первоначальная конфигурация была примерно такой (где proxy_override - это имя файла cookie):

location /original-request {
    if ($cookie_proxy_override = "proxy-target-A") {
        rewrite . http://backend-a/some-application;
        break;
    }
    if ($cookie_proxy_override = "proxy-target-B") {
        rewrite . http://backend-b/another-application;
        break;
    }
    proxy_pass http://primary-backend/original-application;
}

Но этого не произошло. Я попытался проверить, может ли Nginx прочитать мой файл cookie, написав основной прокси-сервер для перенаправления на что-то на основе ${cookie_proxy_override} и я вижу, что он нормально читает содержание, но ifкажется, всегда терпят неудачу.

Моя следующая попытка, согласно ответу Рики, была такой:

location /original-request {
    if ($http_cookie ~ "proxy-target-A") {
        rewrite . http://backend-a/some-application;
        break;
    }
    if ($http_cookie ~ "proxy-target-B") {
        rewrite . http://backend-b/another-application;
        break;
    }
    proxy_pass http://primary-backend/original-application;
}

И теперь я вижу, что if блок активируется, но вместо проксирования запроса (как я и думал) он возвращает перенаправление 302 на указанный URL-адрес - это не то, что я пытаюсь сделать: мне нужен сервер, чтобы прозрачно передать запрос на backends и направьте ответ исходному клиенту.

Что я делаю не так?

Похожий на этот ответ. Идиоматический подход Nginx к подобным проблемам заключается в следующем: map.

По сути, вы определяете map в http раздел

map $cookie_proxy_override $my_upstream {
  default default-server-or-upstream;
  ~^(?P<name>[\w-]+) $name;
}

Тогда вы просто используете $my_upstream в location раздел (ы):

location /original-request {
  proxy_pass http://$my_upstream$uri;
}

Nginx вычисляет переменные карты лениво, только один раз (на запрос) и когда вы их используете.

В конечном итоге мое решение сводится к следующему:

server {
    ...
    set $upstream "default-server-or-upstream";
    if ($http_cookie ~ "proxy_override=([\w-]+)") {
        set $upstream $1;                                   
    }

    location /original-request {
        proxy_pass http://$upstream/original-application
    }
}

Тест проводится в server область для каждого запроса (до разрешения фактического перенаправления) и используется только для установки переменной - очевидно, это поддерживаемое использование модуля «перезаписи» Nginx. Он также проверяет все $http_cookie как предложил @Rikih, но включает имя файла cookie, чтобы убедиться, что я не сопоставляю случайные вещи, которые люди могут мне бросать.

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

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

   location / {
      proxy_set_header Host $http_host;
  if ($request_uri ~ ^/(.*)udid=xxxxxxxxxxxxxx(.*)$) {
    proxy_pass   http://1.1.1.1$request_uri;
    break;
  }
  if ($request_uri ~ ^/(.*)udid=yyyyyyyyyyyyyy(.*)$) {
    proxy_pass   http://3.3.3.3$request_uri;
    break;
  }
       proxy_pass http://2.2.2.2$request_uri;
    }

вы пробовали $ http_cookie? http://wiki.nginx.org/HttpRewriteModule

если ($ http_cookie ~ * "прокси-цель-A") {foo; }