nginx proxy_pass로 경로를 제거하는 방법


77

에 실행중인 웹 http://example.com/응용 프로그램이 있고의 다른 서버에 다른 응용 프로그램을 "마운트"하려고합니다 http://example.com/en. 업스트림 서버 proxy_pass에서 작동하는 것처럼 보이지만 한 가지 문제가 있습니다.

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location /en {
    proxy_pass http://luscious;
  }
}

열면 example.com/en업스트림 응용 프로그램이 반환 404 not found /en됩니다. 업스트림에 경로가 없기 때문에 이치에 맞습니다 /en.

proxy_path올바른 해결책은? /en루트 경로로 대신 수신하도록 "업스트림"을 다시 작성해야합니까 ? 아니면 상류로 전달 된 경로를 다시 쓸 수있는 지시문이 있습니까?

답변:


133

이것은 정규 표현식을 사용하지 않고 원하는 것을 수행하는 가장 효율적인 방법 일 것입니다.

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}

1
내가 아는 한, 마지막 부분은 여전히 ​​프록시에 대한 경로로 "/ en"을 전달하지 않습니까?
berkes

15
@berkes, 아니, 그렇지 않을 것입니다-후행 슬래시 proxy_pass가 차이를 만드는 것입니다. 또한이 답변은에 proxy_redirect머무르는 것을 보장하기 때문에 생각 해낸 답변보다 더 정확합니다 default. 따라서 302백엔드 내에서 et al을 계속 사용할 수 있으며 모든 곳에서 올바르게 작동 할 수 있습니다.
cnst December

4
아, 나는 슬래시를 놓치고 있었다 :(
Vanuan

3
으악! 훈련 슬래시!
barrymac

4
3 시간 동안의 검색과 네 .. 마지막 슬래시였습니다. 고마워 친구!
Lucas P.

12

인기가 높아지고있는 새로운 정규식 기반 답변을 해결하고 싶습니다.

location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$2$is_args$args;  # OOPS!
}

솔루션이 언뜻보기에는 더 귀엽게 보일 수 있지만 여러 가지 이유로 잘못되었습니다.

  • 위의 정규 표현식은의 요청과 일치 /enjoy하여 /joy업스트림으로 리디렉션합니다 . 이것이 실제로 의도 된 것입니까?

  • 에 대한 요청은 /en리디렉션을 일으키지 않고 /업스트림에서 직접 서비스를 제공합니다 (거의 요청 /en/이 이루어진 것처럼 보이지는 않지만). 루트 페이지 업스트림에서 상대 URI를 사용하는 경우 (그렇지 않으면 /en/업스트림 URI 내에 접두사 가없는 이유는 무엇입니까?) (예 : src="style.css"언어 별 참조 url("menu.png")) 브라우저에서 요청합니다. 로 /style.css대신 /en/style.css. (또는 어디에서나 절대 URI를 사용하더라도 누군가가 모호한 반 선택적 리소스를 상대적으로 참조하면 어떻게 되나요?) 죄송합니다.

  • 내 당으로 이미 OP 자신의 대답으로 언급 한 또 다른 질문에서 이전 조언 정규 표현식을 사용하여 방지 proxy_redirect의 기본 값을 갖는로부터 지시를 default그것을 거절, off대신. 즉 Location: http://127.0.0.1:8080/en/dir/, 요청 이 있을 때 업스트림이 응답 /en/dir하면 클라이언트가 보게 될 것입니다. 이는 제대로 작동하지 않습니다. ( /en처음에 정규 표현식을 사용하도록 요청 하는 요청에 대해 특히 아이러니했을 것입니다. 그러나이 특정 구현은 위에서 이미 언급 한 것처럼 다른 문제가 발생합니다.) 또한 이미upstream지시어를 선택하면 사용자 지정 서버를 사용하려고 시도 할 때, 특히 둘 이상의 업스트림 서버가있는 경우 더욱 추악해질 수 있습니다. proxy_redirect각 서버 마다 별도의 서버가 있습니까? 에서 정규 표현식을 사용 proxy_redirect하여 호스트와 일치시킬 수도 있지만 앞으로 도메인 간 리디렉션을 제공하기로 결정한 경우 어떻게해야합니까?

단일 정규 표현식 기반 위치로 위의 포인트 중 일부를 해결하려고 시도하면 다음을 수행 할 수 있습니다 ( 더 간단 하게하기 위해 기반 지시문 proxy_pass에서 서버에 대한 참조를 삭제해야 함 ).upstreamproxy_redirect

location ~ ^/en/?((?<=/).*)?$ {
  location = /en { return 302 /en/; }
  proxy_pass http://127.0.0.1:8080/$1$is_args$args;
  proxy_redirect http://127.0.0.1:8080/ /en/;
}

따라서, 나에게 묻는다면, 두 형제 최상위 위치를 가진 독창적 인 솔루션은 대신 정규식 경로를 통해 토끼 구멍에 파는 것보다 더 나은 아이디어입니다.


예외 :nginx: [emerg] location "/en" is outside location "^/en/?((?<=/).*
Athlan

1
@Athlan, 그것은 당신이 처음에 그것을 사용해서는 안되기 때문입니다! 그래도 원하는 경우 해당 위치를 정규 표현식 외부에 둘 수 있습니다.
cnst

현지화 퍼팅 = / en 외부 작동 정말 훌륭합니다! 감사합니다
Sebastian Webber

7

그래서 stackoverflow에 대한 답변을 찾았습니다 .

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location ~ ^/en(/?)(.*) {
    proxy_pass http://luscious/$2;
  }
}

기본적으로 정규식을 위치에 전달하고 역 참조를 proxy_pass url에 전달합니다.


"proxy_pass luscious / $ ;" 라고 생각합니다 "proxy_pass luscious / $ 2 " 여야합니다
Zafer

1
@Zafer가 맞습니다. 위의 답변으로 오류가 발생했습니다.
franck

답변을 변경했지만 ATM을 사용할 수있는 서버가 없으므로 확인되지 않았습니다.
berkes

0

Nginx 문서에 대한 회계

HTTP 프록시 서버에 요청을 전달하기 위해 proxy_pass 지시문이 위치 내에 지정됩니다. 예를 들면 다음과 같습니다.

location /some/path/ {
    proxy_pass http://www.example.com/link/;
}

이 예제 구성은이 위치에서 처리 된 모든 요청을 지정된 주소의 프록시 서버로 전달합니다. 이 주소는 도메인 이름 또는 IP 주소로 지정할 수 있습니다. 주소에는 포트가 포함될 수도 있습니다.

location ~ \.php {
    proxy_pass http://127.0.0.1:8000;
}

위의 첫 번째 예에서 프록시 서버의 주소 다음에는 URI / link /가옵니다. URI가 주소와 함께 지정되면 위치 매개 변수와 일치하는 요청 URI 부분을 대체합니다. 예를 들어, 여기서 /some/path/page.html URI가있는 요청은 http://www.example.com/link/page.html 로 프록시됩니다 . URI없이 주소를 지정하거나 교체 할 URI 부분을 결정할 수없는 경우 전체 요청 URI가 전달됩니다 (아마도 수정).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.