http

클라이언트/원본과 진행하는 HTTP 트랜잭션을 설정한다. /usr/local/m2/setting.json 다음 영역에 대해 기술한다.

{
  "functions": {
    "network": {
      "http": {
        ...
      }
    }
  }
}

frontEnd

HTTP 클라이언트 세션과 요청을 처리하는 방식에 대해 설명한다.

{
  "functions": {
    "network": {
      "http": {
        "frontEnd": {
          ...
        }
      }
    }
  }
}

session

클라이언트 세션과 아무런 통신이 없는 상태로 설정된 시간이 경과하면 세션을 종료한다. 시간을 너무 길게 설정하면 통신을 하지 않는 세션이 지나치게 많아진다. 너무 많은 세션을 유지하는 것만으로도 시스템엔 부하가 된다.

"session": {
  "keepAliveSec": 10
}
keepAliveSec (기본: 10초)

HTTP 통신이 없는 상태로 세션을 유지하는 시간(초)

headers

{
  "functions": {
    "network": {
      "http": {
        "frontEnd": {
          "headers": {
            ...
          }
        }
      }
    }
  }
}

via

클라이언트에게 보내는 HTTP응답에 Via 헤더 명시여부를 설정한다.

"via": {
  "enable": true
}
enable (기본: true)

Via 헤더를 M2Live/{version} 로 명시한다.

etag

클라이언트에게 보내는 HTTP응답에 ETag 헤더 명시여부를 설정한다.

"etag": {
  "enable": true
}
enable (기본: true)

ETag 헤더를 명시한다.

age

Age헤더는 캐싱된 순간부터 경과시간(초)을 의미하며 RFC2616 - 13.2.3 Age Calculations 에 의하여 계산된다.

"age": {
  "enable": false
}
enable (기본: false)

true 라면 Age헤더를 명시한다.

expires

Expires 헤더를 재설정한다. Expires조건은 Apache의 mod_expires 와 동일하게 동작한다. 특정 조건(URL이나 MIME Type)에 해당하는 콘텐츠의 Expires헤더와 Cache-Control 값을 설정할 수 있다. Cache-Control의 max-age값은 설정된 Expires시간에서 요청한 시간을 뺀 값이 된다.

"expires": {
  "enable": false,
  "base": "access",
  "matchingList": [
    {
      "pattern": "$URL[/test.jpg]",
      "time": "86400"
    },
    {
      "pattern": "$MIME[application/octet-stream]",
      "time": "#ORG_MAXAGE",
      "base": "modification"
    }
  ]
}

enable (기본: false)

  • false (기본) 원본서버에서 응답한 Expires헤더를 클라이언트에게 명시한다. 원본서버에서 Expires헤더가 생략되었다면 클라이언트 응답에도 Expires헤더가 생략된다.

  • true Expires조건을 반영하여 Expires헤더를 명시한다. 조건에 해당하지 않는 콘텐츠는 OFF 설정과 동일하게 동작한다.

base (기본: access)

Expires만료시간의 기준시점( access 또는 modification )을 설정한다.

  • access

    현재 시간을 기준으로 한다. 다음은 MIME Type이 image/gif인 파일에 대하여 접근시간으로부터 1일 12시간 후로 Expires헤더 조건을 설정하는 예제이다.

    {
      "pattern": "$MIME[image/gif]",
      "time": "1 day 12 hours",
      "base": "access"
    }
    
  • modification

    원본서버에서 보낸 Last-Modified를 기준으로 한다. 다음은 모든 jpg파일에 대하여 Last-Modified로부터 30분 뒤를 Expires값으로 설정하는 예제이다.

    {
      "pattern": "*.jpg",
      "time": "30min",
      "base": "modification"
    }
    

    modification 의 경우 계산된 Expires값이 현재시간보다 과거의 시간일 경우 현재시간을 명시한다. 만약 원본서버에서 Last-Modified헤더를 제공하지 않는다면 Expires헤더를 보내지 않는다.

matchingList

매칭리스트

pattern

URL과 MIME Type 2가지로 설정이 가능하다. URL일 경우 $URL[...] 로, MIME Type일 경우 $MIME[...] 으로 표기한다. 패턴표현이 가능하며 $표현이 생략된 경우 URL로 인식한다.

time (단위: 초)

Expires만료시간을 설정한다. 시간단위 표현을 지원하며 단위를 명시하지 않을 경우 초로 계산된다.

  • {number} - Expires만료시간

  • #ORG_MAXAGE - 원본서버가 응답한 Max-Age 값

  • #TTL_LEFT - 콘텐츠가 만료되는 시간

base

변경모드 - access , modification

Note

#ORG_MAXAGE 키워드를 통해 원본서버가 응답한 Max-Age 값을 Expire 시간으로 사용할 수 있다.

"expires": {
  "enable": true,
  "matchingList": [
    {
      "pattern": "/stat.jpg",
      "time": "#ORG_MAXAGE"
    },
    {
      "pattern": "/pds/*.dat",
      "time": "#ORG_MAXAGE",
      "base": "modification"
    },
    {
      "pattern": "$MIME[application/shockwave]",
      "time": "#ORG_MAXAGE"
    },
    {
      "pattern": "$MIME[application/octet-stream]",
      "time": "#ORG_MAXAGE",
      "base": "modification"
    },
    {
      "pattern": "$MIME[image/gif]",
      "time": "#ORG_MAXAGE",
      "base": "modification"
    }
  ]
}

#TTL_LEFT 키워드를 통해 콘텐츠가 만료되는 시간을 Expires 헤더의 값으로 명시한다. 기준 설정이 access 인 경우에만 동작한다.

{
  "pattern": "/*",
  "time": "#TTL_LEFT",
  "base": "access"
}

원본서버가 보낸 Max-Age 헤더가 없거나, 값이 0인 경우 Expire헤더를 붙이지 않는다.

server

클라이언트에게 보내는 HTTP응답에 Server 헤더 명시여부를 설정한다.

"server": {
  "enable": true
}
enable (기본: true)

원본서버의 Server헤더를 명시한다.

connection

클라이언트에게 보내는 HTTP응답의 Connection헤더( keep-alive 또는 close )를 설정한다.

"connection": {
  "directive": "keep-alive"
}
directive (기본: keep-alive)

keep-alive 또는 close

lastModified

클라이언트가 보내는 요청의 If-Modified-Since 헤더 처리정책을 설정한다.

"lastModified": {
  "rule": "orlater"
}

rule (기본: orlater)

  • orlater (기본) 요청 대상의 Last-Modified 시간보다 일치하거나 큰 경우 304 Not Modified 응답한다.

  • exact 요청 대상의 Last-Modified 시간과 일치하는 경우에만 304 Not Modified 로 응답한다.

cacheFreshness

캐싱된 콘텐츠에 대한 304 Not Modified 응답판단을 설정한다.

"cacheFreshness": {
  "rule": "both"
}

rule (기본: both)

  • both (기본) 클라이언트가 전송한 If-Modified-Since 또는 ETag 헤더 중 하나라도 같다면 동일 콘텐츠로 판단한다.

  • lmt 클라이언트가 전송한 If-Modified-Since 만으로 동일 콘텐츠로 판단한다.

  • etag 클라이언트가 전송한 ETag 만으로 동일 콘텐츠로 판단한다.

ifRange

클라이언트가 보내는 Range요청의 If-Range 헤더를 인식하여 처리한다.

Note

2 Tier구성이라면 Parent Layer에서 반드시 활성화해주어야 무결성이 보장된다.

"ifRange": {
  "enable": true,
  "purge": false
}

enable (기본: true)

  • true  (기본) If-Range헤더를 인식하여 Range 요청을 처리한다. 값이 유효하다면 206 Partial Content 로 응답한다. 아니라면 200 OK 로 응답한다.

  • false If-Range헤더를 무시한다.

purge (기본: false)

활성화되면 클라이언트가 보낸 Last-Modified 시간이 더 최근일 경우 캐싱된 컨텐츠를 Purge 한다.

keepAlive

