mod_rewrite의 숨겨진 기능
mod_rewrite요즘 스레드의 특정 측면이 어떻게 작동하는지에 대한 약간의 혼란으로 인해 떠 다니는 상당한 수의 스레드가있는 것 같습니다 . 결과적으로 일반적인 기능에 대한 몇 가지 메모와 몇 가지 성가신 뉘앙스를 편집했습니다.
다른 어떤 기능 / 공통 문제를 사용하여 실행 mod_rewrite했습니까?
mod_rewrite 규칙을 배치 할 위치
mod_rewrite규칙은 httpd.conf파일 또는 파일 내에 배치 될 수 있습니다 .htaccess. 에 액세스 할 수있는 경우 httpd.conf여기에 규칙을 배치하면 .htaccess파일이 호출 될 때마다 규칙이 한 번 처리되므로 성능 이점이 제공됩니다 .
mod_rewrite 요청 로깅
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=$1Apache 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있지만 위와 같이 기본 리디렉션을 처리하는 것보다 더 많은 작업이 필요합니다.Context affects syntax
Within
.htaccessfiles, a leading slash is not used in the RewriteRule pattern:# 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] is not last! (sometimes)
The
[L]flag stops processing any further rewrite rules for that pass through the rule set. However, if the URL was modified in that pass and you're in the.htaccesscontext or the<Directory>section, then your modified request is going to be passed back through the URL parsing engine again. And on the next pass, it may match a different rule this time. If you don't understand this, it often looks like your[L]flag had no effect.# processing does not stop here RewriteRule ^dirA$ /dirB [L] # /dirC will be the final result RewriteRule ^dirB$ /dirCOur rewrite log shows that the rules are run twice and the URL is updated twice:
rewrite 'dirA' -> '/dirB' internal redirect with /dirB [INTERNAL REDIRECT] rewrite 'dirB' -> '/dirC'The best way around this is to use the
[END]flag (see Apache docs) instead of the[L]flag, if you truly want to stop all further processing of rules (and subsequent passes). However, the[END]flag is only available for Apache v2.3.9+, so if you have v2.2 or lower, you're stuck with just the[L]flag.For earlier versions, you must rely on
RewriteCondstatements to prevent matching of rules on subsequent passes of the URL parsing engine.# Only process the following RewriteRule if on the first pass RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule ...Or you must ensure that your RewriteRule's are in a context (i.e.
httpd.conf) that will not cause your request to be re-parsed.
if you need to 'block' internal redirects / rewrites from happening in the .htaccess, take a look at the
RewriteCond %{ENV:REDIRECT_STATUS} ^$
condition, as discussed here.
The deal with RewriteBase:
You almost always need to set RewriteBase. If you don't, apache guesses that your base is the physical disk path to your directory. So start with this:
RewriteBase /
Other Pitfalls:
1- Sometimes it's a good idea to disable MultiViews
Options -MultiViews
I'm not well verse on all of MultiViews capabilities, but I know that it messes up my mod_rewrite rules when active, because one of its properties is to try and 'guess' an extension to a file that it thinks I'm looking for.
I'll explain: Suppose you have 2 php files in your web dir, file1.php and file2.php and you add these conditions and rule to your .htaccess :
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ file1.php/$1
You assume that all urls that do not match a file or a directory will be grabbed by file1.php. Surprise! This rule is not being honored for the url http://myhost/file2/somepath. Instead you're taken inside file2.php.
What's going on is that MultiViews automagically guessed that the url that you actually wanted was http://myhost/file2.php/somepath and gladly took you there.
Now, you have no clue what just happened and you're at that point questioning everything that you thought you knew about mod_rewrite. You then start playing around with rules to try to make sense of the logic behind this new situation, but the more you're testing the less sense it makes.
Ok, In short if you want mod_rewrite to work in a way that approximates logic, turning off MultiViews is a step in the right direction.
2- enable FollowSymlinks
Options +FollowSymLinks
That one, I don't really know the details of, but I've seen it mentioned many times, so just do it.
Equation can be done with following example:
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]
Dynamic Load Balancing:
If you use the mod_proxy to balance your system, it's possible to add a dynamic range of worker server.
RewriteCond %{HTTP_COOKIE} ^.*stickysession=route\.server([0-9]{1,2}).*$ [NC]
RewriteRule (.*) https://worker%1.internal.com/$1 [P,L]
A better understanding of the [L] flag is in order. The [L] flag is last, you just have to understand what will cause your request to be routed through the URL parsing engine again. From the docs (http://httpd.apache.org/docs/2.2/rewrite/flags.html#flag_l) (emphasis mine):
The [L] flag causes mod_rewrite to stop processing the rule set. In most contexts, this means that if the rule matches, no further rules will be processed. This corresponds to the last command in Perl, or the break command in C. Use this flag to indicate that the current rule should be applied immediately without considering further rules.
If you are using RewriteRule in either .htaccess files or in
<Directory>sections, it is important to have some understanding of how the rules are processed. The simplified form of this is that once the rules have been processed, the rewritten request is handed back to the URL parsing engine to do what it may with it. It is possible that as the rewritten request is handled, the .htaccess file or<Directory>section may be encountered again, and thus the ruleset may be run again from the start. Most commonly this will happen if one of the rules causes a redirect - either internal or external - causing the request process to start over.
So the [L] flag does stop processing any further rewrite rules for that pass through the rule set. However, if your rule marked with [L] modified the request, and you're in the .htaccess context or the <Directory> section, then your modifed request is going to be passed back through the URL parsing engine again. And on the next pass, it may match a different rule this time. If you don't understand what happened, it looks like your first rewrite rule with the [L] flag had no effect.
The best way around this is to use the [END] flag (http://httpd.apache.org/docs/current/rewrite/flags.html#flag_end) instead of the [L] flag, if you truly want to stop all further processing of rules (and subsequent reparsing). However, the [END] flag is only available for Apache v2.3.9+, so if you have v2.2 or lower, you're stuck with just the [L] flag. In this case, you must rely on RewriteCond statements to prevent matching of rules on subsequent passes of the URL parsing engine. Or you must ensure that your RewriteRule's are in a context (i.e. httpd.conf) that will not cause your request to be re-parsed.
Another great feature are rewrite-map-expansions. They're especially useful if you have a massive amout of hosts / rewrites to handle:
They are like a key-value-replacement:
RewriteMap examplemap txt:/path/to/file/map.txt
Then you can use a mapping in your rules like:
RewriteRule ^/ex/(.*) ${examplemap:$1}
More information on this topic can be found here:
http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#mapfunc
mod_rewrite can modify aspects of request handling without altering the URL, e.g. setting environment variables, setting cookies, etc. This is incredibly useful.
Conditionally set an environment variable:
RewriteCond %{HTTP_COOKIE} myCookie=(a|b) [NC]
RewriteRule .* - [E=MY_ENV_VAR:%b]
Return a 503 response: RewriteRule's [R] flag can take a non-3xx value and return a non-redirecting response, e.g. for managed downtime/maintenance:
RewriteRule .* - [R=503,L]
will return a 503 response (not a redirect per se).
Also, mod_rewrite can act like a super-powered interface to mod_proxy, so you can do this instead of writing ProxyPass directives:
RewriteRule ^/(.*)$ balancer://cluster%{REQUEST_URI} [P,QSA,L]
Opinion: Using RewriteRules and RewriteConds to route requests to different applications or load balancers based on virtually any conceivable aspect of the request is just immensely powerful. Controlling requests on their way to the backend, and being able to modify the responses on their way back out, makes mod_rewrite the ideal place to centralize all routing-related config.
Take the time to learn it, it's well worth it! :)
참고URL : https://stackoverflow.com/questions/286004/hidden-features-of-mod-rewrite
'Programing' 카테고리의 다른 글
| io.Reader에서 Go의 문자열로 (0) | 2020.07.15 |
|---|---|
| 단검 2 하위 구성 요소 및 구성 요소 종속성 (0) | 2020.07.15 |
| R의 전역 및 지역 변수 (0) | 2020.07.15 |
| 안드로이드에서 svg를 사용하는 가장 쉬운 방법은 무엇입니까? (0) | 2020.07.15 |
| Windows 10으로 업데이트 한 후 TortoiseSVN 아이콘이 표시되지 않음 (0) | 2020.07.15 |