Dev/Web
allow_url_fopen off 일때, proxy 구현 방법.
newtype
2011. 3. 18. 14:33
jQuery에 관심이 생기면서, javascript 만으로 RSS 리더기를 만들어 보기로 했다.
jQuery가 워낙에 많은 Plugin들을 지원하고 있어서, rss Parser도 금방 찾을 수 있었다.
jFeed 라는 것인데, 소스도 간단하고.. 복잡한 기능이 필요없는 용도로는 적당했다.
그런데, 예상치도 못한 문제가 있었다.
Ajax에서 다른 도메인의 페이지를 읽기 위해 proxy를 구현 해야 하는데..
셈플 소스에 포함된 것이 정상적으로 동작하지 않는 것이다.
셈플 소스에 포함된 코드는 아래와 같다.
원인은 호스팅을 받고 있는 cafe24 에서는 보안상의 이유로 php.ini 파일에서 fopen 함수의 사용을 막아 놓은 것이다.
업체에서 제안하는 방법은, fsockopen 이용하는 방법으로 셈플 소스는 아래와 같다.
하지만, 이방법도.. connection, write는 성공하지만, read 부분에서 데이터를 가져오질 못했다.
업체 문의 결과, www 폴더안에 ".htaccess" 파일을 만들고 파일 내용으로,
를 넣어 주면 된다고 한다. 단, 취약점을 통한 보안적 위험에 대한 책임을 보장할 수 없단다.
왠지 찝찝하다.
좀 더 뒤져보니, curl 이란 php 라이브러리가 있다. 이넘이 물건이다. 좀 잡다한 기능들이 많아 무거워 보이긴 한데.. 일단 동작은 잘 된다.
curl 라이브러리를 이용한 소스는 아래와 같다.
소스의 기능은 아래와 같다.
1. HTTP CODE가 301, 302의 Forwarding 관련된 것이면 해당 URL로 이동.
: CURLOPT_HEADER 옵션, while문 안의 해더 파싱 부분.
2. Forwaring이 5번 이상이면, 에러 처리.
: while문 안의 if문
3. HTTP 해더 부분 제거.
: return 전의 substr 구문. rss 리더를 위한 proxy 이므로 필요 하다.
마지막 소스를 이용해 proxy 문제를 해결 했다.
jQuery가 워낙에 많은 Plugin들을 지원하고 있어서, rss Parser도 금방 찾을 수 있었다.
jFeed 라는 것인데, 소스도 간단하고.. 복잡한 기능이 필요없는 용도로는 적당했다.
그런데, 예상치도 못한 문제가 있었다.
Ajax에서 다른 도메인의 페이지를 읽기 위해 proxy를 구현 해야 하는데..
셈플 소스에 포함된 것이 정상적으로 동작하지 않는 것이다.
셈플 소스에 포함된 코드는 아래와 같다.
<?php header('Content-type: application/xml'); $handle = fopen($_REQUEST['url'], "r"); if ($handle) { while (!feof($handle)) { $buffer = fgets($handle, 4096); echo $buffer; } fclose($handle); } ?>
원인은 호스팅을 받고 있는 cafe24 에서는 보안상의 이유로 php.ini 파일에서 fopen 함수의 사용을 막아 놓은 것이다.
업체에서 제안하는 방법은, fsockopen 이용하는 방법으로 셈플 소스는 아래와 같다.
function get_url_fsockopen( $url ) { $URL_parsed = parse_url($url); $host = $URL_parsed["host"]; $port = $URL_parsed["port"]; if ($port==0) $port = 80; $path = $URL_parsed["path"]; if ($URL_parsed["query"] != "") $path .= "?".$URL_parsed["query"]; $out = "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n"; $fp = fsockopen($host, $port, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br>\n"; } else { fputs($fp, $out); $body = false; while (!feof($fp)) { $s = fgets($fp, 128); if ( $body ) $in .= $s; if ( $s == "\r\n" ) $body = true; } fclose($fp); echo $in; } }
하지만, 이방법도.. connection, write는 성공하지만, read 부분에서 데이터를 가져오질 못했다.
업체 문의 결과, www 폴더안에 ".htaccess" 파일을 만들고 파일 내용으로,
php_flag allow_url_fopen 1
를 넣어 주면 된다고 한다. 단, 취약점을 통한 보안적 위험에 대한 책임을 보장할 수 없단다.
왠지 찝찝하다.
좀 더 뒤져보니, curl 이란 php 라이브러리가 있다. 이넘이 물건이다. 좀 잡다한 기능들이 많아 무거워 보이긴 한데.. 일단 동작은 잘 된다.
curl 라이브러리를 이용한 소스는 아래와 같다.
<?php function get_url_content($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,true); curl_setopt($ch, CURLOPT_HEADER, true); $html = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $inc=1; while ($http_code == 301 || $http_code == 302) { $header = curl_getinfo($ch, CURLINFO_HEADER_OUT); curl_close($ch); list($header, $html) = explode("\n\n", $html, 2); preg_match('/Location: (.*?)\n/', $header, $matches); $url = $matches[1]; if (strlen(trim($url)) <= 0 ) return "[".$http_code."] forwarding error, not found url.<br/>"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,true); $html = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ( $inc++ > 5 ) { curl_close($ch); return "to many forwarding...<br/>"; } } curl_close($ch); return substr($html, strpos($html, '<?xml'));; } echo get_url_content( $_REQUEST['url'] ); ?>
소스의 기능은 아래와 같다.
1. HTTP CODE가 301, 302의 Forwarding 관련된 것이면 해당 URL로 이동.
: CURLOPT_HEADER 옵션, while문 안의 해더 파싱 부분.
2. Forwaring이 5번 이상이면, 에러 처리.
: while문 안의 if문
3. HTTP 해더 부분 제거.
: return 전의 substr 구문. rss 리더를 위한 proxy 이므로 필요 하다.
마지막 소스를 이용해 proxy 문제를 해결 했다.
반응형