티스토리 뷰

발생일: 2014.12.17

키워드: nginx rewrite flags, last, break

문제:
nginx 의 rewrite 디렉티브에는 4가지 플래그(last, break, redirect, permanent)가 있는데, 그 중 last 와 break 는 자꾸 봐도 헷갈린다.
나중에 봐도 헷갈리지 않게 자세히 정리했다.


해결책:

API 문서에 있는 정의는 다음과 같다. (http://wiki.nginx.org/HttpRewriteModule)

Flags can be any of the following:

last - completes processing of current rewrite directives and restarts the process (including rewriting) with a search for a match on the URI from all available locations.
break - completes processing of current rewrite directives and non-rewrite processing continues within the current location block only.
redirect - returns temporary redirect with code 302; it is used if the substituting line begins with http://
permanent - returns permanent redirect with code 301



이 중에 last 와 break 플래그의 정의를 좀 더 쉽게 (우리말로) 바꿔보면 아래와 같다.

last: rewrite 직후에 현재 블럭의 프로세싱을 종료하고 다음 URI 매칭을 찾아 진행한다.
break: rewrite 이후 현재 블럭을 마지막으로 프로세싱을 종료한다. 단, 현재 블럭 내에서 rewrite 가 아닌 작업까진 진행한다.


두 플래그의 동작 방식은 특히 헷갈려서, 쉽게 이해할 수 있는 예제를 만들었다.
(라인을 쉽게 설명하기 위해 A0, A1, … 과 같이 붙여놓았다)


A0   location /a {
A1     rewrite ^ /b;
A2     rewrite ^ /c;
A3     add_header x-a a;
A4     proxy_set_header foo foo;
A5     proxy_pass http://localhost:3000;
A6   }

B0   location /b { # B
B1     add_header x-b b;
B2     proxy_pass http://localhost:3000;
B3   }

C0   location /c { # C
C1     rewrite ^ /d;
C2     add_header x-c c;
C3     proxy_pass http://localhost:3000;
C4   }

D0   location /d { # D
D1     add_header x-d d;
D2     proxy_pass http://localhost:3000;
D3   }


nginx 룰이 위와 같은 때, `/a`로 요청을 할 경우 다음과 같은 순서로 룰이 적용된다.

`/a` 요청 시:
A0 -> A1 -> A2 -> C0 -> C1 -> D0 -> D1 -> D2

기본적으로 블럭 내에 rewrite 룰이 있으면, rewrite 을 수행한 후 해당 블럭의 프로세싱을 종료하고 변경된 URI 룰을 찾아 이동한다.


A0   location /a {
A1     rewrite ^ /b last;
A2     rewrite ^ /c;
A3     add_header x-a a;
A4     proxy_set_header foo foo;
A5     proxy_pass http://localhost:3000;
A6   }

위와 같이 `last` 플래그를 사용하면, 다음과 같이 `last` 플래그를 마지막으로 rewrite 를 종료한다.

`/a` 요청 시:
A0 -> A1 -> B0 -> B1 -> B2



A0   location /a {
A1     rewrite ^ /b break;
A2     rewrite ^ /c;
A3     add_header x-a a;
A4     proxy_set_header foo foo;
A5     proxy_pass http://localhost:3000;
A6   }

`break` 플래그를 사용하면, 현재 블럭 내에서의 rewrite 작업을 break 플래그가 있는 디렉티브에서 종료하고,
현재 블럭 내의 rewrite 가 아닌 다른 작업을 진행하고 프로세싱을 종료한다.

`/a/` 요청 시:
A0 -> A1 -> A3 -> A4 -> A5




이렇게 정리해두니 또 간단하네… -_-
여튼, 이제 헷갈리지 말자. ㅎㅎ


반응형
댓글
공지사항