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 );
рубрика