Created
October 31, 2018 09:09
-
-
Save dkrusky/0658e9e4a410a5fc62fdc1842b36d9db to your computer and use it in GitHub Desktop.
Ultimate curl wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//abstract class curl { | |
class curl { | |
private $error_codes; | |
private $_headers; | |
private $_options; | |
public $headers; | |
public $options; | |
private $response_header; | |
private $default_headers = array(); | |
private $default_options = array( | |
CURLOPT_RETURNTRANSFER => true, | |
CURLOPT_MAXREDIRS => 10, | |
CURLOPT_TIMEOUT => 30, | |
CURLOPT_VERBOSE => false, | |
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, | |
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4 | |
); | |
function __construct() { | |
$this->headers = new collection(); | |
$this->_headers = new collection( $this->default_headers ); | |
// sets some defaults for all curl connections | |
$this->options = new collection( ); | |
$this->_options = new collection( $this->default_options ); | |
// initialize list of all curl error constants, and values | |
$list = get_defined_constants(TRUE); | |
$list = preg_grep('/^CURLE_/', array_flip($list['curl'])); | |
foreach ($list as $code=>$constant) { | |
$list[$code] = array | |
( | |
'code' => $code, | |
'constant' => $constant, | |
'message' => curl_strerror($code) | |
); | |
} | |
$this->error_codes = $list; | |
} | |
private function mergeValues( $arrayA, $arrayB ) { | |
if(empty($arrayA) && empty($arrayB)) { | |
return new collection(); | |
} elseif( empty($arrayA) && !empty($arrayB) ) { | |
return new collection($arrayB); | |
} elseif( !empty($arrayA) && empty($arrayB) ) { | |
return new collection($arrayA); | |
} elseif( !empty($arrayA) && !empty($arrayB) ) { | |
return new collection(array_merge($arrayA, $arrayB)); | |
} | |
return new collection(); | |
} | |
private function getOptions() { | |
$_options = $this->_options->value(false); | |
$options = $this->options->value(false); | |
return $this->mergeValues($options, $options); | |
} | |
private function getHeaders() { | |
$_headers = $this->_headers->value(false); | |
$headers = $this->headers->value(false); | |
return $this->mergeValues($_headers, $headers); | |
} | |
// reset curl options, and headers to defaults | |
function reset() { | |
$this->headers->set(array(), true); | |
$this->options->set(array(), true); | |
return true; | |
} | |
// DELETE request | |
function delete($url, $data) { | |
// remove post/custom request options | |
$this->options->remove( CURLOPT_POST ); | |
// add curstom request for put | |
$this->options->add( CURLOPT_CUSTOMREQUEST, "DELETE" ); | |
$this->options->add( CURLOPT_POSTFIELDS, $data ); | |
// process request and return response | |
return $this->curl_request( $url ); | |
} | |
// PUT request | |
function put($url, $data) { | |
// remove post/custom request options | |
$this->options->remove( CURLOPT_POST ); | |
// add curstom request for put | |
$this->options->add( CURLOPT_CUSTOMREQUEST, "PUT" ); | |
$this->options->add( CURLOPT_POSTFIELDS, $data ); | |
// process request and return response | |
return $this->curl_request( $url ); | |
} | |
// GET request | |
function get($url) { | |
// remove post/custom request options | |
$this->options->remove( CURLOPT_CUSTOMREQUEST ); | |
$this->options->remove( CURLOPT_POST ); | |
$this->options->remove( CURLOPT_POSTFIELDS ); | |
// process request and return response | |
return $this->curl_request( $url ); | |
} | |
// POST request | |
function post($url, $data) { | |
// remove custom request if set | |
$this->options->remove( CURLOPT_CUSTOMREQUEST ); | |
// set basic parameters | |
$this->options->add( CURLOPT_POST, true ); | |
$this->options->add( CURLOPT_POSTFIELDS, $data ); | |
// process request and return response | |
return $this->curl_request( $url ); | |
} | |
// internal handler for processing curl header lines | |
private function curl_header_response($curl, $header) { | |
$_header = trim($header); | |
if(!empty($_header)) { | |
$this->response_header[] = $_header; | |
} | |
return strlen($header); | |
} | |
// universal curl handler | |
private function curl_request($url) { | |
// clear response_header object | |
$this->response_header = array(); | |
$options = $this->getOptions(); | |
$headers = $this->getHeaders(); | |
// set url to connect to | |
$options->add( CURLOPT_URL, $url ); | |
// initialize headers | |
if(!empty($headers->value())) { | |
$options->add( CURLOPT_HTTPHEADER, $headers->value() ); | |
} | |
// set handler to process headers so they can be returned with the result | |
$options->add( CURLOPT_HEADERFUNCTION, array(&$this, 'curl_header_response') ); | |
// initialize response object and get scheme of url being connected to | |
$response = new stdClass(); | |
$response->scheme = parse_url($url, PHP_URL_SCHEME); | |
// if https is set, verify peer, and set ssl version | |
if($response->scheme == 'https') { | |
$options->add( CURLOPT_SSL_VERIFYPEER, true ); | |
$options->add( CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2, false ); | |
$options->add( CURLOPT_CERTINFO, true ); | |
} else { | |
$options->remove( CURLOPT_SSL_VERIFYPEER, true ); | |
$options->remove( CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2 ); | |
$options->remove( CURLOPT_CERTINFO, true ); | |
} | |
$curl = curl_init(); | |
curl_setopt_array( | |
$curl, | |
$options->value(false) | |
); | |
// get the data | |
$response->data = new stdClass(); | |
$response->data->raw = curl_exec($curl); | |
$response->data->type = trim(curl_getinfo($curl, CURLINFO_CONTENT_TYPE)); | |
$response->data->header = $this->response_header; | |
if(strpos($response->data->type, ';')) { | |
// parse content-type if contains more than just the mime type | |
$response->data->type = trim(explode(';', $response->data->type)[0]); | |
} | |
// automatically decode based on mime type | |
switch($response->data->type) { | |
case 'application/xml'; | |
case 'text/xml'; | |
$response->data->object = simplexml_load_string($response->data->raw); | |
break; | |
case 'application/json'; | |
case 'text/json'; | |
case 'application/vnd.api+json'; | |
$response->data->object = json_decode($response->data->raw); | |
break; | |
} | |
// get curl error information | |
$response->curl = $this->curl_code(curl_errno($curl)); | |
$response->curl->error = curl_error($curl); | |
// get http status code information | |
$response->http = new stdClass(); | |
$response->http->code = curl_getinfo($curl, CURLINFO_HTTP_CODE); | |
$response->http->description = $this->http_code($response->http->code); | |
$response->http->url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); | |
if($response->scheme == 'https') { | |
// get ssl information if scheme is https | |
$response->ssl = new stdClass(); | |
$response->ssl->code = curl_getinfo($curl, CURLINFO_SSL_VERIFYRESULT); | |
$response->ssl->engines = curl_getinfo($curl, CURLINFO_SSL_ENGINES); | |
$response->ssl->message = $this->ssl_code($response->ssl->code); | |
$response->ssl->valid = false; | |
if($response->ssl->code == 0) { | |
$response->ssl->valid = true; | |
$response->ssl->chain = curl_getinfo($curl, CURLINFO_CERTINFO); | |
} | |
} | |
curl_close($curl); | |
return $response; | |
} | |
// used to translate curl error codes into more meaningful information | |
private function curl_code($int) { | |
$int = intval($int); | |
if($int == 0) { | |
return (object)array( | |
'code' => 0, | |
'constant' => 'SUCCESS', | |
'message' => "Communication was successful" | |
); | |
} | |
if(isset($this->error_codes[$int])) { | |
return (object)$this->error_codes[$int]; | |
} | |
return (object)array( | |
'code' => 13377331, | |
'constant' => 'L33T_CODE_L33T', | |
'message' => "No curl error code was found to match the value : {$int}" | |
); | |
} | |
private function ssl_code($int) { | |
$int = intval($int); | |
$ssl_codes = array( | |
'0' => 'X509_V_OK', | |
'2' => 'X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT', | |
'3' => 'X509_V_ERR_UNABLE_TO_GET_CRL', | |
'4' => 'X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE', | |
'5' => 'X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE', | |
'6' => 'X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY', | |
'7' => 'X509_V_ERR_CERT_SIGNATURE_FAILURE', | |
'8' => 'X509_V_ERR_CRL_SIGNATURE_FAILURE', | |
'9' => 'X509_V_ERR_CERT_NOT_YET_VALID', | |
'10' => 'X509_V_ERR_CERT_HAS_EXPIRED', | |
'11' => 'X509_V_ERR_CRL_NOT_YET_VALID', | |
'12' => 'X509_V_ERR_CRL_HAS_EXPIRED', | |
'13' => 'X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD', | |
'14' => 'X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD', | |
'15' => 'X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD', | |
'16' => 'X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD', | |
'17' => 'X509_V_ERR_OUT_OF_MEM', | |
'18' => 'X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT', | |
'19' => 'X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN', | |
'20' => 'X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY', | |
'21' => 'X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE', | |
'22' => 'X509_V_ERR_CERT_CHAIN_TOO_LONG', | |
'23' => 'X509_V_ERR_CERT_REVOKED', | |
'24' => 'X509_V_ERR_INVALID_CA', | |
'25' => 'X509_V_ERR_PATH_LENGTH_EXCEEDED', | |
'26' => 'X509_V_ERR_INVALID_PURPOSE', | |
'27' => 'X509_V_ERR_CERT_UNTRUSTED', | |
'28' => 'X509_V_ERR_CERT_REJECTED', | |
'29' => 'X509_V_ERR_SUBJECT_ISSUER_MISMATCH', | |
'30' => 'X509_V_ERR_AKID_SKID_MISMATCH', | |
'31' => 'X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH', | |
'32' => 'X509_V_ERR_KEYUSAGE_NO_CERTSIGN', | |
'50' => 'X509_V_ERR_APPLICATION_VERIFICATION' | |
); | |
if(isset($ssl_codes[$int])) { | |
return $ssl_codes[$int]; | |
} | |
return "Undefined Code [{$int}]"; | |
} | |
// used to translate http status codes into more meaningful information | |
private function http_code($int) { | |
$int = intval($int); | |
$http_codes = array( | |
100 => 'Continue', | |
101 => 'Switching Protocols', | |
102 => 'Processing', // WebDAV; RFC 2518 | |
200 => 'OK', | |
201 => 'Created', | |
202 => 'Accepted', | |
203 => 'Non-Authoritative Information', // since HTTP/1.1 | |
204 => 'No Content', | |
205 => 'Reset Content', | |
206 => 'Partial Content', | |
207 => 'Multi-Status', // WebDAV; RFC 4918 | |
208 => 'Already Reported', // WebDAV; RFC 5842 | |
226 => 'IM Used', // RFC 3229 | |
300 => 'Multiple Choices', | |
301 => 'Moved Permanently', | |
302 => 'Found', | |
303 => 'See Other', // since HTTP/1.1 | |
304 => 'Not Modified', | |
305 => 'Use Proxy', // since HTTP/1.1 | |
306 => 'Switch Proxy', | |
307 => 'Temporary Redirect', // since HTTP/1.1 | |
308 => 'Permanent Redirect', // approved as experimental RFC | |
400 => 'Bad Request', | |
401 => 'Unauthorized', | |
402 => 'Payment Required', | |
403 => 'Forbidden', | |
404 => 'Not Found', | |
405 => 'Method Not Allowed', | |
406 => 'Not Acceptable', | |
407 => 'Proxy Authentication Required', | |
408 => 'Request Timeout', | |
409 => 'Conflict', | |
410 => 'Gone', | |
411 => 'Length Required', | |
412 => 'Precondition Failed', | |
413 => 'Request Entity Too Large', | |
414 => 'Request-URI Too Long', | |
415 => 'Unsupported Media Type', | |
416 => 'Requested Range Not Satisfiable', | |
417 => 'Expectation Failed', | |
418 => 'I\'m a teapot', // RFC 2324 | |
419 => 'Authentication Timeout', // not in RFC 2616 | |
420 => 'Enhance Your Calm', // Twitter | |
420 => 'Method Failure', // Spring Framework | |
422 => 'Unprocessable Entity', // WebDAV; RFC 4918 | |
423 => 'Locked', // WebDAV; RFC 4918 | |
424 => 'Failed Dependency', // WebDAV; RFC 4918 | |
424 => 'Method Failure', // WebDAV) | |
425 => 'Unordered Collection', // Internet draft | |
426 => 'Upgrade Required', // RFC 2817 | |
428 => 'Precondition Required', // RFC 6585 | |
429 => 'Too Many Requests', // RFC 6585 | |
431 => 'Request Header Fields Too Large', // RFC 6585 | |
444 => 'No Response', // Nginx | |
449 => 'Retry With', // Microsoft | |
450 => 'Blocked by Windows Parental Controls', // Microsoft | |
451 => 'Redirect', // Microsoft | |
451 => 'Unavailable For Legal Reasons', // Internet draft | |
494 => 'Request Header Too Large', // Nginx | |
495 => 'Cert Error', // Nginx | |
496 => 'No Cert', // Nginx | |
497 => 'HTTP to HTTPS', // Nginx | |
499 => 'Client Closed Request', // Nginx | |
500 => 'Internal Server Error', | |
501 => 'Not Implemented', | |
502 => 'Bad Gateway', | |
503 => 'Service Unavailable', | |
504 => 'Gateway Timeout', | |
505 => 'HTTP Version Not Supported', | |
506 => 'Variant Also Negotiates', // RFC 2295 | |
507 => 'Insufficient Storage', // WebDAV; RFC 4918 | |
508 => 'Loop Detected', // WebDAV; RFC 5842 | |
509 => 'Bandwidth Limit Exceeded', // Apache bw/limited extension | |
510 => 'Not Extended', // RFC 2774 | |
511 => 'Network Authentication Required', // RFC 6585 | |
598 => 'Network read timeout error', // Unknown | |
599 => 'Network connect timeout error', // Unknown | |
); | |
if(isset($http_codes[$int])) { | |
return $http_codes[$int]; | |
} | |
return "Undefined Code"; | |
} | |
} | |
// collection object | |
class collection { | |
private $collection; | |
function __construct($array = array()) { | |
if(!empty($array) && is_array($array)) { | |
$this->collection = $array; | |
} else { | |
$this->collection = array(); | |
} | |
} | |
function set($array = array(), $force = false) { | |
if(!empty($array) && is_array($array)) { | |
$this->collection = $array; | |
return true; | |
} | |
if($force == true) { | |
$this->collection = array(); | |
return true; | |
} | |
return false; | |
} | |
function add($key, $value, $overwrite = true) { | |
$key = strtolower($key); | |
if(isset($this->collection[$key])) { | |
if($overwrite) { | |
$this->collection[$key] = $value; | |
return true; | |
} | |
return false; | |
} | |
$this->collection[$key] = $value; | |
return true; | |
} | |
function remove($key) { | |
$key = strtolower($key); | |
if(isset($this->collection[$key])) { | |
unset($this->collection[$key]); | |
} | |
return true; | |
} | |
function get($key) { | |
$key = strtolower($key); | |
if(isset($this->collection[$key])) { | |
return $this->collection[$key]; | |
} | |
return false; | |
} | |
function clear() { | |
$this->collection = array(); | |
return true; | |
} | |
function value($compact = true) { | |
if($compact) { | |
$result = array(); | |
foreach($this->collection as $key=>$value) { | |
$result[] = $key . ':' . $value; | |
} | |
return $result; | |
} | |
return $this->collection; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment