본문 바로가기
WIKI 기술 지식 베이스

header 지시문

원문 보기 위키 갱신

header 지시문 (응답 헤더 조작)

header 지시문은 HTTP 응답 헤더 필드를 조작해요. 헤더 값을 설정·추가·삭제하거나 정규 표현식으로 치환할 수 있어요.

출처: Caddy 공식 문서

본문

HTTP 응답 헤더 필드를 조작해요. 헤더 값을 설정·추가·삭제하거나 정규 표현식을 사용해 치환할 수 있어요.

기본적으로 헤더 연산은 즉시 수행돼요. 단 헤더 중 하나라도 삭제(- 접두사)되거나 기본 값 설정(? 접두사)이면 예외예요. 그런 경우 헤더 연산은 클라이언트에 쓰는 시점으로 자동 연기돼요.

HTTP 요청 헤더를 조작하려면 request_header 지시문을 사용해요.

문법 (Syntax)

header [<matcher>] [[+|-|?|>]<field> [<value>|<find>] [<replace>]] {
	# Add
	+<field> <value>

	# Set
	<field> <value>

	# Set with defer
	><field> <value>

	# Delete
	-<field>

	# Replace
	<field> <find> <replace>

	# Replace with defer
	><field> <find> <replace>

	# Default
	?<field> <value>

	[defer]

	match <inline_response_matcher>
}
  • ****는 헤더 필드의 이름이에요.

    접두사가 없으면 필드를 설정(덮어쓰기)해요.

    +를 붙이면 필드가 이미 존재해도 덮어쓰지 않고 추가해요. 헤더 필드는 응답에 여러 번 나타날 수 있어요.

    -를 붙이면 필드를 삭제해요. 필드에 접두사 또는 접미사 * 와일드카드를 써서 일치하는 필드를 모두 삭제할 수 있어요.

    ?를 붙이면 필드의 기본 값을 설정해요. 필드는 아직 없을 때만 작성돼요.

    >를 붙이면 필드를 설정하면서 defer를 활성화하는 단축이에요.

  • ****는 필드를 추가하거나 설정할 때의 헤더 필드 값이에요.

  • ****는 검색할 정규 표현식이에요. 검색 패턴에 동적 입력을 위한 placeholder를 사용할 수 있어요. 사용되는 정규 표현식 언어는 RE2로, Go에 포함돼 있어요. RE2 문법 참조와 Go regexp 문법 개요를 참고해요.

  • ****는 치환 값이에요. 검색-치환을 수행하면 필수예요. 검색 패턴의 캡처 그룹을 참조하려면 $1이나 $2 등을 사용해요. 치환 값이 ""이면 일치한 텍스트가 값에서 제거돼요. 자세한 내용은 Go 문서를 참고해요.

  • defer는 응답이 클라이언트로 보내질 때까지 헤더 연산의 실행을 연기해요. 이 옵션은 다음 조건에서 자동으로 활성화돼요:

    • -로 헤더 필드가 삭제되는 경우

    • ?로 기본 값을 설정하는 경우

    • set 또는 replace 연산에 > 접두사를 사용하는 경우

    • match 조건이 하나 이상 있는 경우

  • match는 인라인 응답 matcher예요. 지정된 조건을 만족하는 응답에만 헤더 연산이 적용돼요.

여러 헤더 조작에는 블록을 열고 같은 방식으로 한 줄에 하나씩 지정할 수 있어요.

? 접두사로 기본 헤더 값을 설정할 때, 여러 헤더 연산이 있는 header 블록 안에 있었다면 자동으로 별도의 header 핸들러로 분리돼요. 내부적으로 ?를 쓰면 지시문 전체 핸들러에 적용되는 응답 matcher를 설정해요. 이는 defer 같은 헤더 연산만 적용하되, 필드가 아직 설정되지 않았을 때만 적용해요.

예시 (Examples)

모든 응답에 커스텀 헤더 필드를 설정해요:

header Custom-Header "My value"

"Hidden" 헤더 필드를 제거해요:

header -Hidden

모든 Location 헤더에서 http://를 https://로 치환해요:

header Location http:// https://

모든 페이지에 보안·프라이버시 헤더를 설정해요: (경고: 영향력을 이해할 때만 사용해요!)

header {
	# HSTS 활성화
	Strict-Transport-Security max-age=31536000;

	# 클라이언트가 미디어 타입을 스니핑하지 못하게 함
	X-Content-Type-Options nosniff

	# 클릭재킹 방지
	X-Frame-Options DENY
}

상호 배타적으로 의도된 여러 header 지시문:

route {
	header           Cache-Control max-age=3600
	header /static/* Cache-Control max-age=31536000
}

업스트림이 정의하지 않으면 기본 캐시 만료를 설정해요:

header ?Cache-Control "max-age=3600"
reverse_proxy upstream:443

GET 요청에 대한 모든 성공 응답을 최대 한 시간 동안 캐시 가능으로 표시해요:

@GET method GET
header @GET Cache-Control "max-age=3600" {
	match status 2xx
}
reverse_proxy upstream:443

업스트림 서버에서 예외가 발생한 경우 에러 응답의 캐싱을 방지해요:

header {
	-Cache-Control
	-CDN-Cache-Control
	match status 500
}
reverse_proxy upstream:443

업스트림 서버가 클라이언트 힌트를 지원한다면, 라이트 모드 응답을 다크 모드 응답과 별도로 캐시 가능하게 표시해요:

header {
	Cache-Control "max-age=3600"
	Vary "Sec-CH-Prefers-Color-Scheme"
	match {
		header Accept-CH "*Sec-CH-Prefers-Color-Scheme*"
		header Critical-CH "Sec-CH-Prefers-Color-Scheme"
	}
}
reverse_proxy upstream:443

와일드카드 값을 특정 도메인으로 치환해 과도하게 허용적인 CORS 헤더를 방지해요:

header >Access-Control-Allow-Origin "\*" "allowed-partner.com"
reverse_proxy upstream:443

참고: 치환 연산에서 <find> 값은 정규 표현식으로 해석돼요. * 문자를 매칭하려면 위 예시처럼 백슬래시로 이스케이프해야 해요.

대안으로 응답 matcher를 사용해 헤더 값을 그대로 매칭할 수 있어요:

header Access-Control-Allow-Origin "allowed-partner.com" {
	match header Access-Control-Allow-Origin *
}
reverse_proxy upstream:443

/no-cache로 시작하는 경로에 대해 프록시 업스트림이 설정한 캐시 만료를 덮어쓰려면, 헤더가 프록시가 헤더를 쓴 후에 설정되도록 defer를 활성화해야 해요:

header /no-cache* >Cache-Control no-cache
reverse_proxy upstream:443

Set-Cookie 헤더에 SameSite=None을 추가하는 지연 업데이트를 수행하려면, 정규식 캡처를 사용해 기존 값을 잡고 $1로 시작 부분에 다시 삽입하면서 추가 옵션을 붙여요:

header >Set-Cookie (.*) "$1; SameSite=None;"

더 알아보기 (Learn more)