nginx 프록시에서 URL 디코딩 비활성화


21

이 URL을 탐색하면 http://localhost:8080/foo/%5B-%5Dserver ( nc -l 8080)는 그대로 수신합니다.

GET /foo/%5B-%5D HTTP/1.1

그러나 nginx (1.1.19)를 통해이 응용 프로그램을 프록시 할 때 :

location /foo {
        proxy_pass    http://localhost:8080/foo;
}

nginx 포트를 통해 라우팅 된 동일한 요청이 경로 디코딩 된 상태로 전달됩니다.

GET /foo/[-] HTTP/1.1

GET 경로의 디코드 된 대괄호는 이스케이프되지 않은 도착시 대상 서버 ( HTTP 상태 400-경로의 잘못된 문자 ... ) 에서 오류를 발생시킵니다 .

URL 디코딩을 비활성화하거나 다시 인코딩하여 대상 서버가 nginx를 통해 라우팅 될 때 정확히 동일한 경로를 얻도록하는 방법이 있습니까? 영리한 URL 다시 쓰기 규칙?


보고 된 버그의 nginx에 : trac.nginx.org/nginx/ticket/262
토마스 Nurkiewicz

답변:


19

Valentin V. Bartenev 인용 (이 답변에 대한 전체 크레딧을 받아야하는 사람) :

문서 에서 인용 :

  • proxy_pass 를 URI 로 지정 하면 요청을 서버에 전달할 때 위치와 일치 하는 정규화 된 요청 URI의 일부가 지시문에 지정된 URI로 바뀝니다.

  • 경우에 proxy_pass지정된 URI 않고 원래의 요청을 처리 할 때, 클라이언트에 의해 전송 된 바와 같이, 요청 URI는 동일한 형태로 서버에 전달

귀하의 경우 올바른 구성은 다음과 같습니다.

location /foo {
   proxy_pass http://localhost:8080;
}

8
다른 사람과 같은 상황에 처한 경우에 대비 하여 변경 http://localhost:8080/해야 http://localhost:8080했습니다.
herrtim

4
Nginx가 URI를 백엔드 서버로 전달하기 전에 URI를 디코딩하는 이유는 무엇입니까? URI를 그대로 유지하면 더 이해가되지 않습니까?
오리너구리

@platypus, 명시 적으로 대체 수행을 시작할 때까지 그대로 유지됩니다
cnst

2

nginx 문서에서 일반적으로 $uri"정규화" 라고 알려진 URL 디코딩 은 백엔드 IFF 전에 발생합니다.

  • proxy_pass후행 슬래시만으로도 모든 URI가 자체적 으로 지정 됩니다.

  • 또는, 처리 동안, 예를 들어를 통해 URI가 변경된다 rewrite.


두 조건은 http://nginx.org/r/proxy_pass (강조 광산)에 명시 적으로 문서화되어 있습니다 .

  • 는 IF proxy_pass지시자가 지정된 URI를 가진 후, 요청을 서버에 전달 될 때, 부분 정규화 URI가 위치 일치 요구가 URI로 대체 지시어에 지정된

  • 경우에 proxy_pass지정된 URI에없는 요청은 URI에서 서버로 전달되고 , 클라이언트에 의해 전송 된 바와 같이 동일한 형태의 원래의 요청을 처리 할 때, 또는 전체 정규화 요청 URI가 전달되는 경우 가공하는 변경 URI를


해결책은 OP의 경우와 같이 URI를 생략하거나 실제로 영리한 rewrite규칙을 사용하는 것입니다.

# map `/foo` to `/foo`:
location /foo {
    proxy_pass  http://localhost:8080;  # no URI -- not even just a slash
}

# map `/foo` to `/bar`:
location /foo {
    rewrite  ^  $request_uri;            # get original URI
    rewrite  ^/foo(/.*)  /bar$1  break;  # drop /foo, put /bar
    return 400;   # if the second rewrite won't match
    proxy_pass    http://localhost:8080$uri;
}

컨트롤 그룹을 포함하여 관련 스택 오버플로 응답에서 실시간으로 볼 수 있습니다 .


여기에 문서가 혼동됩니다. 두 양식 모두 URI를 포함합니다. 그것은 인 경로 성분 은 다른 하나에 존재하는 누락된다.
Michael Hampton

@MichaelHampton은 동의하지 않습니다. PATH는 일반적으로 URI라고하므로 경로가없는 경로는 URI를 포함하지 않습니다.
cnst

물론 상대 경로만으로도 유효한 URL이 될 수 있습니다. 요점은 나머지는 유효한 URI (예 :) http://localhost:8080입니다. 당신이 동의하지 않으면, 당신은 RFC 3986의 저자와 함께 그것을 취할 수 있습니다.
Michael Hampton

@MichaelHampton 불행히도, 계획과 경로는 URI, 권한, 인수, 프래그먼트가 필수 인 것 같습니다
Norman Xu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.