XML или JSON в HTTP-запросе без cURL
1 октября 2011 г.
Многие вебсервисы работают с запросами в 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