참조 : mod_rewrite, URL 재 작성 및 "예쁜 링크"설명
"예쁜 링크"는 자주 요청되는 주제이지만 완전히 설명되지는 않습니다. mod_rewrite 는 "예쁜 링크"를 만드는 한 가지 방법이지만 복잡하고 구문이 매우 간결하고 이해하기 어려우며 문서는 HTTP에 대한 특정 수준의 숙련도를 가정합니다. 누군가 "예쁜 링크"가 작동하는 방식과 mod_rewrite를 사용하여이를 만드는 방법을 간단한 용어로 설명 할 수 있습니까?
기타 일반적인 이름, 별칭, 깨끗한 URL 용어 : RESTful URL, 사용자 친화적 인 URL, SEO 친화적 인 URL, slugging 및 MVC URL (아마도 잘못된 이름)
답변
mod_rewrite가 무엇인지 이해하려면 먼저 웹 서버가 작동하는 방식을 이해해야합니다. 웹 서버는 HTTP 요청에 응답 합니다 . 가장 기본적인 수준의 HTTP 요청은 다음과 같습니다.
GET /foo/bar.html HTTP/1.1
이것은 URL /foo/bar.html 을 요청하는 웹 서버에 대한 브라우저의 간단한 요청입니다 . 파일을 요청하지 않고 임의의 URL 만 요청한다는 점을 강조하는 것이 중요합니다 . 요청은 다음과 같을 수도 있습니다.
GET /foo/bar?baz=42 HTTP/1.1
이것은 URL에 대한 유효한 요청과 마찬가지로 파일과 관련이 없습니다.
웹 서버는 포트에서 수신 대기하는 애플리케이션으로 해당 포트에서 들어오는 HTTP 요청을 수락하고 응답을 반환합니다. 웹 서버는 사용자가 응답하도록 구성한 방식으로 적합하다고 판단되는 방식으로 모든 요청에 대해 전적으로 무료로 응답 할 수 있습니다. 이 응답은 파일이 아니며 디스크의 실제 파일과 관련이있을 수도 있고 없을 수도 있는 HTTP 응답 입니다. 웹 서버가 Apache 일 필요는 없습니다. 지속적으로 실행되고 HTTP 요청에 응답하는 포트에 연결된 프로그램 인 다른 많은 웹 서버가 있습니다. 직접 작성할 수 있습니다. 이 단락은 URL이 파일과 직접적으로 동일하다는 개념에서 벗어나기 위해 작성되었으며, 이해하는 것이 정말 중요합니다. :)
대부분의 웹 서버의 기본 구성은 하드 디스크의 URL과 일치하는 파일을 찾는 것입니다. 서버 의 문서 루트 가로 설정되어 있으면 /var/www파일 /var/www/foo/bar.html이 존재 하는지 여부를 확인하여 제공 할 수 있습니다. 파일이 ".php"로 끝나면 PHP 인터프리터를 호출 한 다음 결과 를 반환합니다. 이 모든 연결은 완전히 구성 할 수 있습니다. 웹 서버가 PHP 인터프리터를 통해 파일을 실행하기 위해 파일이 ".php"로 끝나지 않아도되며, URL이 디스크의 특정 파일과 일치 할 필요가 없습니다.
mod_rewrite는 내부 요청 처리 를 다시 작성 하는 방법 입니다. 웹 서버가 URL 요청을 받으면 웹 서버가 디스크에서 일치하는 파일을 찾기 전에 해당 URL을 다른 것으로 다시 작성할/foo/bar 수 있습니다 . 간단한 예 :
RewriteEngine On
RewriteRule /foo/bar /foo/baz
이 규칙은 요청이 "/ foo / bar"와 일치 할 때마다 "/ foo / baz"로 다시 작성합니다. 그러면 요청이 /foo/baz대신 요청 된 것처럼 처리 됩니다. 다음과 같은 다양한 효과에 사용할 수 있습니다.
RewriteRule (.*) $1.html
이 규칙은 모든 항목 ( .*)과 일치 하여 캡처 ( (..)) 한 다음 ".html"을 추가하도록 다시 작성합니다. 즉, /foo/bar요청 된 URL이면 요청 된 것처럼 처리됩니다 /foo/bar.html. 정규식 일치, 캡처 및 대체에 대한 자세한 내용은 http://regular-expressions.info 를 참조하십시오 .
자주 접하는 또 다른 규칙은 다음과 같습니다.
RewriteRule (.*) index.php?url=$1
이것은 다시 무엇이든 일치시키고 url쿼리 매개 변수에 추가 된 원래 요청 된 URL을 사용하여 index.php 파일에 다시 작성합니다 . 즉, 들어오는 모든 요청에 대해 index.php 파일이 실행되고이 파일은의 원래 요청에 액세스 $_GET['url']할 수 있으므로 원하는 모든 작업을 수행 할 수 있습니다.
주로 이러한 재 작성 규칙을 웹 서버 구성 파일에 넣습니다 . Apache는 또한 .htaccess문서 루트 (즉, .php 파일 옆) 에있는 파일에 파일을 넣을 수 있습니다 * .
* 기본 Apache 구성 파일에서 허용하는 경우 ; 선택 사항이지만 종종 활성화됩니다.
mod_rewrite가하지 않는 것
mod_rewrite는 마술처럼 모든 URL을 "예쁘게"만드는 것은 아닙니다. 이것은 일반적인 오해입니다. 웹 사이트에이 링크가있는 경우 :
<a href="/my/ugly/link.php?is=not&very=pretty">
mod_rewrite가이를 예쁘게 만들기 위해 할 수있는 일은 없습니다. 이 링크를 예쁜 링크로 만들려면 다음을 수행해야합니다.
링크를 예쁜 링크로 변경하십시오.
<a href="/my/pretty/link">/my/pretty/link위에서 설명한 방법 중 하나를 사용 하여 URL에 대한 요청을 처리하려면 서버에서 mod_rewrite를 사용하십시오 .
( mod_substitute함께 사용 하여 나가는 HTML 페이지 및 포함 된 링크를 변환 할 수 있습니다 . 이는 HTML 리소스를 업데이트하는 것보다 일반적으로 더 많은 노력이 필요합니다.)
mod_rewrite가 할 수있는 일이 많고, 여러 재 작성을 연결하고, 요청을 완전히 다른 서비스 나 시스템에 프록시하고, 특정 HTTP 상태 코드를 응답으로 반환하고, 요청을 리디렉션하는 등 생성 할 수있는 매우 복잡한 일치 규칙이 있습니다. 매우 강력하며 다음 용도로 사용할 수 있습니다. 기본적인 HTTP 요청-응답 메커니즘을 이해하면 좋습니다. 자동으로 링크를 예쁘게 만들지 는 않습니다 .
가능한 모든 플래그 및 옵션 은 공식 문서 를 참조하십시오 .
deceze의 답변 을 확장 하기 위해 몇 가지 다른 mod_rewrite 기능에 대한 몇 가지 예와 설명을 제공하고 싶었습니다.
예 아래의 모든 이미 포함했다고 가정 RewriteEngine On당신의 .htaccess파일.
재 작성 예
이 예를 들어 보겠습니다.
RewriteRule ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ /blog/index.php?id=$1&title=$2 [NC,L,QSA]
규칙은 4 개의 섹션으로 나뉩니다.
RewriteRule-다시 쓰기 규칙을 시작합니다.^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$-이것을 패턴이라고합니다. 그러나 저는 이것을 규칙의 왼쪽 부분이라고 부르겠습니다.blog/index.php?id=$1&title=$2-대체 또는 재 작성 규칙의 오른쪽-재 작성하려는 항목[NC,L,QSA]다시 쓰기 규칙에 대한 플래그이며 쉼표로 구분됩니다. 나중에 자세히 설명하겠습니다.
위의 재 작성은 다음과 같은 링크를 허용 /blog/1/foo/하며 실제로로드 /blog/index.php?id=1&title=foo됩니다.
규칙의 왼쪽
^페이지 이름의 시작을 나타내므로 다시example.com/blog/...쓰지만example.com/foo/blog/...- 각
(…)괄호 세트 는 규칙의 오른쪽에서 변수로 캡처 할 수있는 정규식을 나타냅니다. 이 예에서 : ?앞의 문자가 선택 사항 이므로이 경우 모두/blog/1/foo/및/blog/1/foo같은 위치에 다시 씁니다.$이것이 우리가 일치시킬 문자열의 끝임을 나타냅니다.
플래그
특정 조건을 지정하기 위해 다시 쓰기 규칙 끝에 대괄호로 추가되는 옵션입니다. 다시 말하지만, 문서 에서 읽을 수있는 다양한 플래그가 있지만 더 일반적인 플래그 중 일부를 살펴 보겠습니다.
NC
no case 플래그는 다시 쓰기 규칙이 대소 문자를 구분하지 않음을 의미하므로 위의 예제 규칙의 경우 /blog/1/foo/및 /BLOG/1/foo/(또는 이것의 모든 변형)이 일치 함을 의미합니다.
L
마지막 플래그는 이것이 처리되어야하는 마지막 규칙임을 나타냅니다. 즉,이 규칙이 일치하는 경우에만 현재 다시 쓰기 처리 실행에서 더 이상의 규칙이 평가되지 않습니다. 규칙이 일치하지 않으면 다른 모든 규칙이 평소와 같이 순서대로 시도됩니다. L플래그를 설정하지 않으면 이후에 다시 작성된 URL에 다음 규칙이 모두 적용됩니다 .
END
Apache 2.4부터 [END]플래그 를 사용할 수도 있습니다 . 일치하는 규칙은 추가 별칭 / 다시 쓰기 처리를 완전히 종료합니다. ( [L]플래그가 종종 두 번째 라운드를 트리거 할 수있는 반면, 예를 들어 서브 디렉토리에 다시 쓰거나 나갈 때)
QSA
쿼리 문자열 추가 플래그를 사용하면 원래의 get 매개 변수에 추가 될 지정된 URL에 추가 변수를 전달할 수 있습니다. 이 예에서는 다음과 같은 내용 /blog/1/foo/?comments=15이로드 됨을 의미합니다./blog/index.php?id=1&title=foo&comments=15
R
이 플래그는 위의 예에서 사용한 플래그가 아니지만 언급 할 가치가 있다고 생각하는 플래그입니다. 이렇게하면 상태 코드 (예 :)를 포함하는 옵션과 함께 http 리디렉션을 지정할 수 있습니다 R=301. 예를 들어 / myblog /에서 / blog /로 301 리디렉션을 수행하려면 다음과 같은 규칙을 작성하면됩니다.
RewriteRule ^/myblog/(*.)$ /blog/$1 [R=301,QSA,L]
재 작성 조건
재 작성 조건 은 재 작성을 더욱 강력하게 만들어보다 구체적인 상황에 대한 재 작성을 지정할 수 있도록합니다. 문서 에서 읽을 수있는 많은 조건이 있지만 몇 가지 일반적인 예를 다루고 설명하겠습니다.
# if the host doesn't start with www. then add it and redirect
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
이것은 매우 일반적인 관행으로, 도메인 앞에 www.(아직없는 경우) 추가하고 301 리디렉션을 실행합니다. 예를 들어,로드 http://example.com/blog/하면 다음으로 리디렉션됩니다.http://www.example.com/blog/
# if it cant find the image, try find the image on another domain
RewriteCond %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)$ http://www.example.com/$1 [L]
이것은 약간 덜 일반적이지만 파일 이름이 서버에있는 디렉토리 나 파일 인 경우 실행되지 않는 규칙의 좋은 예입니다.
%{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]파일 확장자가 jpg, jpeg, gif 또는 png (대소 문자 구분 안 함) 인 파일에 대해서만 다시 쓰기를 실행합니다.%{REQUEST_FILENAME} !-f파일이 현재 서버에 있는지 확인하고 그렇지 않은 경우에만 다시 쓰기를 실행합니다.%{REQUEST_FILENAME} !-d파일이 현재 서버에 있는지 확인하고 그렇지 않은 경우에만 다시 쓰기를 실행합니다.- 다시 쓰기는 다른 도메인에서 동일한 파일을로드하려고 시도합니다.
참고 문헌
Stack Overflow에는 시작할 수있는 다른 많은 훌륭한 리소스가 있습니다.
- Serverfault : mod_rewrite에 대해 알고 싶었던 모든 것
( 사용을^/위해 패턴 접두사 에서 슬래시를 제거하십시오.htaccess.) - mod_rewrite의 숨겨진 기능 에서해야 할 일과하지 말아야 할 일 .
- 가장 인기있는 모드 재 작성 질문과 답변을 살펴보십시오 .
- Apache 리디렉션 및 리매핑 가이드.
- AskApache 궁극적 인 .htaccess 가이드
- 그리고 mod-rewrite 태그 위키는 .
신규 사용자 친화적 인 정규식 개요는 다음과 같습니다.
- 우리의 정규식 태그 위키 구문 개론합니다.
- 그리고 짧은 Apache regex 요약 .
- 이해하기 쉬운 기본 사항을위한 기타 regexp.info .
자주 사용되는 자리 표시 자
.*빈 문자열도 일치합니다. 모든 곳에서이 패턴을 사용하지 않고 마지막 대체 규칙에서 자주 사용합니다.[^/]+경로 세그먼트에 더 자주 사용됩니다. 슬래시를 제외한 모든 항목과 일치합니다.\d+숫자 문자열과 만 일치합니다.\w+영숫자 문자와 일치합니다. 기본적으로[A-Za-z0-9_].[\w\-]+"슬러그"스타일 경로 세그먼트의 경우 문자, 숫자, 대시-및_[\w\-.,]+마침표와 쉼표를 추가합니다. charclasses\-에서 이스케이프 된 대시를 선호합니다[…].\.문자 그대로 마침표를 나타냅니다. 그렇지 않으면.외부는[…]모든 기호에 대한 자리 표시 자입니다.
이러한 각 자리 표시자는 일반적 (…)으로 캡처 그룹 으로 괄호로 묶여 있습니다. 그리고 전체 패턴은 종종 ^………$시작 + 끝 마커에 있습니다. 인용 "패턴"은 선택 사항입니다.
RewriteRules
다음 예제는 PHP 중심이며 유사한 경우에 좀 더 점진적이고 쉽게 적용 할 수 있습니다. 그것들은 단지 요약 일 뿐이며 종종 더 많은 변형이나 자세한 Q & A로 연결됩니다.
정적 매핑
/contact,/about몇 가지 페이지 이름을 내부 파일 체계로 줄이는 것이 가장 간단합니다.
RewriteRule ^contact$ templ/contact.html RewriteRule ^about$ about.php숫자 식별자
/object/123http://example.com/article/531기존 PHP 스크립트 와 같은 단축키를 도입 하는 것도 쉽습니다. 숫자 자리 표시자는$_GET매개 변수에 다시 매핑 할 수 있습니다 .RewriteRule ^article/(\d+)$ article-show.php?id=$1 # └───────────────────────────┘슬러그 스타일 자리 표시 자
/article/with-some-title-slug/article/title-string자리 표시자를 허용하도록 해당 규칙을 쉽게 확장 할 수 있습니다 .RewriteRule ^article/([\w-]+)$ article-show.php?title=$1 # └────────────────────────────────┘참고 스크립트가 있어야 할 수 있습니다 (또는 적용 할 수) 다시 데이터베이스 식별자에 그 제목을 매핑 할 수 있습니다. RewriteRules만으로는 허공에서 정보를 생성하거나 추측 할 수 없습니다.
숫자 접두사가있는 슬러그
/readable/123-plus-title따라서
/article/529-title-slug실제로 사용되는 혼합 경로를 자주 볼 수 있습니다.RewriteRule ^article/(\d+)-([\w-]+)$ article.php?id=$1&title=$2 # └───────────────────────────────┘이제
title=$2스크립트는 일반적으로 어쨌든 데이터베이스 ID에 의존하기 때문에 어쨌든 전달을 건너 뛸 수 있습니다 . 는-title-slug임의의 URL 장식되었다.대체 목록과의 통일성
/foo/…/bar/…/baz/…여러 가상 페이지 경로에 대해 유사한 규칙이있는 경우
|대체 목록 과 일치시키고 압축 할 수 있습니다 . 그리고 다시 내부 GET 매개 변수에 다시 할당합니다.# ┌─────────────────────────┐ RewriteRule ^(blog|post|user)/(\w+)$ disp.php?type=$1&id=$2 # └───────────────────────────────────┘RewriteRule너무 복잡해지면 개별으로 분할 할 수 있습니다 .관련 URL을 다른 백엔드로 디스패치
/date/SWITCH/backend대체 목록의보다 실용적인 사용은 요청 경로를 개별 스크립트에 매핑하는 것입니다. 예를 들어 날짜를 기준으로 이전 및 최신 웹 응용 프로그램에 대해 균일 한 URL을 제공하려면 다음을 수행합니다.
# ┌─────────────────────────────┐ # │ ┌───────────┼───────────────┐ RewriteRule ^blog/(2009|2010|2011)/([\d-]+)/?$ old/blog.php?date=$2 RewriteRule ^blog/(\d+)/([\d-]+)/?$ modern/blog/index.php?start=$2 # └──────────────────────────────────────┘이것은 단순히 2009-2011 게시물을 하나의 스크립트에 다시 매핑하고 다른 모든 연도는 암시 적으로 다른 핸들러에 매핑합니다. 더 구체적인 규칙이 먼저 오는 것에 유의하십시오 . 각 스크립트는 다른 GET 매개 변수를 사용할 수 있습니다.
/경로 슬래시 이외의 다른 구분 기호
/user-123-name가상 디렉터리 구조를 시뮬레이션하기 위해 가장 일반적으로 RewriteRules가 표시됩니다. 그러나 당신은 창의적이지 않게 강요받지는 않습니다.
-세그먼트 화 또는 구조화에 하이픈을 사용할 수도 있습니다 .RewriteRule ^user-(\d+)$ show.php?what=user&id=$1 # └──────────────────────────────┘ # This could use `(\w+)` alternatively for user names instead of ids.또한 일반적인
/wiki:section:Page_Name계획의 경우 :RewriteRule ^wiki:(\w+):(\w+)$ wiki.php?sect=$1&page=$2 # └─────┼────────────────────┘ │ # └────────────────────────────┘경우에 따라-
/구분자:또는.동일한 규칙에서 번갈아 사용하는 것이 적합합니다 . 또는 두 개의 RewriteRules를 다시 사용하여 변형을 다른 스크립트에 매핑하십시오.선택적 후행
/슬래시
/dir=/dir/디렉토리 스타일 경로를 선택할 때 최종 경로를 사용하거나 사용하지 않고 연결할 수 있습니다. /
RewriteRule ^blog/([\w-]+)/?$ blog/show.php?id=$1 # ┗┛이제 이것은
http://example.com/blog/123및/blog/123/. 이/?$접근 방식은 다른 RewriteRule에 쉽게 추가 할 수 있습니다.가상 경로를위한 유연한 세그먼트
.*/.*/.*/.*만나게 될 대부분의 규칙은 제한된
/…/리소스 경로 세그먼트 집합 을 개별 GET 매개 변수에 매핑합니다 . 그러나 일부 스크립트 는 다양한 옵션을 처리합니다 . Apache regexp 엔진은 임의의 수를 선택적으로 허용하지 않습니다. 그러나 규칙 블록으로 쉽게 확장 할 수 있습니다.Rewriterule ^(\w+)/?$ in.php?a=$1 Rewriterule ^(\w+)/(\w+)/?$ in.php?a=$1&b=$2 Rewriterule ^(\w+)/(\w+)/(\w+)/?$ in.php?a=$1&b=$2&c=$3 # └─────┴─────┴───────────────────┴────┴────┘최대 5 개의 경로 세그먼트가 필요한 경우이 구성표를 5 개의 규칙에 복사합니다. 물론
[^/]+각각 더 구체적인 자리 표시자를 사용할 수 있습니다 . 여기서 순서는 겹치지 않기 때문에 중요하지 않습니다. 따라서 가장 자주 사용되는 경로를 먼저 갖는 것이 좋습니다.또는 스크립트가 사전 분할을 선호하는 경우 여기에서 쿼리 문자열을 통해 PHP 배열 매개 변수를 활용할 수 있습니다 . (포괄적 규칙을 사용하고 스크립트 자체가 REQUEST_URI에서 세그먼트를 확장하도록하는 것이 더 일반적이지만)
?p[]=$1&p[]=$2&p[]=3선택적 세그먼트
prefix/opt?/.*일반적인 변형은 규칙 내에 선택적 접두사를 포함 하는 것입니다. 이것은 일반적으로 정적 문자열이나 더 제한된 자리 표시자가있는 경우에 의미가 있습니다.
RewriteRule ^(\w+)(?:/([^/]+))?/(\w+)$ ?main=$1&opt=$2&suffix=$3이제 더 복잡한 패턴은
(?:/([^/])+)?단순히 비 캡처(?:…)그룹을 래핑하고 선택 사항으로 만듭니다)?. 포함 된 자리 표시자는([^/]+)대체 패턴$2이지만 중간/…/경로 가 없으면 비어 있습니다 .나머지 캡처
/prefix/123-capture/…/*/…whatever…앞서 말했듯이 너무 일반적인 재 작성 패턴을 원하지 않는 경우가 많습니다. 그러나
.*때로는 정적 및 특정 비교를 결합하는 것이 합리적 입니다.RewriteRule ^(specific)/prefix/(\d+)(/.*)?$ speci.php?id=$2&otherparams=$2이것은 모든
/…/…/…후행 경로 세그먼트를 선택적으로 지정했습니다 . 당연히 그것들을 분할하기위한 핸들링 스크립트와 추출 된 매개 변수 자체를 가변 화 해야합니다 ( 웹- "MVC" 프레임 워크가하는 일입니다).후행 파일 "확장자"
/old/path.HTMLURL에는 실제로 파일 확장자가 없습니다. 이것이 바로이 전체 참조에 관한 것입니다 (= URL은 가상 로케이터이며 반드시 직접 파일 시스템 이미지 일 필요는 없습니다). 그러나 이전에 1 : 1 파일 매핑이 있었다면 더 간단한 규칙을 만들 수 있습니다 .
RewriteRule ^styles/([\w\.\-]+)\.css$ sass-cache.php?old_fn_base=$1 RewriteRule ^images/([\w\.\-]+)\.gif$ png-converter.php?load_from=$2다른 일반적인 용도는 사용되지 않는
.html경로를 최신.php처리기 로 다시 매핑 하거나 개별 (실제 / 실제) 파일에 대해서만 디렉토리 이름을 별칭 지정하는 것입니다.탁구 (일제히 리디렉션 및 재 작성)
/ugly.html← →/pretty따라서 어떤 시점에서 deceze에서 설명한대로 예쁜 링크 만 전달하도록 HTML 페이지를 다시 작성합니다 . 한편 , 때로는 북마크에서도 이전 경로에 대한 요청을 계속받습니다 . 으로 해결 , 당신은 / 화면에 브라우저를 탁구 - 핑 새로운 URL을 설정할 수 있습니다.
이 일반적인 트릭은 들어오는 URL이 쓸모없고보기 흉한 이름 지정 체계를 따를 때마다 30x / 위치 리디렉션을 보내는 것 입니다. 브라우저 것이다 다음 rerequest 나중에 원본 또는 새 위치 (단지 내부적으로) 다시 작성하는 새 / 꽤 URL.
# redirect browser for old/ugly incoming paths RewriteRule ^old/teams\.html$ /teams [R=301,QSA,END] # internally remap already-pretty incoming request RewriteRule ^teams$ teams.php [QSA,END]이 예제 가 안전하게 대체 하는
[END]대신 사용하는 방법에 유의하십시오[L]. : 이전의 아파치 2.2 버전의 경우 외에 또한 예를 들어 쿼리 문자열 매개 변수를 매핑 다른 해결 방법을 사용할 수 있습니다 다시 매핑 다시 추한 경로로, 꽤 URL로 리디렉션 추한, 무한 루프없이를␣패턴의 공간
/this+that+브라우저 주소 표시 줄에서는 그다지 예쁘지 않지만 URL에는 공백을 사용할 수 있습니다. 재 작성 패턴의 경우 백 슬래시 이스케이프 처리 된
\␣공백을 사용 하십시오. 그렇지 않으면"전체 패턴 또는 대체를 인용하십시오.RewriteRule "^this [\w ]+/(.*)$" "index.php?id=$1" [L]클라이언트와 함께 URL을 직렬화
+또는%20스페이스. 그러나 RewriteRules에서는 모든 상대 경로 세그먼트에 대해 리터럴 문자로 해석됩니다.
잦은 중복 :
캐치 - 모두를위한 중앙 디스패처 / 프론트 컨트롤러 스크립트
RewriteCond %{REQUEST_URI} !-f RewriteCond %{REQUEST_URI} !-d RewriteRule ^.*$ index.php [L]PHP 프레임 워크 또는 WebCMS / 포털 스크립트에서 자주 사용됩니다. 실제 경로 분할은 PHP에서
$_SERVER["REQUEST_URI"]. 따라서 개념적으로는 "mod_rewrite 당"URL 처리와 거의 반대입니다. (FallBackResource대신 사용하십시오.)www.호스트 이름에서 제거이것은 쿼리 문자열 등을 복사하지 않습니다.
# ┌──────────┐ RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] │ RewriteRule ^(.*)$ http://%1/$1 [R=301,L] │ # ↓ └───┼────────────┘ # └───────────────┘참조 :
· .htaccess의 다른 프로토콜에 대한 URL 재 작성
· 일반 htaccess가 www를 www가 아닌 것으로 리디렉션
· .htaccess- "www"를 강제하는 방법 일반적인 방식으로?RewriteCond / RewriteRule 콤보는 더 복잡 할 수 있으며 일치 항목 (
%1및$1)이 양방향으로 상호 작용하더라도 다음과 같습니다.
Apache 설명서-mod_rewrite 소개 , Copyright 2015 The Apache Software Foundation, AL-2.0리디렉션
HTTPS://RewriteCond %{SERVER_PORT} 80 RewriteRule ^(.*)$ https://example.com/$1 [R,L]PHP 확장 "제거"
RewriteCond %{REQUEST_FILENAME}.php -f RewriteRule ^(.+)$ $1.php [L] # or [END]이전 .html 경로를 .php 스크립트로 별칭 지정
참조 : http://httpd.apache.org/docs/2.4/rewrite/remapping.html#backward-compatibility
"/ page"와 같은 URL에서 "/index.php/page"와 같은 스크립트로 재 작성
mod_rewrite, php 및 .htaccess 파일을 참조하십시오.
하위 도메인을 폴더로 리디렉션
널리 퍼진 .htaccess함정
이제 이것을 소금 한 알로 가져 가십시오. 모든 조언이 모든 상황에 일반화 될 수있는 것은 아닙니다. 이것은 잘 알려져 있고 몇 가지 분명하지 않은 걸림돌에 대한 간단한 요약입니다.
활성화
mod_rewrite및.htaccess디렉터리 별 구성 파일에서 RewriteRules를 실제로 사용하려면 다음을 수행해야합니다.
서버가
AllowOverride All활성화 되었는지 확인하십시오 . 그렇지 않으면 디렉토리 별.htaccess지시문이 무시되고 RewriteRules가 작동하지 않습니다.분명히 했습니다
mod_rewrite활성화 당신의httpd.conf모듈 섹션.각 규칙 목록 앞에
RewriteEngine On스틸을 추가하십시오 . mod_rewrite는<VirtualHost>및<Directory>섹션 에서 암시 적으로 활성화되어 있지만 디렉토리 별.htaccess파일은 개별적으로 호출해야합니다.
선행 슬래시
^/는 일치하지 않습니다.다음
.htaccess과 같이 RewriteRule 패턴을 시작하면 안됩니다^/.RewriteRule ^/article/\d+$ … ↑이것은 종종 오래된 튜토리얼에서 볼 수 있습니다. 그리고 그것은 고대 Apache 1.x 버전에 맞았습니다. 요즘 요청 경로는 RewriteRules 에서 편리 하게 완전히 디렉토리에 상대적 입니다
.htaccess. 리드는 그대로 두십시오/.·
<VirtualHost>섹션 에서 선행 슬래시는 여전히 정확 합니다. 그렇기 때문에^/?규칙 패리티를 위해 종종 선택적으로 표시됩니다 .
· 또는를 사용할 때RewriteCond %{REQUEST_URI}여전히 선행/.
· Webmaster.SE 참조 : mod_rewrite 패턴에 선행 슬래시 (/)가 필요한 경우는 언제입니까?<IfModule *>래퍼가 시작되었습니다!많은 예에서 이것을 보셨을 것입니다.
<IfModule mod_rewrite.c> Rewrite… </IfModule>- 그것은 수행 에서 메이크업 감각
<VirtualHost>섹션 -이 같은 ScriptAliasMatch 같은 다른 대체 옵션과 결합 된 경우. (하지만 아무도 그렇게하지 않습니다). - 그리고
.htaccess많은 오픈 소스 프로젝트가있는 기본 규칙 세트에 대해 일반적으로 배포됩니다 . 그것은 단지 폴백을 의미하며 "추악한"URL이 기본값으로 작동하도록 유지합니다.
그러나 일반적으로 자신의 파일 에는 원하지 않습니다
.htaccess.- 첫째, mod_rewrite는 임의로 해제되지 않습니다. (그렇다면 더 큰 문제가있을 것입니다).
- 실제로 비활성화 되어도 RewriteRules는 여전히 작동하지 않습니다.
- 이는 HTTP
500오류 를 방지하기위한 것 입니다. 일반적으로 수행하는 것은 사용자에게 HTTP404오류를 대신하는 것입니다. ( 생각하면 그다지 사용자 친화적이지 않습니다.) - 실제로는 더 유용한 로그 항목 또는 서버 알림 메일을 억제합니다. 당신은 없을 거라고 아무도 현명를 당신의 RewriteRules가 작동하지 않을 이유에.
일반화 된 보호 장치로서 매력적으로 보이는 것은 종종 실제로 장애물로 판명됩니다.
- 그것은 수행 에서 메이크업 감각
RewriteBase필요 하지 않으면 사용 하지 마십시오많은 복사 + 붙여 넣기 예제에는
RewriteBase /지시문이 포함되어 있습니다 . 어쨌든 암시 적 기본값이됩니다. 따라서 실제로 이것이 필요하지 않습니다. 멋진 VirtualHost 재 작성 체계에 대한 해결 방법이며 일부 공유 호스팅 업체에 대해 잘못된 DOCUMENT_ROOT 경로를 추측합니다.더 깊은 하위 디렉터리에서 개별 웹 응용 프로그램과 함께 사용하는 것이 좋습니다. 이러한 경우 RewriteRule 패턴을 줄일 수 있습니다. 일반적으로 디렉토리 별 규칙 세트에서 상대 경로 지정자를 선호하는 것이 가장 좋습니다.
.htaccess에서 RewriteBase가 작동하는 방법 도 참조하십시오.
MultiViews가상 경로가 겹칠 때 비활성화URL 재 작성은 주로 가상 수신 경로 를 지원하는 데 사용됩니다 . 일반적으로 당신은 단지 하나의 디스패처 스크립트 (가
index.php) 또는 몇 개인 핸들러 (articles.php,blog.php,wiki.php, ...). 후자 는 유사한 가상 RewriteRule 경로와 충돌 할 수 있습니다 ./article/123예를 들어 에 대한 요청은 암시 적article.php으로/123PATH_INFO로 매핑 될 수 있습니다 . 그런 다음 commonplaceRewriteCond!-f+ 를 사용하여 규칙을 보호!-d하거나 PATH_INFO 지원을 비활성화하거나Options -MultiViews.그렇다고 항상 해야한다는 말은 아닙니다 . 콘텐츠 협상은 가상 리소스에 대한 자동화 일뿐입니다.
주문이 중요합니다
mod_rewrite에 대해 알고 싶었던 모든 것을 아직 보지 않았다면 참조하십시오 . 여러 RewriteRules를 결합하면 종종 상호 작용이 발생합니다. 이것은
[L]깃발 마다 습관적으로 예방 하는 것이 아니라 일단 숙달되면 받아 들일 계획입니다. 실제 대상 처리기에 도달 할 때까지 한 규칙에서 다른 규칙으로 가상 경로를 다시 쓸 수 있습니다 .그럼에도 불구하고 당신은 것입니다 종종 가장 구체적인 규칙 (고정 문자열이 원하는
/forum/…패턴, 또는 더 제한적인 자리[^/.]+에서) 초기 규칙을. 일반적인 slurp-all 규칙 (.*)은 나중 규칙에 남겨 두는 것이 좋습니다 . (예외는RewriteCond -f/-d기본 블록으로서의 가드입니다.)스타일 시트와 이미지가 작동하지 않습니다.
가상 디렉터리 구조를 도입하면
/blog/article/123HTML의 상대 리소스 참조 (예 :)에 영향을줍니다<img src=mouse.png>. 다음으로 해결할 수 있습니다.- 서버 절대 참조 만 사용
href="/old.html"하거나src="/logo.png" - 종종
<base href="/index">HTML<head>섹션 에 추가 하기 만하면됩니다 . 이것은 그들이 이전에 있었던 것에 대한 상대 참조를 암시 적으로 리 바인드합니다.
.css또는.png원래 위치에 대한 경로를 리 바인드하기 위해 추가 RewriteRule을 만들 수 있습니다. 그러나 이는 불필요하거나 추가 리디렉션을 발생시키고 캐싱을 방해합니다.- 서버 절대 참조 만 사용
RewriteConds는 하나의 RewriteRule을 마스크합니다.
일반적인 잘못된 인터 페팅은 RewriteCond가 여러 RewriteRules를 차단한다는 것입니다 (시각적으로 함께 정렬되어 있기 때문).
RewriteCond %{SERVER_NAME} localhost RewriteRule ^secret admin/tools.php RewriteRule ^hidden sqladmin.cgi기본값이 아닙니다. 당신은 할 수 있습니다 그들을 체인 은 Using
[S=2]플래그. 그렇지 않으면 반복해야합니다. 때때로 "반전 된"기본 규칙을 만들어 재 작성 처리를 일찍 [END] 할 수 있습니다.RewriteRules에서 QUERY_STRING 제외
RewriteRule index.php\?x=ymod_rewrite는 기본 당 상대 경로와 비교하기 때문에 일치 할 수 없습니다 . 그러나 다음을 통해 개별적으로 일치시킬 수 있습니다.RewriteCond %{QUERY_STRING} \b(?:param)=([^&]+)(?:&|$) RewriteRule ^add/(.+)$ add/%1/$1 # ←──﹪₁──┘.htaccess대<VirtualHost>디렉터리 별 구성 파일에서 RewriteRules를 사용하는 경우 정규식 성능에 대한 걱정은 무의미합니다. Apache는 공통 라우팅 프레임 워크를 사용하는 PHP 프로세스보다 컴파일 된 PCRE 패턴을 더 오래 유지합니다. 트래픽이 많은 사이트의 경우 전투 테스트를 마치면 규칙 세트를 가상 호스트 서버 구성으로 이동하는 것을 고려해야합니다.
이 경우 선택적
^/?디렉터리 구분 기호 접두사를 선호합니다 . 이를 통해 PerDir 및 서버 구성 파일간에 RewriteRules를 자유롭게 이동할 수 있습니다.무언가 가 작동하지 않을 때마다
걱정하지 마십시오.
비교
access.log하고error.log종종 RewriteRule이
error.log및access.log. 액세스 시간을 상관시켜 원래 들어온 요청 경로와 Apache가 해결할 수없는 경로 / 파일 (오류 404/500)을 확인합니다.이것은 어떤 RewriteRule이 범인인지 알려주지 않습니다. 그러나 액세스 할 수없는 최종 경로
/docroot/21-.itle?index.php는 추가 검사 위치를 제공 할 수 있습니다. 그렇지 않으면 예측 가능한 경로를 얻을 때까지 규칙을 비활성화하십시오.RewriteLog 활성화
Apache RewriteLog 문서를 참조하십시오 . 디버깅을 위해 가상 호스트 섹션에서 활성화 할 수 있습니다.
# Apache 2.2 RewriteLogLevel 5 RewriteLog /tmp/rewrite.log # Apache 2.4 LogLevel alert rewrite:trace5 #ErrorLog /tmp/rewrite.log그러면 들어오는 요청 경로가 각 규칙에 따라 어떻게 수정되는지에 대한 자세한 요약이 생성됩니다.
[..] applying pattern '^test_.*$' to uri 'index.php' [..] strip per-dir prefix: /srv/www/vhosts/hc-profi/index.php -> index.php [..] applying pattern '^index\.php$' to uri 'index.php'지나치게 일반적인 규칙과 정규식 사고를 좁히는 데 도움이됩니다.
참고 :
· .htaccess가 작동하지 않음 (mod_rewrite)
· .htaccess 재 작성 규칙 디버깅을위한 팁자신의 질문을하기 전에
아시다시피 Stack Overflow는 mod_rewrite에 대한 질문에 매우 적합합니다. 이전 연구 및 시도 (중복 답변 방지)를 포함하여 주제 에 맞게 만들고 기본 정규식 이해를 보여주고 다음을 수행합니다.
- 포함 전체 입력 된 URL의 예, falsly 다시 대상 경로, 실제 디렉토리 구조를.
- 완전한 RewriteRule 세트이지만, 결함이 있다고 추정되는 것도 골라냅니다.
- Apache 및 PHP 버전, OS 유형, 파일 시스템, DOCUMENT_ROOT 및 PHP
$_SERVER환경 (매개 변수 불일치에 관한 경우) - 기존 규칙이 해결 된 내용을 확인하기 위해
access.log및 에서 발췌 한 내용입니다error.log. 더 나은 방법은rewrite.log요약입니다.
이것은 더 빠르고 정확한 답변을 제공하고 다른 사람들에게 더 유용하게 만듭니다.
댓글
.htaccess어딘가에서 예제를 복사하는 경우
# comment and origin link. 귀인을 생략하는 것은 매너 일 뿐이지 만 나중에 유지 관리에 큰 타격을줍니다. 코드 또는 튜토리얼 소스를 문서화하십시오. 특히 익숙하지 않은 동안 당신은 그들을 마법의 블랙 박스처럼 취급하지 않는 데 더욱 관심을 가져야합니다."SEO"-URL이 아닙니다.
면책 조항 : 그냥 애완 동물 오싹함. "SEO"링크 또는 기타라고하는 예쁜 URL 재 작성 체계를 자주 듣습니다. 이것은 인터넷 검색 예제에 유용하지만 날짜가 잘못된 이름입니다.
현대적인 검색 엔진의 아무도는 정말 방해하지 않습니다
.html및.php패스 세그먼트 (segment), 또는에서?id=123그 문제에 대한 쿼리 문자열. 같은 알타 비스타 등 기존의 검색 엔진은, 한 잠재적 ambigious 액세스 경로로 웹 사이트 크롤링을 피합니다. 최신 크롤러는 종종 딥 웹 리소스를 갈망합니다.개념적으로 "예쁜"URL을 사용해야하는 것은 웹 사이트를 사용자 친화적으로 만드는 것 입니다.
- 읽기 쉽고 명확한 리소스 체계가 있습니다.
- URL이 오래 지속되도록합니다 (일명 영구 링크 ).
- 을 통해 검색 기능을 제공
/common/tree/nesting.
그러나 적합성에 대한 고유 한 요구 사항을 희생하지 마십시오.
도구
대부분의 GET 매개 변수 URL에 대해 RewriteRules를 생성하는 다양한 온라인 도구가 있습니다.
- http://www.generateit.net/mod-rewrite/index.php
- http://www.ipdistance.com/mod_rewrite.php
- http://webtools.live2support.com/misc_rewrite.php
대부분 [^/]+일반 자리 표시 자만 출력 하지만 사소한 사이트에는 충분합니다.
mod_rewrite의 대안
RewriteRules를 사용하지 않고도 많은 기본 가상 URL 체계를 얻을 수 있습니다. Apache를 사용하면 .php확장 없이 가상 PATH_INFO인수를 사용하여 PHP 스크립트를 호출 할 수 있습니다 .
PATH_INFO 사용 , Luke
요즘
AcceptPathInfo On은 종종 기본적으로 활성화되어 있습니다. 기본적으로.php및 기타 리소스 URL이 가상 인수를 전달하도록 허용 합니다.http://example.com/script.php/virtual/path이제
/virtual/pathPHP에서$_SERVER["PATH_INFO"]원하는대로 추가 인수를 처리 할 수 있습니다.이것에 아파치 별도의 입력 경로 세그먼트를 구비 한 편리하지
$1,$2,$3별개로 전달$_GETPHP하는 변수. 적은 구성 노력으로 "예쁜 URL"을 에뮬레이트하는 것입니다.MultiViews 를 활성화 하여
.php확장 기능 숨기기.phpURL에서 "파일 확장자"를 피하는 가장 간단한 옵션 은 다음을 활성화하는 것입니다.Options +MultiViews이것은 일치하는 basename으로 인해
article.phpHTTP 요청에 대해 Apache를 선택 합니다/article. 그리고 이것은 앞서 언급 한 PATH_INFO 기능과 함께 잘 작동합니다. 따라서http://example.com/article/virtual/title. 여러 PHP 호출 지점 / 스크립트가있는 기존 웹 애플리케이션이있는 경우 의미가 있습니다.MultiView는 다른 / 광범위한 목적을 가지고 있습니다. Apache는 항상 기본 이름이 일치하는 다른 파일을 찾기 때문에 매우 사소한 성능 저하 가 발생합니다 . 그것은 실제로 의미있어 내용 협상 브라우저 (예 : 가용 자원 중 가장 좋은 대안을받을 수 있도록,
article.en.php,article.fr.php,article.jp.mp4).확장없는
.php스크립트를 위한 SetType 또는 SetHandler.phpURL에서 접미사 를 사용하지 않기위한보다 직접적인 접근 방식 은 다른 파일 체계에 대해 PHP 처리기 를 구성하는 것 입니다. 가장 간단한 옵션은.htaccess다음을 통해 기본 MIME / 핸들러 유형을 재정의하는 것입니다 .DefaultType application/x-httpd-php이렇게하면
article.php스크립트 이름article을 확장명없이 그냥 이름으로 바꿀 수 있지만 여전히 PHP 스크립트로 처리 할 수 있습니다.이제 확장이없는 모든 파일이 이제 PHP를 통해 파이프되기 때문에 보안 및 성능에 영향을 미칠 수 있습니다. 따라서 개별 파일에 대해서만이 동작을 설정할 수 있습니다.
<Files article> SetHandler application/x-httpd-php # or SetType </Files>이것은 서버 설정과 사용 된 PHP SAPI에 따라 다소 다릅니다. 일반적인 대안으로는
ForceType application/x-httpd-php또는AddHandler php5-script.이러한 설정은 하나
.htaccess에서 하위 폴더로 전파됩니다 . 당신은 항상 스크립트 실행 (사용하지 않아야SetHandler None하고Options -Exec또는php_flag engine off정적 자원 등), 업로드 / 디렉토리 등기타 Apache 재 작성 체계
많은 옵션 중에서 Apache는 RewriteRules
mod_alias만큼 잘 작동하는 기능을 제공 합니다mod_rewrite. 대부분은<VirtualHost>디렉토리 별.htaccess구성 파일이 아닌 섹션 에서 설정해야 합니다.ScriptAliasMatch주로 CGI 스크립트 용이지만 PHP에서도 작동해야합니다. 모든RewriteRule. 실제로 포괄 전면 컨트롤러를 구성하는 가장 강력한 옵션 일 것입니다.그리고 일반
Alias은 몇 가지 간단한 재 작성 체계에도 도움이됩니다.단순한
ErrorDocument지시어 조차도 PHP 스크립트가 가상 경로를 처리하도록 할 수 있습니다. 그러나 이것은 복잡한 해결 방법이며 GET 요청 이외의 것을 금지하고 정의에 따라 error.log를 플러딩합니다.
추가 팁 은 http://httpd.apache.org/docs/2.2/urlmapping.html 을 참조 하십시오 .