관리 메뉴

I LOVE EJ

php 쿼리 날리는 법 본문

Web Development/PHP

php 쿼리 날리는 법

BeOne 2007. 10. 29. 14:35
[PHP] URI 파라메터 전달 방법과 환경변수 비교

- 작성자 : 김칠봉 <san2(at)linuxchannel.net>
- 작성일 : 2003-06-27
- 내 용 : PHP URI 파라메터 전달 방법과 그 사용법
- 수 준 : 초보용
- 키워드 : PATH_INFO, SCRIPT_NAME, PHP_SELF, PATH_TRANSLATED

*주)
이 문서에 대한 최신 내용은 아래 URL에서 확인할 수 있습니다.

http://www.linuxchannel.net/docs/php-parameter.txt

---------------------------------------------------------
목차
1. PHP extension를 이용한 방법
2. PHP 확장자를 없애고 사용하는 방법
3. 사용 가능한 PHP 변수 비교(표)
4. 응용(실제 적용가능한 방법)
4-1. 아파치 RedirectMatch 에 이용
4-2. 아파치 ErrorDocument 에 이용
4-3. 가상의 파일이름 이용
5. 후기
---------------------------------------------------------

파일 이름이 `foo.php' 이라고 가정.

1. PHP extension(이하 '확장자')를 이용한 방법

1) foo.php?id=abc&n=1
2) foo.php/?id=abc&n=1
3) foo.php/id=abc&n=1
4) foo.php/id=abc/n=1
5) foo.php/abc/1
6) foo.php/?id=abc&n=1&/s.ext
7) foo.php/?id=abc&/&n=1
8) foo.php?id=abc&/&n=1
9) foo.php/a/b/?id=abc&n=1
10) 그외 조합 가능


1)번은 가장 많이 사용하는(표준적인) 방법
2)번은 특이하게 1)번에 '/'가 붙은 방법으로 이것도 가능함
3)번은 2)번에서 쿼리(?)를 없애는 방법이며 대신 $_GET[id]와 같은
방법으로 값을 가져올 수 없음
4)번은 3번의 '&'대신 '/'을 이용한 방법
5)번은 각각 순서대로 그 값을 할당하는 방법
6)번은 2번과 4번을 조합한 방법으로 제일 뒤는 가상의 파일이름임
7)번은 6번과 거의 같지만 $_GET 변수를 사용하기 위해서 변형된 형태
8)번은 7번과 같은 형태로 제일 앞의 '/'를 제거한 형태
9)번은 5번과 1번의 조합


2. PHP 확장자를 없애고 사용하는 방법

1) foo?id=abc&n=1
2) foo/?id=abc&n=1
3) foo/id=abc&n=1
4) foo/id=abc/n=1
5) foo/abc/1
6) foo/?id=abc&n=1&/s.ext
7) foo/?id=abc&/&n=1
8) foo?id=abc&/&n=1
9) foo/a/b/?id=abc&n=1
10) 그외 조합 가능


상위의 1번 방법과 거의 동일하며 다만 확장자만 없을 뿐임.
(이런식으로도 가능하며, foo 디렉토리와 서로 구별되어야 함)


3. 사용 가능한 PHP 변수 비교

<PRE>
+----------------------------+----+--------------+------------+------------+
|REQUEST_URI |id |PHP_SELF |PATH_INFO |SCRIPT_NAME |
+----------------------------+----+--------------+------------+------------|
|/foo.php?id=abc&n=1 |abc |/foo.php |NA |/foo.php |
+----------------------------+----+--------------+------------+------------|
|/foo.php/?id=abc&n=1 |abc |/foo.php/ |/ |/foo.php |
+----------------------------+----+--------------+------------+------------|
|/foo.php/id=abc&n=1 |NA |REQUEST_URI |/id=abc&n=1 |/foo.php |
+----------------------------+----+--------------+------------+------------|
|/foo.php/id=abc/n=1 |NA |REQUEST_URI |/id=abc/n=1 |/foo.php |
+----------------------------+----+--------------+------------+------------|
|/foo.php/abc/1 |NA |REQUEST_URI |/abc/1 |/foo.php |
+----------------------------+----+--------------+------------+------------|
|/foo.php/?id=abc&n=1&/s.ext |abc |/foo.php/ |/ |/foo.php |
+----------------------------+----+--------------+------------+------------|
|/foo.php/?id=abc&/&n=1 |abc |/foo.php/ |/ |/foo.php |
+----------------------------+----+--------------+------------+------------|
|/foo.php?id=abc&/&n=1 |abc |/foo.php |NA |/foo.php |
+----------------------------+----+--------------+------------+------------|
|/foo.php/a/b/?id=abc&n=1 |abc |/foo.php/a/b/ |/a/b/ |/foo.php |
+----------------------------+----+--------------+------------+------------+

+----------------------------+----+--------------+------------+------------|
|REQUEST_URI |id |PHP_SELF |PATH_INFO |SCRIPT_NAME |
+----------------------------+----+--------------+------------+------------|
|/foo?id=abc&n=1 |abc |/foo |NA |/foo |
+----------------------------+----+--------------+------------+------------|
|/foo/?id=abc&n=1 |abc |/foo/ |/ |/foo |
+----------------------------+----+--------------+------------+------------|
|/foo/id=abc&n=1 |NA |REQUEST_URI |/id=abc&n=1 |/foo |
+----------------------------+----+--------------+------------+------------|
|/foo/id=abc/n=1 |NA |REQUEST_URI |/id=abc/n=1 |/foo |
+----------------------------+----+--------------+------------+------------|
|/foo/abc/1 |NA |REQUEST_URI |/abc/1 |/foo |
+----------------------------+----+--------------+------------+------------|
|/foo/?id=abc&n=1&/s.ext |abc |/foo/ |/ |/foo |
+----------------------------+----+--------------+------------+------------|
|/foo/?id=abc&/&n=1 |abc |/foo/ |/ |/foo |
+----------------------------+----+--------------+------------+------------|
|/foo?id=abc&/&n=1 |abc |/foo |NA |/foo |
+----------------------------+----+--------------+------------+------------|
|/foo/a/b/?id=abc&n=1 |abc |/foo/a/b/ |/a/b/ |/foo |
+----------------------------+----+--------------+------------+------------+
(악... 이것 그리는데 시간이...T.T)
</PRE>

*참고)
- 제일 기본이 되는 환경변수는 DOCUMENT_ROOT 와 SCRIPT_FILENAME 임
- DOCUMENT_ROOT = DocumentRoot 의 설정값(httpd.conf)
- SCRIPT_FILENAME = 실제 실행 파일의 절대 경로(제일 정확한 값)

*결과)
- QUERY_STRING 은 REQUEST_URI 에서 첫번째 '?' 다음의 모든 문자열
- PHP_SELF 은 REQUEST_URI 에서 QUERY_STRING 문자열을 제외한 나머지
- PATH_INFO 는 PHP_SELF 에서 두번째 '/' 부터 나머지 문자열
- SCRIPT_NAME 는 PHP_SELF 에서 PATH_INFO 를 뺀 앞부분 문자열
(즉 REQUEST_URI 에서 '?'와 '/' 다음에 오는 모든 문자열을 제외한 나머지)
- PATH_TRANSLATED = PATH_INFO ? DOCUMENT_ROOT + PATH_INFO : SCRIPT_FILENAME
(PATH_INFO 값이 있다면 DOCUMENT_ROOT 와 PATH_INFO 의 결합,
그 외는 SCRIPT_FILENAME)

<주의 >
아파치 Action 지시자가 적용될 경우 약간 까다로움.

설정예: Action text/plain /bin/action.php
요청예: /test.txt?str=string

결과(SCRIPT_NAME 이 기준)
DOCUMENT_ROOT => /www
SCRIPT_FILENAME => /www/bin/action.php <-- 주의
SCRIPT_NAME => /bin/action.php <-- Action 지시자에서 설정값
QUERY_STRING => str=string
PHP_SELF => /bin/action.php/test.txt <-- SCRIPT_NAME 이 앞에 붙음
PATH_INFO => /test.txt <-- PHP_SELF 로 착각하기 쉬움
PATH_TRANSLATED => /www/test.txt
</주의 >



*환경변수 얻는 순서)
<PRE>
[DOCUMENT_ROOT]---+
| |
[REQUEST_URI] ----+
| |
| [SCRIPT_FILENAME]
|
|--(? 이하 축출)-----------> [QUERY_STRING]
|
`--(QUERY_STRING 제거)-----> [PHP_SELF]
|
[PATH_INFO] <---(/ 이하 축출)----+
|
[SCRIPT_NAME] <--(PATH_INFO 제거)--+
</PRE>


