Избегайте nginx декодирования параметров запроса на прокси-пропуске (эквивалентно AllowEncodedSlashes NoDecode)

Я использую nginx в качестве balencer нагрузки в передней части несколько котищ. В моих входящих запросах я закодировал параметры запроса. Но когда запрос поступает в Tomcat, параметры декодирования :

входящий запрос на nginx:

curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http%3A%2F%2Fwww.google.com%2F"

входящий запрос к tomcat:

curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http:/www.google.com/"

Я не хочу, чтобы мои параметры запроса были преобразованы, потому что в этом случае мой tomcat выдает ошибку 405.

моя конфигурация nginx следующая :

upstream tracking  {
    server front-01.server.com:8080;
    server front-02.server.com:8080;
    server front-03.server.com:8080;
    server front-04.server.com:8080;
}

server {
    listen 80;
    server_name tracking.server.com;
    access_log /var/log/nginx/tracking-access.log;
    error_log  /var/log/nginx/tracking-error.log;

    location / {
        proxy_pass  http://tracking/webapp;
    }
}

в моей текущей конфигурации балансировщика нагрузки apache у меня есть AllowEncodedSlashes директива, которая сохраняет мои закодированные параметры:

AllowEncodedSlashes NoDecode

мне нужно перейти от apache к nginx.

мой вопрос совершенно противоположен этому вопросу:избегайте nginx экранирования параметров запроса на proxy_pass

5 ответов


Я, наконец, нашел решение: мне нужно передать $request_uri параметр :

location / {
    proxy_pass  http://tracking/webapp$request_uri;
}

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


Жан это хорошо, но это не работает с подстановками. В этом случае более общий ответ:

location /path/ {
  if ($request_uri ~* "/path/(.*)") {
    proxy_pass http://tracking/webapp/;
  }
}

существует один документированный вариант для директива proxy_pass nginx в директива

Если необходимо передать URI в необработанной форме, то следует использовать директиву proxy_pass без URI:

location  /some/path/ {
  proxy_pass   http://127.0.0.1;
}

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

location / {
    proxy_pass  http://tracking;
}

надеюсь, что это помогает.


обратите внимание, что декодирование URL, широко известный как $uri "нормализации" в документации nginx, происходит до бэкэнда IFF:

  • либо любой URI указан в proxy_pass сам, даже если только косая черта сама по себе,

  • или URI изменяется во время обработки, например, через rewrite.


оба условия явно документировано вhttp://nginx.org/r/proxy_pass (Курсив мой):

  • если это без URI, URI запроса передается на сервер в та же форма, что и отправлена клиентом при обработке исходного запроса или полное нормированный запрос URI передается , когда обработка изменен URI


решение зависит от того, нужно ли изменять URL-адрес между интерфейсом и бэкэндом.

  • если изменение URI не требуется:

    # map `/foo` to `/foo`:
    location /foo {
        proxy_pass  http://localhost:8080;  # no URI -- not even just a slash
    }
    
  • в противном случае, если вам нужно поменять местами или map /api передней части с /app на бэкэнде, то вы можете получить оригинальный URI из $request_uri переменная и использование rewrite директивы по $uri переменная, похожая на DFA (кстати, если вы хотите больше rewrite Действие DFA, взгляните наmdoc.su). Обратите внимание, что return 400 часть необходима в случае, если кто-то пытается обойти ваше второе правило перезаписи, так как он не соответствует что-то вроде //api/.

    # map `/api` to `/app`:
    location /foo {
        rewrite  ^  $request_uri;            # get original URI
        rewrite  ^/api(/.*)  /app  break;  # drop /api, put /app
        return 400;   # if the second rewrite won't match
        proxy_pass    http://localhost:8080$uri;
    }
    
  • если вы просто хотите добавить префикс для серверной, то вы можете просто использовать $request_uri переменной сразу:

    # add `/webapp` to the backend:
    location / {
        proxy_pass    http://localhost:8080/webapp$request_uri;
    }
    

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


в некоторых случаях проблема не на стороне nginx - вы должны установить кодировку uri на Tomcat connector в UTF-8.