替代curl非常简洁明了的http请求库
来源:https://gitee.com/brh/http
备注:作者已逝
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Provides http server communication options using [Stream]
* Mainly used to communiate with http
* Add Support HTTP/1.1 by Default
* Only Support Connection Close Mode
*
* @author anthony Chen
*/
class Http {
public static $allow_self_signed = true;
public static $non_blocking = false;
/**
* @var array default header options
*/
public static $default_options = array (
'User-Agent'=> 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit /538.36 (KHTML, like Gecko) Pexcel/6.998',
'Connection'=> 'Close' //Need to close the request every time for HTTP 1.1
);
/**
* return Array lines of headers
* Overwrite by $options
*
* @param Array $options, key value pairs of Header options
*
* @return Array,Array line of headers
*/
private static function getHeaders($options){
if ($options === NULL) {
// Use default options
$options = self::$default_options;
} else {
//Merge the $options with $default_options, if the value set in $options,
//Value in $default_options will be overwrite
$options =$options + self::$default_options ;
}
$headers = array();
foreach($options as $k=>$v){
$headers[] = $k.': '.$v;
}
return $headers;
}
/**
* Returns the output of a http URL.
* may be used.
*
* @param string http base URL or FULL url
* @param array Header options
* @param array $data Get Param
* @param array &$rr_headers,Request Response headers
* if Assigned,the response header will be populated
* If ['fingerprint'] is set, then finger is checked in SSL Context
* If ['ignore_errors'] is set, then ignore http error code other than 200
*
* @return string, Raw String of Http body
*/
public static function get($url, array $options = NULL,$data = NULL,&$rr_headers = NULL) {
$headers = self::getHeaders($options);
$params = ['http' => [
'method' => 'GET',
//Defautl HTTP 1.1 and with Connection Close
'protocol_version'=>'1.1',
//'Connection'=> 'Close' //Need to close the request every time for HTTP 1.1
]];
if(Arr::get($rr_headers,'ignore_errors') == true){
$params['http']['ignore_errors'] = true;
}
$params['http']['header'] = $headers;
if($data){
$url .= '?'.http_build_query($data);
}
$ctx = stream_context_create($params);
if(self::$allow_self_signed == true){
stream_context_set_option($ctx,["ssl"=>["allow_self_signed"=>true,"verify_peer_name"=>false,"verify_peer"=>false]]);
$_finger = Arr::get($rr_headers,'fingerprint');
if($_finger){
stream_context_set_option($ctx,["ssl"=>["peer_fingerprint"=>$_finger]]);
}
}
$fp = fopen($url, 'rb', false, $ctx);
if (!$fp) {
throw new Exception("Connection failed: $url");
}
if(self::$non_blocking == TRUE){
stream_set_blocking($fp,0);
}
if($rr_headers !== NULL){
$rr_headers = stream_get_meta_data($fp);
}
$response = stream_get_contents($fp);
if ($response === false) {
throw new Exception("Reading data Failed: $url");
}
fclose($fp);
return $response;
}
/**
* Post with request options and data
*
* @param String url, FULL url
* @param Array $options , key=>value pairs array
* @param Array $data ,Post Data pairs
* @param array &$rr_headers,Request Response headers
* if Assigned,the response header will be populated
* If ['fingerprint'] is set, then finger is checked in SSL Context
* If ['ignore_errors'] is set, then ignore http error code other than 200
* @return string, Raw String of Http body
*/
public static function post($url, $options = null,$data=NULL,&$rr_headers = NULL) {
//Restricted the Form formate
if(is_array($data)){
$data = http_build_query($data);
}
$options['Content-type'] = Arr::get($options,'Content-type','application/x-www-form-urlencoded');
$options['Content-Length'] =Arr::get($options,'Content-Length',strlen($data));
$params = ['http' => [
'method' => 'POST',
'protocol_version'=>'1.1',
//'Connection'=> 'Close', //Need to close the request every time for HTTP 1.1
//'ignore_errors'=>true,
'content' => $data
]];
if(Arr::get($rr_headers,'ignore_errors') == true){
$params['http']['ignore_errors'] = true;
}
$headers = self::getHeaders($options);
$params['http']['header'] = $headers;
$ctx = stream_context_create($params);
if(self::$allow_self_signed == true){
stream_context_set_option($ctx,["ssl"=>["allow_self_signed"=>true,"verify_peer_name"=>false,"verify_peer"=>false]]);
$_finger = Arr::get($rr_headers,'fingerprint');
if($_finger){
stream_context_set_option($ctx,["ssl"=>["peer_fingerprint"=>$_finger]]);
}
}
$fp = fopen($url, 'rb', false, $ctx);
if (!$fp) {
throw new Exception("Connection Failed: $url ");
}
if(self::$non_blocking == TRUE){
stream_set_blocking($fp,0);
}
if($rr_headers !== NULL){
$rr_headers = stream_get_meta_data($fp);
}
$response = stream_get_contents($fp);
if ($response === false) {
throw new Exception("Reading data failed: $url");
}
fclose($fp);
return $response;
}
/**
* Inflate zipped content
*
* @param String $_content, gzipped content
*
* @return String, Inflated content
*/
public static function inflate($_content){
//deflate add 10 charaters before inflate format and 8 charaters checksum append
//gzdecode is not availible for ALL PHP even gzencode is avalible
$_content = substr($_content, 10,-8);
return gzinflate($_content);
}
/**
* Check if the reponse content is zipped from response header
*
* @param Array $_response_header, Response header captured from get/post
*
* @return Boolean, True for zipped contented
*/
public static function isZipped($_response_header){
if (preg_grep('/^Content-Encoding:\s*gzip/i',$_response_header['wrapper_data'])){
return TRUE;
}else{
return False;
}
}
/**
* Parse response headers into K V data
*
* @param Array $headers, wrapper data return from http request
*
* @return Array , the parsed headers of http
*/
public static function parseHeaders( $_response_header ) {
$headers = Arr::get($_response_header,'wrapper_data',[]);
$head = array();
foreach( $headers as $k=>$v )
{
$t = explode( ':', $v, 2 );
if( isset( $t[1] ) )
$head[ trim($t[0]) ] = trim( $t[1] );
else
{
$head[] = $v;
if( preg_match( "#HTTP/[0-9\.]+\s+([0-9]+)#",$v, $out ) )
$head['reponse_code'] = intval($out[1]);
}
}
return $head;
}
} // End http