Problem discription
URL rewrite 가 인코딩된 주소를 받고, 이를 재작성(또는 리디렉션) 된 주소에 다시 활용하는 경우 잘못 인코딩된(=입력과 동일하지 않은) 주소를 반환하는 문제.
Background
워드프레스에서 제목을 한글로 쓰면 퍼머링크도 기본적으로 한글로 작성되기 때문에 이것을 수정하지 않고 저장하면 페이지 보기가 안되고 404 가 뜨는 문제가 있었다.
이것이 OS의 레거시 인코딩 문제(윈도우즈에서 유니코드가 아닌 ANSI 문자열을 사용하는 레거시 API를 호출하는 프로그램이 겪는 문제) 라고 생각했었는데… 아주 틀린 건 아니지만 내가 생각한 종류의 것은 아니었다.
알고보니 한글로 작성을 하더라도 클라이언트에서는 이 퍼머링크를 인코딩하여 보내므로 저장까지는 인코딩 문제가 발생하지 않고 잘 된다. 그러나 페이지 보기를 누르면 워드프레스의 설정의 사이트 주소가 http 를 기준으로 설정되어 있으므로 퍼머링크도 http 링크로 생성되어1 클라이언트가 http 주소로 접속을 시도한다. 그러면 서버는 이 요청을 https 리다이렉트 룰에 의하여 https 주소로 리다이렉트하는데, 이 과정에서 URL rewrite 가 프로토콜만 변경하고 나머지 값은 그대로 유지하여야 하지만 실제로는 그렇게 동작하지 않아서(path 값이 입력 그대로가 아닌 잘못 인코딩된 값으로 반환된다) 결국 404 에러가 발생하게 된다.
이것을 해결하기 위해서는,
- 워드프레스 사이트 주소를 https 로 설정
- 리다이렉트 룰이 제대로 인코딩 된 주소를 보내도록 수정
중에 하나를 수행하여야 하는데, 현재는 2개 모두 적용했다.
1. 의 경우에는 wp_config.php 파일의 WP_HOME 및 WP_SITEURL 변수를 수정해주면 되고, 2. 의 경우에는 아래에 서술한다.
Solution
원래는 이런 식의 https 리다이렉트 룰을 썼었다.
<rule name="https redirect" enabled="true" patternSyntax="Wildcard" stopProcessing="true"> <match url="*" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false"> <add input="{HTTPS}" pattern="OFF" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}{R:0}" redirectType="Permanent" /> </rule>
이것을 보면, 룰에 의하여 캡처된 주소를 그대로 리턴하므로 문제가 없을 것 같지만 실제로는 잘못된 주소를 리턴한다.
이를 해결하기 위해 현재는 다음의 룰을 사용한다.
<rule name="https redirect" enabled="true" patternSyntax="Wildcard" stopProcessing="true"> <match url="*" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false"> <add input="{HTTPS}" pattern="OFF" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}{UNENCODED_URL}" redirectType="Permanent" /> </rule>
캡처 과정에서 문제가 발생하는 것 같아 {R:0} 대신 {UNENCODED_URL} 를 사용하여 클라이언트가 요청한 값을 그대로 돌려주도록 했다.
한편, URL Rewrite Module Configuration Reference2 에 의하면 또한 {HTTP_X_ORIGINAL_URL} 도 제시되고 있는데, 로그를 보면 X-ORIGINAL-URL 서버 변수는 기록되고 있는 것으로 보이지만 URL Rewrite 에서 저 변수를 쓰면 그냥 공백이 리턴된다. 전에도 다른 건으로 검색해보았지만 납득할만한 설명이 없었던 것으로 보아 이것 또한 버그로 보인다.
Continue reading “URL Rewrite 에서 인코딩된 주소를 재작성시 제대로 처리하지 못하는 문제”