XML или JSON в HTTP-запросе без cURL

1 октября 2011 г.

JSONМногие вебсервисы работают с запросами в JSON или XML формате. Зачастую предоставляя монструозные библиотеки обёртки. Но хороших лаконичных реализаций RAW-постинга этих запросов я в сети не встретил поэтому написал функцию работающую через сокеты для отправки JSON или XML запроса и получение строки ответа с поддержкой chunk-encoding.

 
// sockets version HTTP/POST
function http_post( $url, $data ) {
 
    $eol = "\r\n";
 
    $post = '';
 
    if (is_array($data)) {
        foreach( $data as $k => $v)
            $post .= $k.'='.urlencode($v).'&';
        $post = substr($post, 0,-1);
        $content_type = 'application/x-www-form-urlencoded';
    } else {
        $post = $data;
        if (strpos($post, '<?xml') ===  0)
            $content_type = 'text/xml';
        else if (strpos($post, '{') ===  0)
            $content_type = 'application/json';
        else
            $content_type = 'text/html';
    }
    if ((($u = parse_url($url)) === false) || !isset($u['host'])) return false;
 
    if (!isset($u['scheme'])) $u['scheme'] = 'http';
 
    $request = 'POST '.(isset($u['path']) ? $u['path'] : '/').((isset($u['query'])) ? '?'.$u['query'] : '' ).' HTTP/1.1'.$eol
        .'Host: '.$u['host'].$eol
        .'Content-Type: '.$content_type.$eol
        .'Content-Length: '.mb_strlen($post, 'latin1').$eol
        .'Connection: close'.$eol.$eol
        .$post;
 
    $host = ($u['scheme'] == 'https') ? 'ssl://'.$u['host'] : $u['host'];
 
    if (isset($u['port']))
        $port = $u['port'];
    else
        $port = ($u['scheme'] == 'https') ? 443 : 80;
 
    $fp = @fsockopen( $host, $port, $errno, $errstr, 10);
    if ($fp) {
 
        $content = '';
        $content_length = false;
        $chunked = false;
 
        fwrite($fp, $request);
 
        // read headers                
        while ($line = fgets($fp)) {
 
            if (preg_match('~Content-Length: (\d+)~i', $line, $matches)) { 
                $content_length = (int) $matches[1];
            } else if (preg_match('~Transfer-Encoding: chunked~i', $line)) {
                $chunked = true;
            } else if ($line == "\r\n") {
                break;
            }
 
        }
        // read content        
        if ($content_length !== false) {
 
            $content = fread($fp, $content_length);
 
        } else if ($chunked) {
 
            while ( $chunk_length = hexdec(trim(fgets($fp))) ) {
 
                $chunk = '';
                $read_length =  0;
 
                while ( $read_length < $chunk_length ) {
 
                    $chunk .= fread($fp, $chunk_length - $read_length);
                    $read_length = strlen($chunk);
 
                } 
                $content .= $chunk;
 
                fgets($fp);
 
            }
        } else {
            while(!feof($fp)) $content .= fread($fp, 4096);
        }
        fclose($fp);
 
//        echo $content;
 
        return $content;
 
    } else {
        return false;
    }
}

Простой пример:

$json = json_encode(array('test' => 1));
$result = http_post('http://mywebserviceurl.net', $json);
// $result = json_decode( $result );
Теги:
рубрика PHP
  • Похожие статьи
  • Предыдущие из рубрики