Daylogs/Nginx

nginx: SSI 구문에서 중첩 if문 구현하기

ohgyun 2016. 6. 14. 11:28
발생일: 2016.07.14

키워드: nginx, ssi, 중첩 if 문, multiple condition, server side include

문제:
nginx 의 SSI에서 중첩으로 if 구문을 넣으려고 한다.

아래처럼 넣어봤는데 잘 되지 않는다.

<!--# if expr="$name = foo" -->
    <!--# if expr="$address = bar" -->
        ...
    <!--# endif -->
<!-- # endif -->


이상하다. 아래처럼 && 연산자로 추가해봤는데도 잘 되지 않는다.

<!--#if expr="$name = foo && $address = bar" -->
    ...
<!-- #endif -->


여러 방법으로 테스트해봤는데,
어떤 경우엔 [an error occurred while processing the directive] 와 같이 구문 오류라고 나오고,
어떤 경우엔 바깐 if 문을 타는 등 의도치 않게 동작한다.

왜 그럴까?


해결책:

nginx SSI 모듈 API에 따르면 if 구문은 1뎁스만 가능하다고 한다.

> Only one level of nesting is currently supported. The command has the following parameter:


좀 지저분하긴 하지만, 변수에 두 조건의 값을 할당해 비교하는 방식으로 우회할 수 있다.

<!--# set var="name_and_address" value="${name}_${address}" -->

<!--# if expr="$name_and_address = foo_bar" -->
    ...
<!--# endif -->




논의:

- 어떤 튜토리얼에서는 SSI에 중첩 if 문이나 &&, || 연산자를 사용할 수 있다고 하지만, 이 튜토리얼은 Apache 의 SSI 설명이다.
nginx 에서는 제공하지 않는 것에 주의한다.

- 필요한 경우, 아래와 같이 정규식을 사용하면 좀 더 유연하게 처리할 수 있다.
  <!--# if expr="$name_and_address = /.+_.+/" -->

- 테스트했던 버전은 nginx 1.4 버전이었는데, 중첩으로 정의하는 경우 구문 오류 대신 암묵적으로 다음 조건으로 넘어가는 이슈가 있었다.

  아래 테스트에서 (A)에 매칭되지 않은 경우 종료되어야 하지만 (B)가 실행됨
  <!--# if expr="$name = foo" -->
      <!--# if expr="$address = bar" --> (A)
          ...
      <!--# endif -->
  <!--# else -->
    ... (B)
  <!-- # endif -->

- 어이없이 시간을 까먹었던 건, var 디렉티브에서 선언한 변수를 $ 없이 사용한 것 때문이었다.

  <!-- set var="name_and_address" value="${name}_${address}" -->
  <!--# if expr="name_and_address = foo_bar" --> // $name_and_adress 로 작성했어야 함

- nginx 의 location 블럭 내 if 디렉티브도 동작 방식은 동일하다.
  조건에 따라 변수를 할당하고 최종적으로 만들어진 변수의 값을 비교하는 방법으로 우회할 수 있다.


참고:














반응형