클라이언트에게 보내는 HTTP응답의 Keep-Alive 헤더를 설정한다.

"keepAlive": {
  "enable": true,
  "max": 0
}

enable (기본: true)

  • true (기본) HTTP응답에 Keep-Alive헤더를 명시한다.

  • false HTTP응답에 Keep-Alive헤더를 생략한다.

max (기본: 0)

0보다 크게 설정하면 Keep-Alive 헤더의 값으로 max 값이 명시된다. 이후 HTTP 트랜잭션이 발생할때마다 1씩 차감된다.

modify

클라이언트 HTTP요청과 응답헤더를 특정 조건에 따라 변경한다.

"modify": {
  "enable": false,
  "matchFirstOnly": false,
  "defaultCaseSensitive": true,
  "matchingList": [
    {
      "pattern": "/*.mp4",
      "header": "$RES[Access-Control-Allow-Origin: example1.com]",
      "caseSensitive": false,
      "mode": "set"
    }
  ]
}
enable (기본: false)

헤더 수정 활성화

matchFirstOnly (기본: false)

최초 조건에만 변경을 원할 경우 속성을 true 로 설정한다. 서로 다른 조건이 같은 헤더를 변경하는 경우 set 에 의해 Last-Win이 된다. 또는 명시적으로 put , append 또는 rewrite 할 수 있다.

defaultCaseSensitive (기본: true)

  • true (기본) 헤더를 제외한 값의 대소문자를 구분한다. (헤더는 대소문자 미구분이 스펙이다.)

  • false 대소문자를 구분하지 않는다.

matchingList

매칭리스트

pattern

패턴은 다음 조건을 지원한다.

조건

표현

설명

IP

$IP[...]

클라이언트 IP, IP Range, Bitmask, Subnet 네 가지 형식을 지원한다.

GeoIP

$IP[...]

클라이언트 국가코드. 반드시 geoip 가 설정되어 있어야 한다. 국가코드는 ISO 3166-1 alpha-2ISO 3166-1 alpha-3 를 지원한다.

요청헤더

$HEADER[Key : Value]

클라이언트 요청헤더 패턴을 검사하며, Value는 명확한 표현과 패턴을 지원한다.

Value가 생략된 경우에는 Key에 해당하는 헤더의 존재유무를 조건으로 판단한다.

응답헤더

$RESHEADER[Key : Value]

클라이언트 응답헤더 패턴을 검사하며 그 외 동작은 요청헤더와 동일하다.

URL

$URL[...]

명확한 표현과 패턴을 인식한다.

URL 정규표현식

$URLMATCH[ ]

HTTP 요청 URL을 정규표현식으로 검사한다. 부정표현을 지원한다. ( $URL[...] 과 $URLMATCH[...] 차이 참조)

Method

$METHOD[...]

GET , POST , HEAD , OPTIONS 중 하나만 명시적으로 지정한다.

응답코드

$CODE[...]

클라이언트 응답코드. 200 , 404 등 구체적인 코드외에 2xx , 3xx , 4xx , 5xx 표현이 가능하다.

Warning

위 조건 중 응답헤더 $RESHEADER[...] 와 응답코드 $CODE[...] 표현은 응답헤더 변조 $RES[...] 설정에서만 사용 가능하다.

"matchingList": [
  {
    ...
    "pattern": "$URL[/*.mp4]",
    "header": "$RES[...]",
    ...
  }
]

개별 $ , 부정 ! , 결합 & 표현을 지원한다.

# 특정 IP만 지정한 경우
$IP[10.10.10.10]

# 국가코드 AP에 해당하며 referer헤더가 없는 경우
$IP[AP] & !HEADER[referer]