4. 응용(실제 적용가능한 방법)

4-1. 아파치 RedirectMatch 에 이용

RedirectMatch ^/([^./]+)$ /check.php?id=$1

이 설정의도는

/abc ---> /check.php?id=abc (redirect 의도)
/ccc ---> /check.php?id=ccc (redirect 의도)
/abc/ ---> /abc/
/abc.php ---> /abc.php

이와 같은 결과가 되도록 설정했지만 애석하게도 제대로 Redirect
되지 않습니다.
이유는 아파치의 Redirect 는 ? 문자가 인코딩(%3f)되어 넘어가기
때문에 PHP 파일에서는 요청쿼리로 해석하지 않고 완전한 하나의
파일로 인식하기 때문입니다.

실제로 첫번째 redirect 결과는

/abc ---> /check.php%3fid=abc (redirect 의도 실패)

이렇게 넘어가서 404 에러를 내게 됩니다.

해결방법은 ?(쿼리)를 사용하지 않고 PATH_INFO 환경변수가 생기도록
다음과 같은 방법을 사용하는것이 좋습니다.

권장설정)

RedirectMatch ^/([^./]+)$ /check.php/id=$1
or
RedirectMatch ^/([^./]+)$ /check.php/$1
or
RedirectMatch ^/([^./]+)$ /check/id=$1
or
RedirectMatch ^/([^./]+)$ /check/$1


