mod_headers 는 HTTP 요청 및 응답 헤더를 조정하고 변경할 수 있는 모듈이다.

HTTP 헤더는 여러 헤더를 하나로 합치거나 치환하거나 삭제할 수 있다.


처리 순서

mod_headers가 제공하는 지시어는 서버 설정의 거의 모든 부분에서 사용할 수 있으며, Location 이나 Directory, IfModule, VirtualHost 같은 설정 섹션으로 감싸서 적용 범위를 제한할 수도 있다.

처리순서는 중요하며, 설정 파일에 나온 순서와 설정 섹션의 영향을 받는다. 다음 두 지시어를 반대로 적으면 다른 결과가 나온다.

RequestHeader append MirrorID "mirror 12"
RequestHeader unset MirrorID

MirrorID 를 추가한 후에 unset MirrorID 를 하기 때문에 헤더가 나오지 않는다. 반대로 적을 경우 unset 후에 append 를 하는 것이므로 헤더가 표시된다.

Header 지시자

HTTP 응답 헤더를 처리하는 지시자이다. 다음과 같은 문법을 갖게 된다.

Header [condition] set|append|add|unset|echo header [value[replacement] [early|env=[!]variable]

condition 은 생략될 수 있으며 값은 onsuccess나 always 를 사용한다. 그 다음 명령문은 동작으로 다음과 같은 설정이 가능하다.

  • set
     응답 헤더를 설정한다. 기존 헤더에 같은 이름의 헤더가 있으면 덮어 쓴다.
  • append
     기존 헤더에 값을 추가한다.
  • add 
    기존 HTTP 응답 헤더에 새로이 추가한다. 같은 이름의 헤더가 이미 있을 경우 여러 개의 헤더가 보일 수 있다. 이것은 예상하지 못한 문제점을 발생시킬 수 있으므로 add 는 사용하지 않기를 권장한다.
  • unset 
    HTTP 응답 헤더에 지정된 이름의 헤더를 삭제한다. 
  • echo
     HTTP 요청 헤더중 지정된 이름의 헤더가 있을 경우 응답 헤더에 추가 한다.

header 항목은 Content-Type: 같은 일치시킬 헤더 이름을 적어주면 되며 value 는 변경할 값을 적어 준다.  set, append, merge, add 일 경우 value 가 반드시 있어야 한다. value 에 공백이 있을 경우 따옴표("") 로 묶어 주면 된다. env 는 특정 환경 변수의 존재 여부에 따라 동작하게 하는 설정이다.

RequestHeader 지시자

Header 지시자와 기능과 문법은 동일하나  컨텐츠 핸들러보다 먼저 호출되며 HTTP 요청 헤더에 대해 작동하므로 브라우저가 보낸 헤더를 수정, 대치, 삭제할 수 있다는 점만 다르다. 브라우저가 특정 헤더를 보내고 이를 수정해야 할 경우에 사용하면 된다.


mod_headers 사용예제

간략하게 문법과 옵션의 의미에 대해서 알아보았으니 mod_header를 어떻게 활용하는지 실제 사용예를 알아보자. 


요청 헤더를 응답 헤더에 복사

echo 를 사용하면 요청 헤더에 있는 내용을 응답 헤더에 출력할 수 있다. 다음은 Host 로 시작하는 요청 헤더를 응답에 출력한다.

Header echo ^Ho

특정 Contype-Type 일 경우 처리

SetEnvIf 는 특정 조건을 만족할 경우 환경 변수를 설정/해제할 수 있으므로 mod_headers 와 SetEnvIf 를 같이 사용하면 다양한 조건에서 HTTP 헤더를 통제할 수 있다.

다음은 Content-Type 이 json 일 경우 Content-Type 을 대문자로 변경하는 예제이다.

SetEnvIf Content-Type application/json is_json
Header set Content-Type: APPLICATION/JSON env=is_json

PHP 특정 헤더 제거

PHP 를 아파치 모듈로 설치하면 모든 PHP 스크립트 구동시 X-Powered-By 라는 헤더를 추가하고 자세한 PHP 버전을 전송하게 된다.

이는 불필요하며 서버의 정보를 과다하게 노출시키게 되므로 mod_headers 를 이용하여 제거해 보자.

다음과 같이 httpd.conf 에 설정하면 모든 php 스크립트 수행시 X-Powered-By 헤더를 제외하고 전송한다.

Header unset X-Powered-By

IE 브라우저의 호환성 보기 끄기

MS의 Internet Explorer 로 웹 페이지에 연결할 경우 호환성 보기가 켜져 있으면 예전 렌더링 엔진이 동작하여 최신 웹 기술을 적용한 페이지는 제대로 표시되지 않을 수 있다. 

HTML내에 <meta http-equiv="X-UA-Compatible" content="IE=edge"태그를 삽입하면 호환성 보기를 끄는 방법도 있지만 HTML 마다 삽입해야 하므로 mod_header를 사용하여 X-UA-Compatible HTTP 헤더를 설정하면 서버 설정으로 간단하게 처리할 수 있다.

다음은 BrowserMatch 로 IE 를 확인한 후에 Header 명령어로 X-UA-Compatible 를 설정해서 보내는 예제이다.

BrowserMatch MSIE is-msie

Header set X-UA-Compatible IE=edge env=is-msie

로그인 페이지는 캐쉬하지 않음

관리자 화면이나 기타 로그인이 필요한 페이지가 있을 경우 보안때문에 캐쉬하지 않는게 좋다. mod_headers 와 아파치의 지시자를 사용하면 어플리케이션의 소스를 수정하지 않아도 가능하다.

<Location "/admin">
Header set Cache-Control "no-cache, no-store"

</Location>


Header 설정 디버깅하기

이제 mod_header 로 설정한 지시자가 정상적으로 동작하는지 확인하려면 어떻게 해야 하는지 생각해 보자. HTTP 헤더는 보통 브라우저에서 표시되지 않는다.

HTTP 헤더를 잡기 위해서 네트워크 패킷 캡춰 프로그램이나 혹은 HTTPWatch 같은 각종 HTTP 정보를 볼 수 있는 툴을 사용하는 것도 좋지만  하려는 일에 비해 너무 과한 측면이 있다.


이럴 때 가장 간편하고 편리한 유틸리티가 중요 유틸리티에서 설명한 curl 이다. curl 은 http 클라이언트로 사용할 수 있고 다양한 옵션으로 curl의 동작을 지정할 수 있으므로 HTTP 관련 디버깅 및 테스트 작업에 매우 유용하다.

이 용도에 가장 맞는 옵션은 상세한 정보를 출력하는 -v 옵션 또는 서버가 전송한 HTTP 헤더 정보만 출력하는 -I(대문자 i) 옵션일 것이다.


이제 실제로 curl 을 이용하여 디버깅하는 예제에 대해서 알바 보자.

여기 PHP 로 개발되었고 /admin URL에서 관리자 기능을 제공하는 어플리케이션이 있다고 가정하자. 다음과 같이 curl 을 통해 서버가 보내는 HTTP 헤더를 확인해 볼 수 있다.

$ curl -I lesstif.example.com/admin/login.php

HTTP/1.1 200 OK
Date: Sat, 26 Jul 2014 05:55:18 GMT
Server: Apache
X-Powered-By: PHP/5.3.3
Content-Type: text/html

X-Powered-By 헤더를 제거하여 PHP 실행 정보를 전송하지 않고  admin 페이지는 캐싱하지 않기 위해 다음과 같이 가상 호스트 설정을 변경하고 웹서버를 재구동한 후에 curl 을 실행하여 정상 동작 여부를 디버깅할 수 있다.

<VirtualHost *:80>

ServerName lesstif.example.com
DocumentRoot /var/www/lesstif/
Header unset X-Powered-By

<Location "/admin">

Header set Cache-Control "no-cache, no-store"

</Location>

</VirtualHost>


이제 curl 을 재실행하면 다음과 같이 X-Powered-By 헤더가 제외되고 Cache-Control 헤더가 전송되고 있음을 확인할 수 있다.

$ curl -I lesstif.example.com/admin/login.php

HTTP/1.1 200 OK
Date: Sat, 26 Jul 2014 05:59:40 GMT
Server: Apache
Cache-Control: no-cache, no-store
Content-Type: text/html


Ref






blog comments powered by Disqus