# POST메소드로 /api/* 경로에 접근한 경우
$METHOD[POST] & $URL[/api/*]

# cookie헤더에 login= 필드가 없는 경우
!HEADER[cookie: *login=*]

# referer, user-agent, host 헤더가 모두 없는 경우
!HEADER[referer] & !HEADER[user-agent] & !HEADER[host]

# /downloads/* 디렉토리 접근시 4xx응답이 발생한 경우
$URL[/downloads/*] & $CODE[4xx]
header

$REQ[...]$RES[...] 문법으로 헤더변경 방법을 설정한다. set put append set_if_not_exist 의 경우 {Key: Value} 로 설정하며, Value가 입력되지 않은 경우 "" 으로 간주한다. unset 의 경우 {Key} 만 입력한다.

caseSensitive

아이템의 대소문자 구분여부. 값이 없다면 defaultCaseSensitive (기본: true) 를 사용한다.

mode

설명

set

요청/응답 헤더에 설정되어 있는 Key와 Value를 헤더에 추가한다. 이미 같은 Key가 존재한다면 이전 값을 덮어쓴다.

set_if_not_exist

헤더가 존재하지 않는 경우에만 set 과 같이 동작한다.

put

( set 과 유사하나) 같은 Key가 존재하면, 덮어쓰지 않고 새로운 라인으로 붙여 넣는다.

append

( set 과 유사하나) 같은 Key가 존재하면, 기존의 Value와 설정된 Value사이에 콤마 , 로 구분하여 값을 결합한다.

unset

요청/응답 헤더에 설정되어 있는 Key에 해당하는 헤더를 삭제한다.

rewrite

정규표현식을 이용하여 헤더 값을 변경한다.

클라이언트가 보낸 헤더의 값은 $REQ.{헤더명} 로 참조한다. 이를 이용해 클라이언트가 보낸 헤더 값을 응답 헤더와 원본 요청 헤더에 명시할 수 있다.

"modify": {
  "enable": true,
  "matchFirstOnly": false,
  "matchingList": [
    {
      # 클라이언트가 보낸 요청의 Origin헤더 값을 응답의 Access-Control-Allow-Origin 헤더 값으로 설정한다.
      "pattern": "$URL[*.html]",
      "header": "$RES[Access-Control-Allow-Origin: $REQ.Origin]",
      "mode": "set"
    },
    {
      # 클라이언트가 보낸 요청의 여러 헤더 값을 응답의 X-Cookie 헤더 값으로 설정한다.
      "pattern": "$URL[*.json]",
      "header": "$RES[X-Cookie: $REQ.[User-Agent, Host]]",
      "mode": "set"
    }
  }
}

요청헤더 설정 예제는 다음과 같다.

"modify": {
  "enable": true,
  "matchFirstOnly": false,
  "matchingList": [
    {
      "pattern": "$IP[192.168.1.1]",
      "header": "$REQ[SOAPAction]",
      "mode": "unset"
    },
    {
      "pattern": "$IP[192.168.2.1-255]",
      "header": "$REQ[accept-encoding: gzip]",
      "mode": "set"
    },
    {
      "pattern": "$IP[192.168.3.0/24]",
      "header": "$REQ[cache-control: no-cache]",
      "mode": "append"
    },
    {
      "pattern": "$IP[192.168.4.0/255.255.255.0]",
      "header": "$REQ[x-custom-header]",
      "mode": "unset"
    },
    {
      "pattern": "$IP[AP]",
      "header": "$REQ[X-Forwarded-For]",
      "mode": "unset"
    },
    {
      "pattern": "$HEADER[user-agent: *IE6*]",
      "header": "$REQ[accept-encoding]",
      "mode": "unset"
    },
    {
      "pattern": "$HEADER[via]",
      "header": "$REQ[via]",
      "mode": "unset"
    },
    {
      "pattern": "$URL[/source/*.zip]",
      "header": "$REQ[accept-encoding: deflate]",
      "mode": "set"
    },
    {
      "pattern": "$METHOD[POST]",
      "header": "$REQ[host: sub.example.com]",
      "mode": "set"
    }
  ]
}

응답헤더 설정 예제는 다음과 같다. resCode 설정을 통해 특정 응답코드에 한하여 헤더를 변경할 수 있지만 필수는 아니다.

"modify": {
  "enable": true,
  "matchFirstOnly": false,
  "matchingList": [
    {
      "pattern": "$IP[192.168.1.1]",
      "header": "$RES[via: STON for CDN]",
      "mode": "set"
    },
    {
      "pattern": "$IP[192.168.2.1-255]",
      "header": "$RES[X-Cache]",
      "mode": "unset"
    },
    {
      "pattern": "$IP[192.168.3.0/24]",
      "header": "$RES[cache-control: no-cache, private]",
      "mode": "append"
    },
    {
      "pattern": "$IP[192.168.4.0/255.255.255.0]",
      "header": "$RES[x-custom-header]",
      "mode": "unset"
    },
    {
      "pattern": "$HEADER[user-agent: *IE6*]",
      "header": "$RES[vary]",
      "mode": "unset"
    },
    {
      "pattern": "$HEADER[x-custom-header]",
      "header": "$RES[cache-control: no-cache, private]",
      "mode": "append"
    },
    {
      "pattern": "$URL[/source/*]",
      "header": "$RES[cache-control: no-cache]",
      "mode": "set_if_not_exist"
    },
    {
      "pattern": "/secure/*.dat",
      "header": "$RES[x-custom]",
      "mode": "unset"
    },
    {
      "pattern": "/*.mp4",
      "header": "$RES[Access-Control-Allow-Origin: example1.com]",
      "mode": "set"
    },
    {
      "pattern": "/*.mp4",
      "header": "$RES[Access-Control-Allow-Origin: example2.com]",
      "mode": "put"
    }
  ]
}

그 밖에 특수 목적의 예약어를 지원한다.

예약어

설명

#PROTOCOL

클라이언트가 요청한 프로토콜. http 또는 https

#PORT

클라이언트가 접속한 포트. 80 , 443

#CACHEHIT

히트율 의 상세코드

#SESSIONID

access.logsession-id

#XCTXID

access.logx-ctx-id

#HOSTNAME

호스트 이름

#1 ~ #9

pattern$URL[]* 에 해당하는 문자열

"modify": {
  "enable": true,
  "matchFirstOnly": false,
  "matchingList": [
    {
      "pattern": "$URL[/download/*.pdf]",
      "header": "$RES[Content-Disposition: #1]",
      "mode": "set"
    },
    {
      "pattern": "$URL[*]",
      "header": "$REQ[X-Forwarded-Proto: #PROTOCOL]",
      "mode": "set"
    },
    {
      "pattern": "$URL[*]",
      "header": "$REQ[X-Forwarded-Port: #PORT]",
      "mode": "set"
    },
    {
      "pattern": "$URL[*]",
      "header": "$ORGREQ[X-Client-Forwarded-Port: #PORT]",
      "mode": "set"
    },
    {
      "pattern": "$URL[*]",
      "header": "$RES[X-Cache-Result: #CACHEHIT]",
      "mode": "set"
    },
    {
      "pattern": "$URL[*]",
      "header": "$RES[X-Cache-Sessionid: #SESSIONID]",
      "mode": "set"
    },
    {
      "pattern": "$URL[*]",
      "header": "$RES[X-Cache-Hostname: #HOSTNAME]",
      "mode": "set"
    },
    {
      # rewrite의 경우 header 필드의 값으로 헤더명만 입력한다.
      "pattern": "$URL[*]",
      "header": "$RES[Location]",
      "mode": "rewrite",
      "rewrites": [
        {
          "pattern": "([^/]+)/(.*)]",
          "replace": "www.example.com/#2"
        },
        {
          "pattern": "bar.com/(.*)?cache=on",
          "replace": "cache.example.com/#1"
        }
      ]
    }
  ]
}

debug

"debug": {
  "enableContentProcessing": false
}
enableContentProcessing (기본: false)

undocumented

accessControl

가상호스트별로 서비스 허용, 차단, Redirect를 설정한다.

"accessControl": {
  "enable": false,
  "defaultAction": "allow",
  "defaultCaseSensitive": true,
  "matchingList": [
    {
      "pattern": "!HEADER[referer] & !HEADER[user-agent] & !HEADER[host]",
      "action": "deny"
    },
    {
      "pattern": "$URL[/source/public.zip]",
      "caseSensitive": false,
      "action": "allow",
      "denialCode": 404
    }
  ]
}

enable (기본: false)

  • false (기본) ACL이 활성화되지 않는다. 모든 클라이언트 요청을 허가한다.

  • true ACL이 활성화된다.

    차단된 요청에 대해서는 denialCode 속성에 설정된 응답코드로 응답한다.

defaultAction (기본: allow)

matchingList 에 해당하지 않거나 action 이 정의되지 않은 조건에 대한 기본 행위

defaultCaseSensitive (기본: true)

  • true (기본) 헤더를 제외한 값의 대소문자를 구분한다. (헤더는 대소문자 미구분이 스펙이다.)

  • false 대소문자를 구분하지 않는다.

denialCode (기본: 401)

차단된 요청에 대한 응답코드

matchingList

접근제어 목록

pattern

매칭 패턴

caseSensitive

아이템의 대소문자 구분여부. 값이 없다면 defaultCaseSensitive (기본: true) 를 사용한다.

action (기본: deny)

deny 또는 allow

denialCode

차단된 요청에 대한 응답코드

allow/deny

모든 클라이언트 HTTP요청에 대하여 허용/거부 여부를 설정한다. deny 된 요청은 access.logTCP_DENY 로 기록된다. 각 조건마다 별도로 응답코드를 설정할 수 있다.

"accessControl": {
  "enable": true,
  "defaultAction": "deny",
  "denialCode": 401,
  "matchingList": [
    {
      "pattern": "$IP[192.168.1.1]",
      "action": "allow"
    },
    {
      "pattern": "$IP[192.168.2.1-255]"
    },
    {
      "pattern": "$IP[192.168.3.0/24]",
      "action": "deny"
    },
    {
      "pattern": "$IP[192.168.4.0/255.255.255.0]"
    },
    {
      "pattern": "$IP[AP] & !HEADER[referer]",
      "action": "allow"
    },
    {
      "pattern": "$HEADER[cookie: *ILLEGAL*]",
      "action": "deny",
      "action": 404
    },
    {
      "pattern": "$HEADER[via: Apache]"
    },
    {
      "pattern": "$HEADER[x-custom-header]"
    },
    {
      "pattern": "!HEADER[referer] & !HEADER[user-agent] & !HEADER[host]",
      "action": "deny"
    },
    {
      "pattern": "$URL[/source/public.zip]",
      "action": "allow"
    },
    {
      "pattern": "$URL[/source/*]"
    },
    {
      "pattern": "/profile.zip",
      "action": "deny",
      "denialCode": 500
    {
      "pattern": "/secure/*.dat"
    }
  ]
}

허용/차단 조건은 IP, GeoIP, Header, URL, Protocol 5가지로 설정이 가능하다.

  • IP

    $IP[...] 로 표기하며 IP, IP Range, Bitmask, Subnet 네 가지 형식을 지원한다.

  • GEOIP

    $IP[...] 로 표기하며 반드시 GeoIP설정이 되어 있어야 동작한다.

  • HEADER

    $HEADER[Key : Value] 로 표기한다. Value는 명확한 표현과 패턴을 인식한다. $HEADER[Key:] 처럼 구분자는 있지만 Value가 빈 문자열이라면 요청 헤더의 값이 비어 있는 경우를 의미한다. $HEADER[Key] 처럼 구분자 없이 Key만 명시되어 있다면 Key에 해당하는 헤더의 존재유무를 조건으로 판단한다.

  • URL

    $URL[...] 로 표기하며 생략이 가능하다. 명확한 표현과 패턴을 인식한다.

  • PROTOCOL

    $PROTOCOL[...] 로 표기한다.

    • $PROTOCOL[http] 요청이 HTTP 이다.

    • $PROTOCOL[https] 요청이 HTTPS 이다.

    • $PROTOCOL[http2] 요청이 HTTP2 이다.

Note

$ 는 “조건에 맞다면 ~ 한다”를 의미하며, ! 는 “조건에 맞지 않는다면 ~ 한다”를 의미한다. 다음과 같이 부정조건으로 지원한다.

"matchingList": [
  {
    # 국가가 KOR이 아니라면 deny한다.
    "pattern": "!IP[KOR]",
    "action": "deny"
  },
  {
    # referer헤더가 존재하지 않는다면 deny한다.
    "pattern": "!HEADER[referer]",
    "action": "deny"
  },
  {
    # /secure/ 경로 하위가 아니라면 allow한다.
    "pattern": "!URL[/secure/*]",
    "action": "allow"
  }
]

redirect

모든 클라이언트 HTTP요청에 대하여 Redirect 여부를 설정한다. Redirect된 요청은 302 Moved temporarily 로 응답하며 denialCode 로 설정이 가능하다.

"matchingList": [
  {
    "pattern": "$IP[GIN]",
    "action": "redirect",
    "location": "/page/illegal_access.html"
  },
  {
    "pattern": "$HEADER[referer:]",
    "action": "redirect",
    "location": "http://another-site.com",
    "denialCode": 307
  },
  {
    "pattern": "!HEADER[referer]",
    "action": "redirect",
    "location": "http://example.com#URL"
  }
]

Warning

POST 요청을 사용 중이라면 307 Temporary Redirect 를 권장한다. Chrome/103 버전의 테스트 결과는 다음과 같다.

응답코드

POST 요청시

301 Moved Permanently

GET 으로 재요청됨

302 Found

GET 으로 재요청됨

303 See Other

GET 으로 재요청됨

307 Temporary Redirect

POST 요청과 Body 가 유지됨

Redirect 시점에 지원되는 예약어는 다음과 같다.

예약어

설명

#HOST

클라이언트 요청의 Host 헤더

Note

#HOST 참조 시 포트는 제거한다.

Host: example.com:8080

위와 같이 요청된 경우 #HOST 의 값은 example.com 이다.

#URL

클라이언트 요청 URL

#1 ~ #9

pattern 설정의 * 에 해당하는 문자열

설정 예제는 다음과 같다.

"matchingList": [
  {
    # HTTP 요청이라면 HTTPS로 강제하도록 redirect시킨다.
    "pattern": "$PROTOCOL[HTTP]",
    "action": "redirect",
    "location": "https://example.com#URL"
  },
  {
    # 모든 요청에 대해 8080 포트로 리다이렉트 시킨다.
    "pattern": "$URL[/*]",
    "action": "redirect",
    "location": "http://#HOST:8080#URL"
  },
  {
    # 문자열을 추출하여 리다이렉트 시킨다.
    "pattern": "$URL[/domain/*/url/*]",
    "action": "redirect",
    "location": "https://#1/#2"
  }
]

optionsMethod

"optionsMethod": {
  "enable": true
}
enable (기본: true)

OPTIONS 메소드 처리. false 경우 501 Not Implemented , true 인 경우 200 OK 응답

Note

extraMethodsOPTIONS 메소드가 설정되었다면 이 설정은 무시된다.

bypass

클라이언트 요청처리를 원본서버에게 위임하는 바이패스에 대해 설정한다. 바이패스는 캐싱정책보다 우선한다.

{
  "functions": {
    "network": {
      "http": {
        "frontEnd": {
          "bypass": {
            ...
          }
        }
      }
    }
  }
}

session

바이패스는 원본서버에서 동적으로 처리한 결과를 응답하는 경우가 많다. 이로 인해 처리 속도가 정적인 콘텐츠보다 느린 경우가 많다. 바이패스 전용 Timeout을 설정하여 섣부른 장애판단이 되지 않도록 한다.

"session": {
  "connectTimeout": 5,
  "receiveTimeout": 300
}
connectTimeout (기본: 5)

바이패스를 위해 n초 이내에 원본서버와 접속이 이루어지지 않는 경우 접속실패로 처리한다.

receiveTimeout (기본: 300)

바이패스 중 원본서버의 응답이 n초 동안 없다면 전송실패로 처리한다.

stickiness

항상 같은 서버로 바이패스되도록 다양한 옵션을 제공한다.

"stickiness": {
  "enable": false,
  "mode": "net_route"
}
enable (기본: false)

stickiness 활성화

mode (기본: net_route)

stickiness 모드

  • none session .balanceMode 로 동작한다.

  • net_route 클라이언트 세션별로 바이패스된 원본 IP를 기억하여 동일 원본 IP로 라우팅한다. 최초 바이패스는 Round-Robin으로 선택한다.

  • net_clientip 클라이언트 IP를 해쉬하여 원본 IP를 선택한다. 원본 IP가 증설, 감축되면 다른 원본 IP로 라우팅될 수 있다.

  • app_cookie_route 바이패스된 원본서버의 힌트를 Set-Cookie 로 설정한다. 최초 바이패스는 Round-Robin으로 선택한다.

    Set-Cookie: M2_BYPASS_TOKEN=<서버힌트>; path=/;
    

    예제와 같이 옵션이 없는 Session Cookie로 동작하기 떄문에 현재 세션동안만 유효하다. Set-Cookie 헤더의 키는 app_cookie_route.name 으로 설정한다.

    # functions.network.http.frontEnd.bypass.stickiness
    
    "stickiness": {
      "enable": true,
      "mode": "app_cookie_route",
      "cookieHint": "M2_BYPASS_TOKEN",
      "cookiePath": "/"
    }
    

    cookiePath 속성을 null 로 설정하면 아래와 같이 명기하지 않는다.

    Set-Cookie: M2_BYPASS_TOKEN=<서버힌트>;
    

    Warning

    path 가 생략된다면 크롬에서는 아래와 같이 수신한 URL Path를 Path로 지정한다.

    ../../../../_images/app_cookie_route_path.png

    같은 Name 이라도 Path 가 다르면 Cookie 헤더에 동일한 Name 과 다른 값이 중복될 수 있어 의도치 않은 결과를 초래할 수 있다.

  • app_cookie_origin 바이패스된 원본서버에서 Set-Cookie 특정 키를 지정할 때에만 원본서버의 힌트를 Set-Cookie 로 설정한다. 최초 또는 Set-Cookie 특정 키가 없는 경우 Round-Robin으로 동작한다.

    # functions.network.http.frontEnd.bypass.stickiness
    
    "stickiness": {
      "enable": true,
      "mode": "app_cookie_origin",
      "cookieHint": "M2_BYPASS_TOKEN"
      "cookieOrigin": "JSESSIONID"
    }
    

    위 설정은 원본서버에서 Set-CookieJSESSIONID 값을 설정할 때 서버힌트를 삽입한다.

    Set-Cookie: JSESSIONID=DB926DF0772BAE3CB361E0BE1A9A7DE7; Expires=Thu, 21 Oct 2022 07:28:00 GMT; Secure; HttpOnly
    Set-Cookie: M2_BYPASS_TOKEN=<서버힌트>; Expires=Thu, 21 Oct 2022 07:28:00 GMT; Secure; HttpOnly
    

    이 모드는 예제와 같이 원본의 Cookie 설정옵션을 모두 승계하며 cookiePath 설정등은 무시한다. 따라서 Persistent Cookie로 동작할 수 있다.

Note

서버힌트와 일치하는 서버를 찾을 수 없는 경우 초기화된다. Round Robin으로 원본 IP가 재선택되고 이후 설정된 절차를 따른다.

matchingList

accessControl 과 동일한 조건을 모두 지원한다.

"matchingList": [
  {
    "pattern": "$IP[192.168.2.1-255]"
  },
  {
    "pattern": "/index.html"
  }
]
matchingList

조건 리스트

pattern

매칭 패턴

action

action 을 명확하게 명시하지 않은 경우 기본설정과 반대로 동작한다.

예를 들어 getMethod 설정을 바이패스하도록 설정하면 예외조건은 캐싱목록이 된다. 혼란스럽다면 항상 action 을 명시하자.

 "matchingList": [
    {
      # 항상 캐싱한다.
      "pattern": "$HEADER[cookie: *ILLEGAL*]",
      "action": "cache"
    },
    {
      # 기본 설정에 따라 다름
      "pattern": "!HEADER[referer:]",
      "action": "cache"
    },
    {
      # 항상 바이패스
      "pattern": "!HEADER[referer] & !HEADER[user-agent]",
      "action": "bypass"
    },
    {
      # 기본 설정에 따라 다름
      "pattern": "$URL[/source/public.zip]"
    }
}

Note

정리하면 우선순위는 다음과 같다.

  1. No-Cache 바이패스

  2. matchingList"action": "bypass" 라고 명시된 경우

  3. matchingList 에서 인식하는 기본 설정

함수체인 등 많은 HTTP/콘텐츠 가공기능은 cache 엔진을 기반으로 한다. 때문에 bypass 는 HTTP/콘텐츠 가공기능을 사용하지 못한다.

bypass 되어야 하는 트래픽을 HTTP/콘텐츠 가공처리하고 싶을 때 instant 모드를 사용한다.

"matchingList": [
   {
      # login 된 요청을 instant모드로 지정하면 캐싱엔진을 통해 가공할 수 있다.
      "pattern": "$HEADER[cookie: *login=yes*] && $URL[/search/*]",
      "action": "instant"
   }
}

instant 모드 상세

instant 모드의 장점은 bypass 처럼 개인화 트래픽에도 활용할 수 있음과 동시에 cache 엔진의 강력한 기능을 활용할 수 있다는 점이다.

기능

bypass

cache

instant

콘텐츠 캐싱

X

O

O

콘텐츠 재가공

X

O

O

fallbacks

X

O

O

콘텐츠 개인화

O

X

O

메모리/디스크 사용

X

O

Warning

instant 를 함수체인과 같이 사용할 경우 각별히 주의해야 한다. 특히 비디오, 이미지등 고용량 콘텐츠가 HIT 되지 않기 때문에 캐싱엔진의 메모리 사용량이 요청수만큼 순식간에 폭증될 우려가 있기 때문이다.

자원(메모리/디스크) 사용량 관점에서 전송 메커니즘을 비교하면 동작 방식과 주의사항을 쉽게 이해할 수 있다. 아래는 3개의 메모리 블록으로 이루어진 콘텐츠를 전송하는 과정을 비교한 것이다.

  • bypass - 캐싱없이 전송 수신된 메모리를 중계만 한다.

    클라이언트 <------■------ BYPASS[] <------■------ 원본
    
  • cache - 캐싱하며 전송한다. 트랜잭션이 종료되어도 콘텐츠는 유지된다.

    클라이언트 <------■ ■ ■------- CACHE[■ ■ ■] <-------■ ■ ■------ 원본
    클라이언트                     CACHE[■ ■ ■]                     원본
    
  • instant - 함수체인이 사용되지 않는다면 전송 중인 메모리 블럭만을 캐싱하며, 완료되면 소거된다.

    # 1. 전송 중인 메모리 블럭만 캐싱하며 전송한다.
    클라이언트 <-------■------ CACHE[■ □ □] <-------■------ 원본
    클라이언트 <-------■------ CACHE[□ ■ □] <-------■------ 원본
    클라이언트 <-------■------ CACHE[□ □ ■] <-------■------ 원본
    
    # 2. 트랜잭션이 종료되면 콘텐츠는 소거된다.
    클라이언트                CACHE[]                     원본
    
  • instant + 함수체인 - 함수체인이 사용된다면 HIT 만 되지 않을 뿐 콘텐츠 생성과정은 cache 와 동일하게 동작한다. 중간 처리과정이 모두 캐싱되며 더 이상 접근이 없는 경우라면 모든 메모리가 소거된다.

    # 원본비디오 ---> 트랜스코더 이미지 추출 ---> DIMS 인 경우 중간 과정이 모두 캐싱된다.
    클라이언트 <------ CACHE[■ ■ ■] <------ DIMS[■ ■ ■] <------ TRANSCODER[■ ■ ■] <------  원본
    
    # 트랜잭션이 종료되어도 최대 3초간 콘텐츠는 유지된다.
    클라이언트         CACHE[■ ■ ■]         DIMS[■ ■ ■]         TRANSCODER[■ ■ ■]          원본
    
    # 이후 모든 메모리는 소거된다.
    클라이언트         CACHE[]              DIMS[]              TRANSCODER[]               원본
    

Note

instant 모드는 캐싱엔진을 사용하지만 바이패스의 성격을 가지고 있기 때문에 cookie 관련헤더 또는 커스텀헤더 등이 모두 캐싱된다. 단, 아래 표준 헤더들은 캐싱엔진에서 콘텐츠 처리와 연관되어 재해석된다.

  • Cache-Control
    • Content-Disposition

    • Content-Encoding

    • Content-Length

    • Content-Type

    • Expire

    • Transfer-Encoding

    • Server

    • Date

    • Keep-Alive

    • Connection

    • ETag

    • Last-Modified

    • Accept-Ranges

noCacheRequest

클라이언트가 no-cache요청을 보냈다면 바이패스한다.

GET / HTTP/1.1
cache-control: no-cache 또는 cache-control:max-age=0
pragma: no-cache
"noCacheRequest": {
  "enable": false
}
enable (기본: false)

true 로 설정하면 클라이언트가 no-cache요청을 보냈을 때 바이패스한다.

Note

이 설정은 클라이언트 동작(아마도 ctrl + F5 )에 의해 판단된다. 그러므로 대량의 바이패스가 원본에 부담을 줄 가능성이 있다.

getMethod

바이패스가 GET요청의 기본동작이 되도록 설정한다.

"getMethod": {
  "enable": false
}
enable (기본: false)

기본 동작은 캐싱이다. true 로 설정하면 GET 요청을 원본서버로 바이패스한다.

postMethod

바이패스가 POST요청의 기본동작이 되도록 설정한다.

"postMethod": {
  "enable": true
}
enable (기본: true)

기본 동작은 원본 바이패스이다. false 로 설정하면 POST 요청을 캐싱한다.

extraMethods

HEAD, GET, POST 제외한 HTTP method 요청에 대한 기본 응답은 처리할 수 없기에 501 Not Implemented 이다. 특정 메소드를 원본서버가 처리할 수 있다면 설정 리스트에 추가하여 바이패스 시킨다.

"extraMethods": [
]
extraMethods

원본으로 바이패스할 메소드 리스트

  • 설정가능 - PUT , DELETE , PATCH , OPTIONS , TRACE , PATCH

    # PUT, OPTIONS 메소드만 바이패스한다.
    "extraMethods": [
      "PUT",
      "OPTIONS"
    ]
    
  • 설정불가 - CONNECT , HEAD , GET , POST , 기타 비표준 문자열

    # 등록불가하거나 알 수 없는 메소드는 무시된다.
    "extraMethods": [
      "CONNECT",
      "HEAD",
      "LIKE"
    ]
    

Note

이 설정은 OPTIONS 메소드에 대해 optionsMethod 보다 우선한다. 따라서 OPTIONS 메소드가 등록되면 원본으로 바이패스된다.

compression

원본 콘텐츠를 압축하여 전송한다.

Note

압축은 캐싱엔진을 경유할 때만 동작한다.

"compression": {
  "enable": false,
  "useOriginEncoding": false,
  "method": "gzip",
  "minSrcSize": 2,
  "maxSrcSize": 2048,
  "matchingList": [
    {
      "pattern": "$URL[/*.css]",
    },
    {
      "pattern": "$URL[/*.js]",
    }
  ]
}
enable (기본: false)

압축 활성화

useOriginEncoding (기본: false)

원본 Content-Encoding 응답에 따라 조건부 압축을 진행한다.

  • false (기본) 항상 솔루션에서 압축하도록, 원본에 Accept-Encoding 헤더를 보내지 않는다.

  • true 원본에 Accept-Encoding 헤더를 보내고, 원본에서 압축하지 않았을 때 (= Content-Encoding 을 명시하지 않았을 때)만 압축한다.

method (기본: gzip)

우선 압축 알고리즘 ( gzip 또는 br ). 클라이언트와 호환되지 않는다면 자동 선택되거나 압축하지 않는다.

minSrcSize (기본: 2KB)

최소 압축크기

maxSrcSize (기본: 2048KB)

최대 압축크기

matchingList

매칭리스트. 압축할 대상 URL을 결정한다.

gzip

gzip 압축정책을 설정한다.

"gzip": {
  "level": 6
}
level (기본: 6)

gzip 압축 레벨 (범위: 1~9)

brotli

brotli 압축정책을 설정한다.

"brotli": {
  "window": 22
  "quality": 11
}
window (기본: 22)

LZ77 window size (범위: 10~24)

quality (기본: 11)

압축 레벨 (범위: 0~11)

customErrorPage

원본통신 장애등으로 인해 정상적인 서비스가 불가능한 경우 미리 정의된 에러페이지를 제공한다.

"customErrorPage": {
  "resCode": 0,
  "path": "/error.html"
}
responseCode (기본: 0)

에러페이지의 HTTP 응답코드. 0인 경우 STON의 에러코드가 제공된다.

path

원본장애 발생시 제공할 에러페이지 경로/URL

backEnd

M2와 원본서버 사이의 HTTP 트랜잭션에 대해 설정한다.

{
  "functions": {
    "network": {
      "http": {
        "backEnd": {
          ...
        }
      }
    }
  }
}

urlRewrites

캐싱을 목적으로 원본으로 보내는 HTTP요청의 URL을 변경한다.

"urlRewrites" : [
  {
    # /download/1.3.4 -> /1.3.4
    "pattern": "/download/(.*)",
    "replace": "/#1"
  },
  {
    # /img/image.jpg?date=20140326 -> /image.jpg?date=20140326/m2/composite/watermark1
    "pattern": "/img/(.*\.(jpg|png).*)",
    "replace": "/#1/m2/composite/watermark1"
  }
]
pattern

변경대상의 정규식 패턴

replace

정규식 패턴

urlRewrites 와 같은 표현을 사용하지만 가상호스트마다 독립적으로 설정하기 때문에 가상호스트명을 입력하지 않는다.

Note

바이패스되는 HTTP요청의 URL은 변경할 수 없다. wholeClientRequest 보다 우선한다.

session

원본서버 연결 및 요청 유입정책을 설정한다.

"session":{
  "connectTimeout": 3,
  "receiveTimeout": 10,
  "reuseTimeout": 60,
  "balanceMode": "roundrobin",
  "maxUnknownSize": 32
}
connectTimeout (기본: 3)

n초 이내에 원본서버와 접속이 이루어지지 않는 경우 접속실패로 간주한다.

receiveTimeout (기본: 10)

정상적인 HTTP요청에도 불구하고 원본서버가 HTTP응답을 n초 동안 보내지 않는 경우 전송실패로 간주한다.

reuseTimeout (기본: 60)

일정 시간동안 사용되지 않은 원본세션은 종료한다. 0으로 설정하면 원본서버 세션을 재사용하지 않는다.

balanceMode (기본: roundrobin)

원본서버 주소가 멀티(2개 이상)로 구성되어 있을 때 원본서버 선택정책을 설정한다.

  • roundrobin - 모든 원본서버가 균등하게 요청을 받도록 Round-Robin으로 동작한다. 연결된 Idle세션은 해당 서버로 요청이 필요할 때만 사용한다.

  • session - 재사용할 수 있는 세션이 있다면 우선 사용한다. 신규 세션이 필요하면 Round-Robin으로 할당한다.

  • hash - 컨텐츠를 Consistent Hashing 알고리즘에 따라 원본서버로 분산하여 요청한다. 서버가 선택되면 이미 연결된 세션을 재사용하며 없다면 신규로 접속한다.

maxUnknownSize (기본: 32MB)

크기를 알 수 없는 원본 콘텐츠 최대 버퍼링 크기. 아래 2가지 상황을 모두 만족해야 maxUnknownSize 버퍼링이 이루어진다.

  • localCacheStorage 가 구성되어 있지 않은 경우 (=메모리 모드)

  • 원본에서 Content-Length 헤더를 제공하지 않는 경우 (예. Transfer-Encoding: Chunked )

Note

이 경우 응답코드는 507 Insufficient Storage 이다. 이 응답이 발생할 경우 가급적 버퍼를 늘리는 것보다 다음 방안을 검토하는 것을 권장한다.

  • 해당 URL을 바이패스한다.

  • 원본에서 Content-Length 를 부여한다.

hash

"balanceMode": "hash" 일 때 분산정책을 설정한다.

"hash":{
  "urlIgnoreList": [
    "/dims/",
    "?start="
  ]
}
urlIgnoreList (기본: null)

효율화를 위해 URL 중 매칭되는 영역부터 Hash 정책에서 무시하도록 설정한다.

dns

원본주소를 Domain으로 설정하면 Resolving해서 IP를 얻어야 한다. ( dns.log 에 기록된다.) IP 목록은 동적으로 변경될 수 있으며 모든 IP는 TTL(Time To Live)동안만 유효하다.

  • Domain은 주기적으로(1~10초) Resolving한다.

  • Resolving을 통해 사용할 IP테이블을 구성한다.

  • 모든 IP는 TTL만큼만 유효하며 TTL이 만료되면 사용하지 않는다.

  • 같은 IP가 다시 Resolving되면 TTL을 갱신한다.

  • IP테이블은 비어서는 안된다. (TTL이 만료되었더라도) 마지막 IP들은 삭제되지 않는다.

IP의 TTL이 너무 길 경우 지나치게 많은 IP를 사용하게 되어 의도치 않은 결과를 만들 수 있다. 이를 방지하기 위해 IP의 최대 TTL을 제한할 수 있다.

"dns": {
  "ttlMin": 0,
  "ttlMax": 0
}
ttlMin (기본: 0)

Resolved TTL 값이 적다면 ttlMin 값으로 보정한다.

ttlMax (기본: 0)

Resolved TTL 값이 크다면 ttlMax 값으로 보정한다.

간혹 너무 TTL이 짧은 경우 ttlMin 설정을 통해 최소 값을 보정할 수 있다. 예를 들어 ttlMin: 30 이라면 TTL이 30초 미만인 경우 30초로 보정된다.

Note

원본주소를 Domain으로 설정하여도 장애/복구는 IP기반으로 동작한다. Domain주소 장애/복구 정책은 다음과 같다.

  • (Domain에 대해) 알고 있는 모든 IP주소가 배제(Inactive)되면 해당 Domain주소가 배제된다.

  • 신규 IP가 Resolving되더라도 Domain이 배제되어 있다면 IP주소는 처음부터 배제된다.

  • 모든 IP가 TTL 만료되더라도 배제된 Domain상태는 풀리지 않는다.

  • 배제된 Domain에 속한 IP주소가 하나라도 복구되어야 해당 Domain은 다시 활성화된다.

다소 복잡한 내용이므로 원본상태 모니터링 API 결과 값의 상태변화를 서비스 동작상태에 대해 이해도를 높이는 것이 좋다.

health

원본서버 장애/복구 정책에 대해 설정한다.

{
  "functions": {
    "network": {
      "http": {
        "backEnd": {
          "health": {
            ...
          }
        }
      }
    }
  }
}

exclusion

캐싱과정 중 원본서버에 장애가 발생하면 자동배제한다.

"exclusion": {
  "count": 3,
  "events": {
    "serverClosed": false
  }
}
exclusion (기본: 3)

원본서버에서 연속적으로 n번 장애상황이 발생하면 해당 서버를 유효 원본서버 목록에서 배제한다. 배제 전 정상적인 통신이 이루어진다면 이 값은 다시 0으로 초기화된다.

Note

"count": 0 으로 설정하면 원본서버를 배제하지 않는다.

events

기본 장애상황인 connectTimeout , receiveTimeout 외에 장애상황을 추가한다.

serverClosed (기본: false)

서버에서 트랜잭션 완료 전 연결을 먼저 종료하는 경우를 장애로 간주한다.

recovery

배제된 원본서버가 다시 안정화됐다고 판단하면 서비스에 투입한다.

"recovery": {
  "cycle": 10,
  "count": 5,
  "responseCode": 0,
  "url": "/",
  "log": true,
  "host": null
}
cycle (기본: 10초)

복구주기

Note

"cycle": 0 으로 설정하면 배제된 원본서버를 복구하지 않는다.

count (기본: 5)

복구허용 연속횟수

responseCode (기본: 0)

정상응답으로 처리할 응답코드. 0인 경우 응답코드와 상관없이 응답이 오면 성공으로 간주한다. 200으로 설정하면 응답코드가 반드시 200이어야 정상응답으로 처리한다. 콤마(,)를 사용하여 유효한 응답코드를 멀티로 설정한다. 200, 206, 404로 설정하면 응답코드가 이 중 하나인 경우 정상응답으로 처리한다.

url (기본: /)

요청을 보낼 url

log (기본: true)

복구를 위해 사용된 HTTP Transaction을 Origin 로그 에 기록한다.

host (기본: null)

복구 세션에서 사용할 Host 헤더를 설정한다.

  • null 또는 "" - 가상호스트 명을 사용한다.

  • 문자열 - 설정된 문자열을 Host 헤더와 SNI 필드로 사용한다.

cycle 마다 url 로 요청하여 원본서버가 responseCode 로 연속적으로 count 만큼 응답하면 해당 서버를 복구한다.

health-checkers

exclusionrecovery 는 캐싱과정 중 발생하는 장애에 대응한다. recovery 는 응답코드를 받는 즉시 HTTP 트랜잭션을 종료한다. 하지만 Health-Checker는 HTTP 트랜잭션이 성공함까지 주기적으로 확인하여 원본서버 배제여부를 결정한다.

"checkers": [
  {
    "resCode": [0],
    "timeout": 10,
    "cycle": 10,
    "exclusion": 3,
    "recovery": 5,
    "log": true,
    "url": "/",
    "host": null
  },
  {
    "resCode": [200, 404],
    "timeout": 10,
    "cycle": 10,
    "exclusion": 3,
    "recovery": 5,
    "log": true,
    "url": "/alive.html",
    "host": null
  }
]
resCode (기본: 0)

올바른 응답코드 (배열로 멀티 구성가능)

timeout (기본: 10초)

소켓연결부터 HTTP 트랜잭션이 완료될 때까지 유효시간

cycle (기본: 10초)

실행주기

exclusion (기본: 3회)

연속 n회 실패 시 해당서버 배제

recovery (기본: 5회)

연속 n회 성공 시 해당서버 재투입

log (기본: true)

HTTP 트랜잭션을 origin.log 에 기록한다.

url

요청 url

host (기본: null)

헬쓰체커에서 사용할 Host 헤더를 설정한다.

  • null 또는 "" - 가상호스트 명을 사용한다.

  • 문자열 - 설정된 문자열을 Host 헤더와 SNI 필드로 사용한다.

Health-Checker는 멀티로 구성할 수 있으며 클라이언트 요청과 상관없이 독립적으로 수행되며, 각각의 기준으로 배제와 투입을 결정한다.

headers

{
  "functions": {
    "network": {
      "http": {
        "backEnd": {
          "headers": {
            ...
          }
        }
      }
    }
  }
}

cacheOriginal

성능과 보안상의 이유로 원본서버가 보내는 헤더 중 캐싱과 관련된 표준 헤더만을 선별적으로 캐싱한다.

Note

어떠한 경우라도 다음 헤더는 캐싱할 수 없다.

  • cookie

  • set-cookie

  • set-cookie2

원본이 응답하는 헤더를 캐싱하기 위해서는 추가 설정이 필요하다.

"cacheOriginal": {
  "enable": false,
  "standard": false
}

enable (기본: false)

  • false (기본) 다음 헤더만을 캐싱한다.

    Cache-Control
    Content-Disposition
    Content-Encoding
    Content-Length
    Content-Type
    Expire
    Transfer-Encoding
    Server
    
  • true 위 목록 이외의 헤더를 캐싱한다.

    • "standard": false (기본) 비표준 헤더만을 캐싱한다.

    • "standard": true 비표준 헤더와 다음 목록의 헤더를 추가로 캐싱한다.:

      Content-Language
      Content-Location
      Content-MD5
      Proxy-Authenticate
      Retry-After
      TE
      Trailer
      Warning
      WWW-Authenticate
      

host

원본서버로 보내는 HTTP요청의 Host 헤더를 설정한다. 별도로 설정하지 않은 경우 가상호스트 이름이 명시된다.

"host": {
  "enable": false,
  "value": null
}

enable (기본: false)

  • false (기본) - 가상호스트 이름

  • true - value 를 host 헤더의 값으로 설정한다. 클라이언트가 보낸 Host헤더를 원본으로 보내고 싶은 경우 * 로 설정한다.

value

host 헤더 값

Note

원본서버에서 80포트 이외의 포트로 서비스하고 있다면 반드시 포트 번호를 명시해야 한다.

"host": {
  "enable": true,
  "value": "www.example2.com:8080"
}

Warning

proxy 함수는 동적으로 Host 헤더를 결정하기 때문에 이 설정보다 우선한다. 따라서 proxy 함수를 사용한다면 proxy 함수의 host 명령어를 사용하여 Host 헤더를 변경해야 한다.

userAgent

원본서버로 보내는 HTTP요청의 User-Agent 헤더를 설정한다.

"userAgent": {
  "enable": false,
  "value": null
}

enable (기본: false)

  • false - 기본 User-Agent 헤더

  • true - value 를 User-Agent 헤더의 값으로 설정한다.

value

host 헤더 값. 클라이언트가 보낸 User-Agent헤더를 원본으로 보내고 싶은 경우 * 로 설정한다.

xff

클라이언트와 원본서버 사이에 M2를 위치하면 원본서버는 클라이언트 IP를 얻을 수 없다. 때문에 M2는 원본서버로 보내는 모든 HTTP요청에 X-Forwarded-For 헤더를 명시한다.

"xff": {
  "appendProxy": true
}

appendProxy (기본: true)

  • true XFF헤더의 첫번째 주소만을 원본서버로 전송한다.

    X-Forwarded-For: 220.61.7.150
    
  • false 클라이언트(IP: 128.134.9.1)가 보낸 XFF헤더에 클라이언트 IP를 추가한다.

    클라이언트가 XFF헤더를 보내지 않았다면 클라이언트 IP만 명시된다.

    X-Forwarded-For: 220.61.7.150, 61.1.9.100, 128.134.9.1
    

ifRange

원본에 Range요청을 보낼 때 If-Range헤더를 추가하여 요청한다.

"ifRange": {
  "enable": false
}

enable (기본: false)

  • false - Range요청 시 If-Range헤더를 추가하지 않는다.

  • true - Range요청 시 If-Range헤더를 추가한다.

Note

If-Range 헤더에 의해 원본서버가 206 Partial Content 가 아닌 200 OK 응답을 주는 경우 다음과 같이 전개된다.

  • 클라이언트가 요청한 파일은 무효화 처리

  • 해당 클라이언트 요청은 실패

  • 동일한 파일이 요청될 때 신규 캐싱 서비스

wholeClientRequest

원본에 요청할 때 클라이언트가 보낸 요청을 유지하도록 설정한다.

"wholeClientRequest": {
  "enable": false
}

wholeClientRequest (기본: false)

  • false (기본) 캐싱엔진이 사용하는 캐싱키를 원본에 요청할 URL로 사용한다.

  • true 클라이언트가 요청한 URL로 원본에 요청한다.

originalEtag

원본서버에서 응답하는 ETag인식여부를 설정한다.

"originalEtag": {
  "enable": false
}

originalEtag (기본: false)

  • false (기본) ETag 헤더를 무시한다.

  • true ETag 헤더를 인식하며 컨텐츠 갱신시 If-None-Match 헤더를 추가한다.

limitMaxRange

한번에 다운로드 받는 컨텐츠 크기를 설정한다. 동영상처럼 앞 부분만이 주로 소비되는 컨텐츠의 경우 다운로드 크기를 제한하면 불필요한 원본 트래픽을 줄일 수 있다.

"limitMaxRange": {
  "enable": false,
  "size": 1
}
enable (기본: false)

기능 활성화

size (단위: MB)

0보다 크면 클라이언트가 요청한 지점부터 설정크기(MB) 만큼 Range요청으로 다운로드 한다.

limitMaxRange 를 사용하는 또 다른 이유는 디스크 공간을 절약하기 위함이다. 기본설정으로 M2는 원본크기의 파일을 디스크에 생성한다. 하지만 size 가 0이 아니라면 다운로드 되는만큼만 파일을 분할하여 저장한다.

예를 들어 1시간짜리 영상(600MB)을 1분(10MB)만 시청한 경우에 디스크 공간을 10MB만 사용한다. 공간을 절약하는 장점은 있지만 파일이 분할되어 저장되기 때문에 디스크 부하가 조금 높아진다.

Note

최초 콘텐츠를 다운로드할 때 Content-Length를 알 수 없으므로 Range요청을 할 수 없다. 때문에 size 가 설정되어 있다면 설정크기만큼만 다운로드 받고 연결을 종료한다.

initByFullRange

일반적으로 원본서버로부터 처음 파일을 다운로드 할 때나 갱신확인 할 때는 다음과 같이 단순한 형태의 GET 요청을 보낸다.

GET /file.dat HTTP/1.1

하지만 원본서버가 일반적인 GET요청에 대하여 항상 파일을 변조하도록 설정되어 있다면 원본파일 그대로를 Caching할 수 없어서 문제가 될 수 있다.

가장 대표적인 예는 Apache 웹서버가 mod_h.264_streaming같은 외부모듈과 같이 구동되는 경우이다. Apache 웹서버는 GET요청에 대해서 항상 mod_h.264_streaming모듈을 통해서 응답한다. 클라이언트(이 경우에는 M2)는 원본파일 그대로가 아닌 모듈에 의해 변조된 파일을 서비스 받는다.

../../../../_images/conf_origin_fullrangeinit1.png

mod_h.264_streaming모듈은 항상 원본을 변조한다.

Range요청을 사용하면 모듈을 우회하여 원본을 다운로드할 수 있다.

"initByFullRange": {
  "enable": false,
  "method": "get"
}
initByFullRange (기본: false)

true - 0부터 시작하는 Range요청을 보낸다. Apache의 경우 Range헤더가 명시되면 모듈을 우회한다.

GET /file.dat HTTP/1.1
Range: bytes=0-

최초로 파일 Caching할 때는 컨텐츠의 Range를 알지 못하므로 Full-Range(=0부터 시작하는)를 요청한다. 원본서버가 Range요청에 대해 정상적으로 응답(206 OK)하는지 반드시 확인해야 한다.

method (기본: get)

head 로 설정할 경우 HEAD 메소드로 최초 요청을 보낸다.

HEAD /file.dat HTTP/1.1

콘텐츠를 갱신할 때는 다음과 같이 If-Modified-Since 헤더가 같이 명시된다. 원본서버가 올바르게 304 Not Modified 로 응답해야 한다.

GET /file.dat HTTP/1.1
Range: bytes=0-
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Note

initByFullRange 가 정상동작함을 확인한 웹서버들 목록.

  • Microsoft-IIS/7.5

  • nginx/1.4.2

  • lighttpd/1.4.32

  • Apache/2.2.22

modify

원본 HTTP요청과 응답헤더를 조건에 따라 변경한다.

"modify": {
  "enable": false,
  "matchFirstOnly": false,
  "defaultCaseSensitive": true,
  "matchingList": [
    {
      "pattern": "$URL[/*.mp4]",
      "header": "$ORGREQ[x-media-type: video/mp4]",
      "caseSensitive": false,
      "mode": "set"
    },
    {
      "pattern": "$URL[/images/private/*]",
      "header": "$ORGRES[Server: m2server]",
      "mode": "set_if_not_exist"
    },
    {
      "pattern": "$IP[1.1.1.1]",
      "header": "$ORGREQ[user-agent: media_probe]",
      "mode": "put"
    },
    {
      "pattern": "*",
      "header": "$ORGREQ[If-Modified-Since]",
      "mode": "unset"
    },
    {
      # #PROTOCOL 키워드를 통해 클라이언트가 요청한 프로토콜을 헤더에 추가한다.
      "pattern": "$URL[*]",
      "header": "$ORGREQ[X-Forwarded-Proto: #PROTOCOL]",
      "mode": "set"
    },
    {
      # $REQ.header-name을 이용해 클라이언트 요청을 원본으로 보낼 수 있다.
      "pattern": "$URL[/account/]",
      "header": "$ORGREQ[cookie: $REQ.Cookie]",
      "mode": "set"
    },
    {
      # #HOSTNAME 키워드를 통해 요청을 보내는 호스트(서버) 이름을 헤더에 추가한다.
      "pattern": "$URL[*]",
      "header": "$ORGREQ[X-Req-Hostname: #HOSTNAME]",
      "mode": "set"
    }
  ]
}

$ORGREQ $ORGRES 키워드를 사용한다는 것만 제외하면 modify 와 동일하다.

Note

If-Modified-Since 헤더와 If-None-Match 헤더를 unset 하면 TTL이 만료된 컨텐츠는 항상 다시 다운로드 한다.

forwardContextId

클라이언트 HTTP 트랜잭션의 UUID(로그의 x-ctx-id 필드)를 원본서버로 전달한다.

"forwardContextId": {
  "enable": false,
  "header": "X-M2X-Forwarded-Context-Id"
}
enable (기본: false)

기능 활성화

header (기본: X-M2X-Forwarded-Context-Id)

헤더 이름

authorization

AWS S3 인증스펙인 Authenticating Requests (AWS Signature Version 4) 를 지원한다.

Note

읽기 권한인 GET 메소드만을 지원한다. 쓰기(POST, PUT, FETCH)는 캐시서버의 목적에 부합하지 않는다.

"authorization": {
  "enable": false,
  "type": "aws-s3",
  "region": "",
  "accessKeyId": "",
  "accessKeyIdType": null,
  "secretAccessKey": "",
  "secretAccessKeyType": null
}
enable (기본: false)

원본인증 활성화

type

원본인증 타입

  • aws-s3 - AWS-S3 Signature Version 4

region

aws-s3 리젼

accessKeyId

액세스 키

secretAccessKey

시크릿 키

accessKeyIdType (기본: null)

액세스 키 타입.

secretAccessKeyType (기본: null)

시크릿 키 타입

Authenticating Requests (AWS Signature Version 4) 동작에 필요한 세부 설정 accessKeyID , secretAccessKey , region 을 구성한다. hosting 이 아닌 functions.networks.http.backEnd.authorization 에 설정하면 모든 가상호스트에 적용된다.

Note

Google Cloud Storage를 인증하는 경우에도 활용이 가능하다.

  • 서비스 계정의 HMAC 키를 생성한다. ( 링크 )

  • 생성된 HMAC 키를 accessKeyIdsecretAccessKey 의 값으로 설정한다.

  • region 은 서버에서 검사하지 않으므로 seoul 로 입력한다.

redirectionTrace

원본서버에서 Redirect계열(301, 302, 303, 307)로 응답하는 경우 Location 헤더를 추적하여 콘텐츠를 요청한다.

"redirectionTrace": {
  "enable": false,
  "max": 3,
  "responseCode": ["3xx", "302", "307"],
  "url": [ "*.ts", "*.mp4" ]
}
enable (기본: false)
true 로 설정하면 Location헤더에 명시된 주소에서 콘텐츠를 다운로드 한다.

형식에 맞지 않거나 Location헤더가 없는 경우에는 동작하지 않는다. 무한히 Redirect되는 경우를 방지하기 위하여 1회만 추적한다.

max (기본: 3)

최대 redirect 동작 회수. 0 이라면 enablefalse 인 것과 동일하다.

responseCode

처리할 응답코드 목록

url": [ "*.ts", "*.mp4" ]

URL패턴을 설정하면 추적할 Location 대상을 지정할 수 있다.