4-2. 아파치 ErrorDocument 에 이용

위에서 그 개념을 이해했다면 ErrorDocument 도 하나의 파일에서 모두 관리할
수 있습니다.

1)일반적인 방법
ErrorDocument 401 /error.php
ErrorDocument 403 /error.php
ErrorDocument 404 /error.php

2)이것도 가능
ErrorDocument 401 /error <-- 실제로는 error.php 파일
ErrorDocument 403 /error
ErrorDocument 404 /error

3)이것도 가능
ErrorDocument 401 /error/ <-- error.php 파일 또는 /error/index.php
ErrorDocument 403 /error/
ErrorDocument 404 /error/

4)파라메터로 전달
ErrorDocument 401 /error/401
ErrorDocument 403 /error/403
ErrorDocument 404 /error/404

4)번 같은 경우는 실제로

/error.php/401
/error/index.php/401

이 두개 중 어느 것이든지 매치됩니다.

참고로 4)번 방법은 실제로 이렇게 설정하지 않아도 가능합니다.
이유는 ErrorDocument 를 처리하는 파일에서는 REDIRECT_STATUS 서버변수가
존재하기 때문입니다.

따라서 ErrorDocument 코딩 예를 든다면,

-- /error.php ---------------------------
<?php
$TITLE[401] = '401 Authorization Required';
$TITLE[403] = '403 Forbidden';
$TITLE[404] = '404 Not Found';

$errcode = $_SERVER["REDIRECT_STATUS"];
$request = 'http://'.$_SERVER[HTTP_HOST].$_SERVER[REQUEST_URI];

echo <<<_EOF_
...
<TITLE>$TITLE[$errcode]</TITLE>
...
- 요청한 (URI)페이지 : $request<BR>
- 에러 요약 : $TITLE[$errcode]<BR>
- 에러 내용 : $_SERVER[REDIRECT_ERROR_NOTES];
...
_EOF_;
?>
-----------------------------------------

이런식으로 코딩이 가능합니다.


4-3. 가상의 파일이름 이용

예1)
Request URI : /dowonload/media/foo/bar/setup.exe

이것은 실제로 웹서버는

/dowonload/media/foo/bar/alpha.exe
/dowonload.php/media/foo/bar/alpha.exe
/dowonload/media.php/foo/bar/alpha.exe
/dowonload/media/foo.php/bar/alpha.exe
/dowonload/media/foo/bar.php/alpha.exe

이와 같은 형태로 해석이 가능합니다.
(확장자를 모두 없애고 링크를 거는 방법)

따라서 첫번째 방법처럼 실제로 웹서버의 DocumentRoot 안쪽에
alpha.exe 파일이 있는 경우를 제외하면, 나머지 방법은 모두
DocumentRoot 바깥쪽에 alpha.exe 파일이 있어도 상관없다는
의미입니다.

또한 alpha.exe 파일은 실제의 파일일 수도 있고 가상의 파일일 수 도
있습니다.

두번째의 경우라면 실제로 download.php 파일에서 PAHT_INFO 의 문자열을
파싱하여 적절하게 헤더와 데이터를 클라이언트에게 전송해야 합니다.

이와 같이 가상의 파일 이름을 이용하는 경우 :

- 확장자에 의해서 브라우저(예:MSIE)가 Content-type를 구별하는 경우
- 대소문자를 구별없이 사용가능하고자 할 경우
- 다운로드하기 전에 어떤 인증 절차가 필요한 경우
- 실제 파일이 DocumentRoot 바깥쪽에 있을 경우
- 보다 간략하게 URI 를 사용하고자 할 경우
- 파일 크기가 비교적 작을 경우와 어떤 접근 기록을 남기고자 할 경우
- 기타


실제 적용 예) winamp 용
/mp3stream/stream.php/sPy_DIR_7MDHtKu5sC5tcDM=/관우의눈물.mp3


5. 후기

시간이 된다면 재미있는(?) 아파치 Action 지시자 설정과 사용법에
대해서...


EOF