Source for file HTTPRelay.php
Documentation is available at HTTPRelay.php
* Project: HTTPRelay :: HTTP Relay class<br>
* HTTPRelay 패키지는 HTTP 요청을 간단하게 하거나 또는 HTTP
* 요청을 다른 서버로 Relay를 하기 위한 기능을 제공한다.
* {@example HTTPRelay/tests/test.php}
* @author JoungKyun.Kim <http://oops.org>
* @copyright (c) 2018, OOPS.org
* @link http://pear.oops.org/package/HTTPRelay
* @since File available since release 0.0.1
@require_once 'myException.php';
* HTTPRelay 패키지는 HTTP 요청을 간단하게 하거나 또는 HTTP
* 요청을 다른 서버로 Relay를 하기 위한 기능을 제공한다.
* {@example HTTPRelay/tests/test.php}
const UAGENT = 'OOPS HTTP Relay Wrapper 1.0';
* 1.0.5 부터는 30x 반환시에 redirect를 내부 처리를 하며,
* 이 경우, $info는 2차 배열로 referer의 info 정보를 보관한다.
* Post data encoding type
* Post data를 어떤 방식으로 인코딩 할지를 결정한다.
* 'url-encode'와 'form-data' 둘 중의 하나로 지정을 해야 한다.
* Post data에 파일 전송을 하기 위해서는 무조건 'form-data'로
* print debug messages to stderr
* 사용자 Request header를 배열로 지정한다.
* 배열 키는 Header Name으로 지정하며, 배열값에는 Header의 값을 지정한다.
* 배열값을 '-'으로 지정을 하면, 빈 값으로 처리를 한다.
* {@example HTTPRelay/tests/test-relay.php 30 1}
private $header = array ();
* Number of recursive calls
* redirect 시에 무한 루프를 방지하기 위한 counter
// {{{ +-- public __construct ($header = null)
* {@example HTTPRelay/tests/test-relay.php 23 6}
* @param array $header (optional) 사용자 정의 HTTP Header
* - Key는 Header 이름이어야 하며 '-'는 '_'로 표기한다.
* - Heder값이 없어야 할 경우에는 값을 '-'로 넣어준다.
* - Key값에 POSTTYPE을 지정할 경우, Post encoding 방식을
* 직접 지정이 가능하다. 이 경우 POSTTYPE은 HTTP Header
* 에 영향을 주지 않으며, 값으로는 'form-data'와 'url-encode'
* 중에 지정할 수 있다. POSTTYPE은 제거될 예정이니 $posttype
$this->error = &self::$error;
if ( $header['POSTTYPE'] ) {
switch ($header['POSTTYPE']) {
unset ($header['POSTTYPE']);
if ( is_array ($header) )
$this->header = &$header;
// {{{ +-- public (stdClass) head ($to, $tmout = 60, $httphost = '', $recursion = false)
* {@example HTTPRelay/tests/test-head.php}
* @param string $to 요청할 URL
* @param int $tmout (optional) timeout 값
* @param string $httphost (optional) HTTP/1.1 Host Header. 지정을 하지 않을 경우
* @param boolean $recursion redirec 처리를 위한 재귀 호출 구분 변수 (1.0.5)
public function head ($to, $tmout = 60, $httphost = '', $recursion = false) {
self::$error = 'Empty request url';
self: $error = 'Failed initialize';
$this->header['Host'] = self::http_host ($to, $httphost);
fprintf (STDERR, "** Request URL : %s\n", $to);
fprintf (STDERR, "** Request Host : %s\n", $this->header['Host']);
$header = self::http_header ();
$this->header['User_Agent'] ? $this->header['User_Agent'] : self::UAGENT
$info = $this->set_return_info ($c);
self::$error = curl_error ($c);
if ( $recursion === true )
if ( $info->http_code < 400 && $info->redirect_url ) {
$info->call_method = __FUNCTION__ ;
if ( ($data = $this->redirect_call ($info, $tmout, $httphost)) === false )
foreach ( $content as $v ) {
if ( preg_match ('!^HTTP/([0-9.]+) ([0-9]+) (.*)!', $v, $matches) ) {
$r->{'VERSION'} = $matches[1];
$r->{'RETURN-CODE'} = $matches[2];
$r->{'RETURN-MSG'} = $matches[3];
// {{{ +-- public (string) fetch ($to, $tmout = 60, $httphost = '', $post = null, $recursion = false)
* {@example HTTPRelay/tests/test.php}
* @param string $to 요청할 URL
* @param int $tmout (optional) timeout 값
* @param string $httphost (optional) HTTP/1.1 Host Header. 지정을 하지 않을 경우
* @param array $post (optional) Post방식으로 요청시 전송할 Post data
* @param boolean $recursion redirec 처리를 위한 재귀 호출 구분 변수 (1.0.5)
public function fetch ($to, $tmout = 60, $httphost = '', $post = null, $recursion = false) {
self::$error = 'Empty request url';
self: $error = 'Failed initialize';
$this->header['Host'] = self::http_host ($to, $httphost);
fprintf (STDERR, "** Request URL : %s\n", $to);
fprintf (STDERR, "** Request Host : %s\n", $this->header['Host']);
$header = self::http_header ();
$this->header['User_Agent'] ? $this->header['User_Agent'] : self::UAGENT
$info = $this->set_return_info ($c);
self::$error = curl_error ($c);
if ( $info->http_code < 400 && $info->redirect_url ) {
$info->call_method = __FUNCTION__ ;
if ( ($data = $this->redirect_call ($info, $tmout, $httphost, $post)) === false )
// {{{ +-- public (string) relay ($to, $tmout = 60, $httphost = '', $recursion = false)
* HTML 요청을 다른 호스트로 중계를 한다.
* {@example HTTPRelay/tests/test.php}
* @param string $to 중계할 URL
* @param int $tmout (optional) timeout 값
* @param string $httphost (optional) HTTP/1.1 Host Header. 지정을 하지 않을 경우
* @param boolean $recursion redirec 처리를 위한 재귀 호출 구분 변수 (1.0.5)
public function relay ($to, $tmout = 60, $httphost = '', $recursion = false) {
self::$error = 'Empty request url';
self: $error = 'Failed initialize';
$this->header['Host'] = self::http_host ($to, $httphost);
fprintf (STDERR, "** Request URL : %s\n", $to);
fprintf (STDERR, "** Request Host : %s\n", $this->header['Host']);
$uri = trim ($_SERVER['QUERY_STRING']);
$header = self::http_header ();
$this->header['User_Agent'] ? $this->header['User_Agent'] : self::UAGENT
$info = $this->set_return_info ($c);
self::$error = curl_error ($c);
if ( $info->http_code < 400 && $info->redirect_url ) {
$info->call_method = __FUNCTION__ ;
if ( ($data = $this->redirect_call ($info, $tmout, $httphost)) === false )
// {{{ +-- private (mixed) redirect_call (void)
private function redirect_call () {
if ( ++ $this->reno > 9 ) {
self::$error = 'Overflows 10 times redirectioins!';
$to = &$arg[0]->redirect_url;
$narg = array ($to, $arg[1], $arg[2]);
if ( $arg[0]->call_method == 'fetch' ) {
fprintf (STDERR, "\n** Redirect Host: %s\n", $to);
$this->header['Referer'] = $arg[0]->url;
$callback_func = array ($this, $arg[0]->call_method);
// {{{ +-- private (stdClass) set_return_info ($c)
private function set_return_info ($c) {
else if ( $this->reno == 1 ) {
$this->info[$this->reno] = $info;
// {{{ +-- private (array) http_header (void)
* 사용자 정의 헤더와 기본 헤더를 셋팅 한다.
private function http_header () {
foreach ( $this->header as $name => $val ) {
if ( $name == 'User_Agent' )
self::set_header ($header, $name, $val);
if ( ! isset ($this->header['Expect']) )
self::set_header ($header, 'Expect', '-');
if ( ! $this->header['Accept_Language'] )
self::set_header ($header, 'Accept-Language', 'ko-KR,ko;q=0.8,en-US;q=0.6,en;q=0.4');
if ( ! $this->header['Connection'] )
self::set_header ($header, 'Connection', 'close');
self::client_ip_set ($header);
// {{{ +-- private (void) set_header (&$h, $d, $v)
* 헤더를 셋팅한다. 헤더 값이 '-'로 지정이 될 경우, 해당 헤더는
* @param array 헤더를 저장할 변수
* @param string 헤더 값. '-' 값을 가지면, 빈 값을 가지는 헤더라는 의미로 처리된다.
private function set_header (&$h, $d, $v) {
// {{{ +-- private (string) http_host ($t, $h)
* HTTP/1.1 Host header에서 사용할 hostname을 구한다.
* Hostname (2번째 인자)가 따로 지정되지 않으면 주어진 Full URL(1번째 인자)
* @param string HTTP/1.1 Host header 값
private function http_host ($t, $h = '') {
$src = array ('!^https?://!i', '!/.*!');
// {{{ +-- private (void) relay_post (&$c)
* Post로 넘어온 Data를 relay하기 위한 post data template
* @param resource CURL resource
private function relay_post (&$c) {
if ( $_SERVER['REQUEST_METHOD'] != 'POST' )
$post['file'] = "@{$_FILES['file']['tmp_name']}";
// {{{ +-- private (void) client_ip_set (&$h, $ip = null)
* Relay를 위한 Client IP 주소 설정
* @param string (optional) IP 주소
private function client_ip_set (&$h, $ip = null) {
$v = $_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
if ( $_SERVER['HTTP_X_FORWARDED_FOR'] )
$v = $ip . ', ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
$v = $ip . ', ' . $_SERVER['REMOTE_ADDR'];
self::set_header ($h, 'X-Forwarded-For', $v);
// {{{ +-- public HTTPRelay_REQUIRES (void)
* HTTRelay 패키지에서 필요한 의존성을 검사한다.
'-------------------------------------------------' . $brbr .
'HTTPRelay ERROR!' . $brbr .
'HTTPRelay class needs oops/myException pear package' . $br .
'You can get myException pear package at' . $br .
'http://mirror.oops.org/pub/oops/php/pear/myException/' . $br .
'Also you can install with pear command as follow command' . $br .
'shell> pear channel-discover pear.oops.org' . $br .
'shell> pear install oops/myException' . $brbr .
'-------------------------------------------------' . $brbr;
throw new Exception ($msg, E_USER_ERROR);
'-------------------------------------------------' . $brbr .
'HTTPRelay ERROR!' . $br .
'HTTPRelay class needs curl extension' . $brbr .
'-------------------------------------------------' . $brbr;
* vim: set filetype=php noet sw=4 ts=4 fdm=marker:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
|