HTTP запрос средствами PHP (POST/GET)

HTTP запрос средствами PHP (POST/GET)
просмотров: 1523513 января 2012 года

Для определенного приложения, мне необходимо было написать функцию, для выполнения HTTP-запроса к внешним сайтам.

Релизовал функцию позволяющую это делать:

/**
 * HTTP Request v1.0 by Denik
 * Parametres:
 *  - (string) or (array)[url] - site url
 *  - [method] - POST | GET
 *  - [data] - array of post data
 *  - [port] - connection port
 *  - [timeout] - timeout connection
 *  - [redirect] - true, allow redirects in headers
 *  - [return] - content|headers|array - type of return data, default - content
 *  - [cookie] - allow to set cookies
 *  - [referer] - allow to set referer url
 **/
function http_request($params)
{
    if( ! is_array($params) )
    {
        $params = array(
            'url' => $params,
            'method' => 'GET'
        );
    }
    
    if( $params['url']=='' ) return FALSE;
    
    if( ! isset($params['method']) ) $params['method'] = (isset($params['data'])&&is_array($params['data'])) ? 'POST' : 'GET';
    $params['method'] = strtoupper($params['method']);
    if( ! in_array($params['method'], array('GET', 'POST')) ) return FALSE; 
    
    /* Приводим ссылку в правильный вид */
    $url = parse_url($params['url']);
    if( ! isset($url['scheme']) ) $url['scheme'] = 'http';
    if( ! isset($url['path']) ) $url['path'] = '/';
    if( ! isset($url['host']) && isset($url['path']) )
    {
        if( strpos($url['path'], '/') )
        {
            $url['host'] = substr($url['path'], 0, strpos($url['path'], '/'));
            $url['path'] = substr($url['path'], strpos($url['path'], '/'));
        }
        else
        {
            $url['host'] = $url['path'];
            $url['path'] = '/';	
        }
    }
    $url['path'] = preg_replace("/[\\/]+/", "/", $url['path']);
    if( isset($url['query']) ) $url['path'] .= "?{$url['query']}";
    
    $port = isset($params['port']) ? $params['port']
            : ( isset($url['port']) ? $url['port'] : ($url['scheme']=='https'?443:80) );
    
    $timeout = isset($params['timeout']) ? $params['timeout'] : 30;
    if( ! isset($params['return']) ) $params['return'] = 'content';
    
    $scheme = $url['scheme']=='https' ? 'ssl://':'';
    $fp = @fsockopen($scheme.$url['host'], $port, $errno, $errstr, $timeout);
    if( $fp )
    {
        /* Mozilla */
        if( ! isset($params['User-Agent']) ) $params['User-Agent'] = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16";
        
        $request = "{$params['method']} {$url['path']} HTTP/1.0\r\n";
        $request .= "Host: {$url['host']}\r\n";
        $request .= "User-Agent: {$params['User-Agent']}"."\r\n";
        if( isset($params['referer']) ) $request .= "Referer: {$params['referer']}\r\n";
        if( isset($params['cookie']) )
        {
            $cookie = "";
            if( is_array($params['cookie']) ) {foreach( $params['cookie'] as $k=>$v ) $cookie .= "$k=$v; "; $cookie = substr($cookie,0,-2);}
            else $cookie = $params['cookie'];
            if( $cookie!='' ) $request .= "Cookie: $cookie\r\n";
        }
        $request .= "Connection: close\r\n";
        if( $params['method']=='POST' )
        {
            if( isset($params['data']) && is_array($params['data']) )
            {
                foreach($params['data'] AS $k => $v)
                    $data .= urlencode($k).'='.urlencode($v).'&';
                if( substr($data, -1)=='&' ) $data = substr($data,0,-1);
            }
            $data .= "\r\n\r\n";
            
            $request .= "Content-type: application/x-www-form-urlencoded\r\n";
            $request .= "Content-length: ".strlen($data)."\r\n";
        }
        $request .= "\r\n";
        
        if( $params['method'] == 'POST' ) $request .= $data;
        
        @fwrite ($fp,$request); /* Send request */
        
        $res = ""; $headers = ""; $h_detected = false;
        while( !@feof($fp) )
        {
            $res .= @fread($fp, 1024); /* читаем контент */
    
            /* Проверка наличия загловков в контенте */
            if( ! $h_detected && strpos($res, "\r\n\r\n")!==FALSE )
            {
                /* заголовки уже считаны - корректируем контент */
                $h_detected = true;
                
                $headers = substr($res, 0, strpos($res, "\r\n\r\n"));
                $res = substr($res, strpos($res, "\r\n\r\n")+4);
                
                /* Headers to Array */
                if( $params['return']=='headers' || $params['return']=='array'
                    || (isset($params['redirect']) && $params['redirect']==true) )
                {
                    $h = explode("\r\n", $headers);
                    $headers = array();
                    foreach( $h as $k=>$v )
                    {
                        if( strpos($v, ':') )
                        {
                            $k = substr($v, 0, strpos($v, ':'));
                            $v = trim(substr($v, strpos($v, ':')+1));
                        }
                        $headers[strtoupper($k)] = $v;
                    }
                }
                if( isset($params['redirect']) && $params['redirect']==true && isset($headers['LOCATION']) )
                {
                    $params['url'] = $headers['LOCATION'];
                    if( !isset($params['redirect-count']) ) $params['redirect-count'] = 0;
                    if( $params['redirect-count']<10 )
                    {
                        $params['redirect-count']++;
                        $func = __FUNCTION__;
                        return @is_object($this) ? $this->$func($params) : $func($params);
                    }
                }
                if( $params['return']=='headers' ) return $headers;
            }
        }
        
        @fclose($fp);
    }
    else return FALSE;/* $errstr.$errno; */
    
    if( $params['return']=='array' ) $res = array('headers'=>$headers, 'content'=>$res);
    
    return $res;
}

 

