답변:
mod_rewrite
규칙은 httpd.conf
파일 또는 파일 내에 배치 될 수 있습니다 .htaccess
. 에 액세스 할 수있는 경우 httpd.conf
여기에 규칙을 배치하면 성능 이점이 제공됩니다 ( .htaccess
파일이 호출 될 때마다 규칙이 한 번 처리되기 때문에 ).
httpd.conf
파일 내에서 로깅을 활성화 할 수 있습니다 (포함 <Virtual Host>
).
# logs can't be enabled from .htaccess
# loglevel > 2 is really spammy!
RewriteLog /path/to/rewrite.log
RewriteLogLevel 2
모든 요청을 단일 지점으로 전달하려면 :
RewriteEngine on
# ignore existing files
RewriteCond %{REQUEST_FILENAME} !-f
# ignore existing directories
RewriteCond %{REQUEST_FILENAME} !-d
# map requests to index.php and append as a query string
RewriteRule ^(.*)$ index.php?query=$1
Apache 2.2.16부터 FallbackResource
.
301/302 리디렉션 처리 :
RewriteEngine on
# 302 Temporary Redirect (302 is the default, but can be specified for clarity)
RewriteRule ^oldpage\.html$ /newpage.html [R=302]
# 301 Permanent Redirect
RewriteRule ^oldpage2\.html$ /newpage.html [R=301]
참고 : 외부 리디렉션은 암시 적으로 302 리디렉션입니다.
# this rule:
RewriteRule ^somepage\.html$ http://google.com
# is equivalent to:
RewriteRule ^somepage\.html$ http://google.com [R]
# and:
RewriteRule ^somepage\.html$ http://google.com [R=302]
SSL 강제
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://example.com/$1 [R,L]
일반적인 플래그 :
[R]
또는 [redirect]
-강제 리디렉션 (기본값은 302 임시 리디렉션)[R=301]
또는 [redirect=301]
-301 영구 리디렉션 강제[L]
또는 [last]
-재 작성 프로세스 중지 (일반적인 함정에 대해서는 아래 참고 참조)[NC]
또는 [nocase]
-일치가 대소 문자를 구분하지 않도록 지정
긴 형식의 플래그를 사용하는 것이 더 읽기 쉽고 나중에 코드를 읽는 다른 사람들에게 도움이됩니다.
쉼표로 여러 플래그를 구분할 수 있습니다.
RewriteRule ^olddir(.*)$ /newdir$1 [L,NC]
mod_alias
스타일 리디렉션과 혼합mod_rewrite
# Bad
Redirect 302 /somepage.html http://example.com/otherpage.html
RewriteEngine on
RewriteRule ^(.*)$ index.php?query=$1
# Good (use mod_rewrite for both)
RewriteEngine on
# 302 redirect and stop processing
RewriteRule ^somepage.html$ /otherpage.html [R=302,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# handle other redirects
RewriteRule ^(.*)$ index.php?query=$1
참고 : mod_alias
와 함께 사용할 수 mod_rewrite
있지만 위와 같이 기본 리디렉션을 처리하는 것보다 더 많은 작업이 필요합니다.
컨텍스트가 구문에 영향을 미침
.htaccess
파일 내 에서 선행 슬래시는 RewriteRule 패턴에 사용되지 않습니다.
# given: GET /directory/file.html
# .htaccess
# result: /newdirectory/file.html
RewriteRule ^directory(.*)$ /newdirectory$1
# .htaccess
# result: no match!
RewriteRule ^/directory(.*)$ /newdirectory$1
# httpd.conf
# result: /newdirectory/file.html
RewriteRule ^/directory(.*)$ /newdirectory$1
# Putting a "?" after the slash will allow it to work in both contexts:
RewriteRule ^/?directory(.*)$ /newdirectory$1
[L]은 마지막이 아닙니다! (때때로)
[L]
플래그는 상기 다시 쓰기 규칙 처리를 중지 규칙 세트를 통해 해당 패스 . 그러나 해당 패스에서 URL이 수정되고 .htaccess
컨텍스트 또는 <Directory>
섹션에있는 경우 수정 된 요청이 URL 구문 분석 엔진을 통해 다시 전달됩니다. 그리고 다음 패스에서 이번에는 다른 규칙과 일치 할 수 있습니다. 당신이 이것을 이해하지 못한다면, 당신의 [L]
깃발이 효과가 없었던 것처럼 보입니다 .
# processing does not stop here
RewriteRule ^dirA$ /dirB [L]
# /dirC will be the final result
RewriteRule ^dirB$ /dirC
재 작성 로그는 규칙이 두 번 실행되고 URL이 두 번 업데이트되었음을 보여줍니다.
rewrite 'dirA' -> '/dirB'
internal redirect with /dirB [INTERNAL REDIRECT]
rewrite 'dirB' -> '/dirC'
이 문제를 해결하는 가장 좋은 방법 은 규칙의 모든 추가 처리 (및 후속 패스)를 진정으로 중지하려는 경우 플래그 대신 [END]
플래그 ( Apache 문서 참조 )를 사용하는 것입니다 [L]
. 그러나 [END]
플래그는 Apache v2.3.9 + 에서만 사용할 수 있으므로 v2.2 이하를 사용하는 경우 [L]
플래그 만 붙어 있습니다.
이전 버전 RewriteCond
의 경우 URL 구문 분석 엔진의 후속 패스에서 규칙이 일치하지 않도록 명령문에 의존해야합니다 .
# Only process the following RewriteRule if on the first pass
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ...
또는 RewriteRule이 httpd.conf
요청을 다시 구문 분석하지 않는 컨텍스트 (예 :)에 있는지 확인해야합니다 .
[L]
플래그는 규칙이 현재 처리에서 마지막 이라는 것을 의미합니다. 내부 리디렉션이기 때문에 다시 쓰기가 중지되지 않으므로 다음 htaccess 처리에 dirB
적용됩니다 dirC
. 혼자서 RewriteRule ^(.*)$ index.php?query=$1
는 내부 리디렉션의 무한 루프가됩니다 (실제로 10 회 반복 후에 종료 됨). -1 왜냐하면 [L]이 마지막이 아니라고 제안했기 때문 입니다. 재 작성 프로세스를 종료하는 것이 아니라 마지막 입니다.
RewriteCond %{HTTPS} off
HTTPS 연결을 확인하는 데 선호되는 방법 이라고 생각 합니다 (비 SSL 트래픽을 HTTPS로 강제하는 예제에서)
.*
와 관련된 모든 질문에 이것을 제안 할 것 [L]
입니다.
200
, !=200
, ^.
, ^$
. 분명히 변수는 200
리디렉션 을 위해 설정 되지만 다른 페이지 (오류 및 항목)도 값을 설정합니다. 이제 방법은 당신도 확인하는 것이 그것이 경우 is empty
, is not empty
, is 200
또는 is not 200
, 당신이 필요에 따라 달라집니다.
RewriteBase와의 거래 :
거의 항상 RewriteBase를 설정해야합니다. 그렇지 않으면 아파치는 기본이 디렉토리에 대한 물리적 디스크 경로라고 추측합니다. 따라서 다음과 같이 시작하십시오.
RewriteBase /
RewriteBase .
URL을 동일하게 유지해야 함을 나타내거나 지정한 내용 만 변경하면됩니다.
RewriteBase
에서 상대 경로 대체를 사용하는 경우 에만 설정해야합니다 RewriteRule
. 상대 경로를 사용하지 않는 것이 좋습니다.
RewriteBase
거의 모든 개발자가 그것이 무엇을하는지 오해하므로 아예 피 합니다. @ w3d가 말했듯이 문자를 저장하고 하나의 파일에있는 모든 RewriteRules에 동일한 기준을 적용하려는 경우에만 필요합니다. 당신이 그것을 피한다면 당신의 코드는 다른 사람들에게 더 명확해질 것입니다.
기타 함정 :
1- 때때로 MultiViews를 비활성화하는 것이 좋습니다.
Options -MultiViews
나는 모든 MultiViews 기능에 대해 좋은 구절은 아니지만, 속성 중 하나가 내가 찾고 있다고 생각하는 파일에 대한 확장자를 시도하고 '추측'하는 것이기 때문에 활성화되면 mod_rewrite 규칙을 엉망으로 만듭니다. .
설명하겠습니다 : 웹 디렉토리에 2 개의 php 파일, file1.php 및 file2.php가 있고 다음 조건과 규칙을 .htaccess에 추가한다고 가정합니다.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ file1.php/$1
파일 또는 디렉토리와 일치하지 않는 모든 URL이 file1.php에 의해 확보된다고 가정합니다. 놀라다! 이 규칙은 URL http : // myhost / file2 / somepath에 적용되지 않습니다 . 대신 file2.php 내부로 이동합니다.
무슨 일이 일어나고 있는지 MultiViews는 실제로 원하는 URL이 http : //myhost/file2.php/somepath 라고 자동으로 추측 하여 기꺼이 당신을 데려갔습니다.
이제 방금 무슨 일이 일어 났는지 전혀 알지 못하며, 그 시점에서 mod_rewrite에 대해 알고 있다고 생각했던 모든 것에 의문을 제기하고 있습니다. 그런 다음이 새로운 상황의 논리를 이해하기 위해 규칙을 가지고 놀기 시작하지만 더 많이 테스트할수록 의미가 떨어집니다.
간단히 말해, mod_rewrite가 로직에 가까운 방식으로 작동하도록하려면 MultiView를 끄는 것이 올바른 방향으로 나아가는 단계입니다.
2- FollowSymlinks 활성화
Options +FollowSymLinks
저것은 세부 사항을 잘 모르지만 여러 번 언급 한 적이 있으니 그냥하세요.
+FollowSymLinks
mod_rewrite
모호한 보안상의 이유로 문서 에서 작업에 필수로 언급되어 있습니다.
방정식은 다음 예를 통해 수행 할 수 있습니다.
RewriteCond %{REQUEST_URI} ^/(server0|server1).*$ [NC]
# %1 is the string that was found above
# %1<>%{HTTP_COOKIE} concatenates first macht with mod_rewrite variable -> "test0<>foo=bar;"
#RewriteCond search for a (.*) in the second part -> \1 is a reference to (.*)
# <> is used as an string separator/indicator, can be replaced by any other character
RewriteCond %1<>%{HTTP_COOKIE} !^(.*)<>.*stickysession=\1.*$ [NC]
RewriteRule ^(.*)$ https://notmatch.domain.com/ [R=301,L]
동적 부하 분산 :
mod_proxy를 사용하여 시스템의 균형을 맞추는 경우 작업자 서버의 동적 범위를 추가 할 수 있습니다.
RewriteCond %{HTTP_COOKIE} ^.*stickysession=route\.server([0-9]{1,2}).*$ [NC]
RewriteRule (.*) https://worker%1.internal.com/$1 [P,L]
[L] 플래그를 더 잘 이해하는 것이 좋습니다. [L] 플래그 는 마지막입니다. 요청이 URL 구문 분석 엔진을 통해 다시 라우팅되는 원인을 이해하면됩니다. 문서에서 ( http://httpd.apache.org/docs/2.2/rewrite/flags.html#flag_l ) (강조 내) :
[L] 플래그는 mod_rewrite가 규칙 세트 처리를 중지하도록합니다. 대부분의 컨텍스트에서 이는 규칙이 일치하면 더 이상 규칙이 처리되지 않음을 의미합니다. 이것은 Perl의 마지막 명령 또는 C의 break 명령에 해당합니다.이 플래그를 사용하여 추가 규칙을 고려하지 않고 현재 규칙을 즉시 적용해야 함을 나타냅니다.
.htaccess 파일 또는
<Directory>
섹션 에서 RewriteRule을 사용 하는 경우 규칙이 처리되는 방법을 이해하는 것이 중요합니다. 이것의 단순화 된 형태는 일단 규칙이 처리되면 재 작성된 요청이 URL 구문 분석 엔진으로 다시 전달 되어 그것으로 할 수있는 일을 할 수 있다는 것입니다. 재 작성된 요청이 처리<Directory>
될 때.htaccess 파일 또는섹션이 다시 발생할 수 있으므로 규칙 세트가 처음부터 다시 실행될 수 있습니다. 대부분의 경우 규칙 중 하나가 내부 또는 외부 리디렉션으로 인해 요청 프로세스가 다시 시작되는 경우에 발생합니다.
따라서 [L] 플래그 는 규칙 세트 를 통과 하는 해당 패스에 대한 추가 다시 쓰기 규칙 처리를 중지 합니다. 그러나 [L]로 표시된 규칙이 요청을 수정하고 .htaccess 컨텍스트 또는 <Directory>
섹션에있는 경우 수정 된 요청이 URL 구문 분석 엔진을 통해 다시 전달됩니다. 그리고 다음 패스에서 이번에는 다른 규칙과 일치 할 수 있습니다. 무슨 일이 일어 났는지 이해가 안된다면 [L] 플래그를 사용한 첫 번째 다시 쓰기 규칙이 효과가없는 것 같습니다.
이 문제를 해결하는 가장 좋은 방법은 정말로 중지하려는 경우 [L] 플래그 대신 [END] 플래그 ( http://httpd.apache.org/docs/current/rewrite/flags.html#flag_end )를 사용하는 것입니다. 모든 추가 규칙 처리 (및 후속 재분석). 그러나 [END] 플래그는 Apache v2.3.9 +에서만 사용할 수 있으므로 v2.2 이하를 사용하는 경우 [L] 플래그 만 사용됩니다. 이 경우 RewriteCond 문을 사용하여 URL 구문 분석 엔진의 후속 패스에서 규칙이 일치하지 않도록해야합니다. 또는 RewriteRule이 요청을 다시 구문 분석하지 않는 컨텍스트 (예 : httpd.conf)에 있는지 확인해야합니다.
또 다른 훌륭한 기능은 rewrite-map-expansions입니다. 처리 할 호스트 / 재 작성이 엄청나게 많은 경우 특히 유용합니다.
키-값 대체와 같습니다.
RewriteMap examplemap txt:/path/to/file/map.txt
그런 다음 다음과 같은 규칙에 매핑을 사용할 수 있습니다.
RewriteRule ^/ex/(.*) ${examplemap:$1}
이 주제에 대한 자세한 정보는 여기에서 찾을 수 있습니다.
http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#mapfunc
.htaccess
기반 재 작성을 . 이 맥락에서는 작동하지 않습니다.
mod_rewrite는 URL을 변경하지 않고도 요청 처리 측면을 수정할 수 있습니다 (예 : 환경 변수 설정, 쿠키 설정 등). 이것은 매우 유용합니다.
조건부로 환경 변수를 설정합니다.
RewriteCond %{HTTP_COOKIE} myCookie=(a|b) [NC]
RewriteRule .* - [E=MY_ENV_VAR:%b]
503 응답을 반환합니다.
RewriteRule
의 [R]
플래그는 비 -3xx 값을 취하고 리디렉션되지 않는 응답을 반환 할 수 있습니다 (예 : 관리되는 다운 타임 / 유지 보수의 경우).
RewriteRule .* - [R=503,L]
503 응답을 반환합니다 ( 리디렉션 자체가 아님).
또한 mod_rewrite는 mod_proxy에 대한 강력한 인터페이스처럼 작동 할 수 있으므로 ProxyPass
지시문 을 작성하는 대신이를 수행 할 수 있습니다 .
RewriteRule ^/(.*)$ balancer://cluster%{REQUEST_URI} [P,QSA,L]
의견 : RewriteRule
s 및 RewriteCond
s를 사용하여 요청의 거의 모든 가능한 측면을 기반으로 다른 애플리케이션 또는로드 밸런서로 요청을 라우팅하는 것은 매우 강력합니다. 백엔드로가는 도중에 요청을 제어하고 다시 나가는 동안 응답을 수정할 수 있으므로 mod_rewrite는 모든 라우팅 관련 구성을 중앙 집중화 할 수있는 이상적인 장소입니다.
시간을내어 배우십시오. 그만한 가치가 있습니다! :)