Использование:

print_r( http_request(array('url'=>"http://denik.od.ua/", 'method'=>'GET')) );
print_r( http_request("http://denik.od.ua/") );

$data = array(
    'param1' => 'val1',
    'param1' => 'val2'
);
print_r( http_request(array('url'=>"http://denik.od.ua/", 'method'=>'POST', 'data'=>$data)) );
print_r( http_request(array('url'=>"denik.od.ua", 'data'=>$data)) );

 

Очень похожая в реализации, но все же немного другая функция, предназначена для копирования файлов/HTML-страниц с интернет потока. Работает примерно как стандартная функция copy(). При существовании файла назначения - перезаписывает его!

/**
 * HTTP Request v1.0 by Denik
 * Parametres:
 * 	- [src_url] - source url
 *  - [dst_file] - destination file path
 *  - [timeout] - timeout connection (default - 30)
 *  return: TRUE/FALSE
 **/
function http_file_down($src_url, $dst_file, $timeout = 30)
{
    /* Приводим ссылку в правильный вид */
    $url = parse_url($src_url);
    if( ! isset($url['scheme']) ) $url['scheme'] = 'http';
    if( ! isset($url['path']) ) $url['path'] = '/';
    if( ! isset($url['host']) && isset($url['path']) )
    {
        if( strpos($url['path'], '/') )
        {
            $url['host'] = substr($url['path'], 0, strpos($url['path'], '/'));
            $url['path'] = substr($url['path'], strpos($url['path'], '/'));
        }
        else
        {
            $url['host'] = $url['path'];
            $url['path'] = '/';	
        }
    }
    $url['path'] = preg_replace("/[\\/]+/", "/", $url['path']);
    if( isset($url['query']) ) $url['path'] .= "?{$url['query']}";
    
    $port = isset($params['port']) ? $params['port']
        	: ( isset($url['port']) ? $url['port'] : ($url['scheme']=='https'?443:80) );
    
    $scheme = $url['scheme']=='https' ? 'ssl://':'';
    $fp = @fsockopen($scheme.$url['host'], $port, $errno, $errstr, $timeout);
    if( ! $fp ) return FALSE;

    /* Mozilla */
    $user_agent = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16";
    
    $request = "GET {$url['path']} HTTP/1.0\r\n";
    $request .= "Host: {$url['host']}\r\n";
    $request .= "User-Agent: {$user_agent}"."\r\n";
    $request .= "Connection: close\r\n";
    $request .= "\r\n";
    
    @fwrite($fp, $request);
    
    $headers = ""; $headers_write = true;
    while( !@feof($fp) )
    {
        $line = @fread($fp, 1024);
        
        if( $headers_write )
        {
            $headers .= $line;
            if( strpos($headers, "\r\n\r\n")!==FALSE )
            {
                $line = substr($headers, strpos($headers, "\r\n\r\n")+4);
                $headers = substr($headers, 0, strpos($headers, "\r\n\r\n"));
                
                /* Parsing headers */
                $h = explode("\r\n", $headers);
                $headers = array('STATUS'=>404);
                foreach( $h as $k=>$v )
                {
                    if( strpos($v, ':') )
                    {
                        $k = substr($v, 0, strpos($v, ':'));
                        $v = trim(substr($v, strpos($v, ':')+1));
                    }
                    $headers[strtoupper($k)] = $v;
                }
                if( isset($headers[0]) ) $headers['STATUS'] = intval(trim(substr($headers[0], strpos($headers[0], ' ')+1)));
                
                if( $headers['STATUS']==404 ) {@fclose($fp); return FALSE;}
                
                // Header Redirect (301)
                if( isset($headers['LOCATION']) )
                {
                    $src_url = $headers['LOCATION'];
                    $attempt = md5(__METHOD__);
                    if( !isset($GLOBALS[$attempt]) ) $GLOBALS[$attempt] = 0;
                    if( $GLOBALS[$attempt]<10 )
                    {
                        $GLOBALS[$attempt]++;
                        $func = __FUNCTION__;
                        return @is_object($this) ? $this->$func($src_url, $dst_file, $timeout) : $func($src_url, $dst_file, $timeout);
                    }
                }
                
                $file = @fopen($dst_file, "w+");
                if( ! $file ) {@fclose($fp); return FALSE;}
                $headers_write = FALSE;
            }
        }
        
        if( ! $headers_write )
        {
            /* Это уже части файла */
            @fwrite($file, $line);
        }
    }
    
    @fclose($file);
    @fclose($fp);
    
    return TRUE;
}

Надеюсь, кому-то все это когда-нибудь пригодиться... Может быть даже и мне))) Удачного программирования!

Что скажем?