Created
January 3, 2014 18:42
-
-
Save matthijn/8243747 to your computer and use it in GitHub Desktop.
Curl emulator for App Engine. This is in no way a complete emulation, but it is enough to make the Podio PHP API Client work.
This file contains hidden or 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 | |
/* A quick emulator for common curl function so code based on CURL works on AppEngine */ | |
if(!function_exists('curl_init')) | |
{ | |
// The curl option constants, when there is no curl they are not defined so we define them here | |
// Some options don't do anything, they just prefent crashes when they are here (see the setOpt method for the support of different options) | |
define('CURLOPT_RETURNTRANSFER', 'CURLOPT_RETURNTRANSFER'); | |
define('CURLOPT_SSL_VERIFYPEER', 'CURLOPT_SSL_VERIFYPEER'); | |
define('CURLOPT_SSL_VERIFYHOST', 'CURLOPT_SSL_VERIFYHOST'); | |
define('CURLOPT_USERAGENT', 'CURLOPT_USERAGENT'); | |
define('CURLOPT_HEADER', 'CURLOPT_HEADER'); | |
define('CURLOPT_CUSTOMREQUEST', 'CURLOPT_CUSTOMREQUEST'); | |
define('CURLOPT_POST', 'CURLOPT_POST'); | |
define('CURLOPT_POSTFIELDS', 'CURLOPT_POSTFIELDS'); | |
define('CURLOPT_HTTPHEADER', 'CURLOPT_HTTPHEADER'); | |
define('CURLOPT_URL', 'CURLOPT_URL'); | |
// curl info constants | |
define('CURLINFO_HEADER_SIZE', 'CURLINFO_HEADER_SIZE'); | |
define('CURLINFO_HTTP_CODE', 'CURLINFO_HTTP_CODE'); | |
define('CURLINFO_HEADER_OUT', 'CURLINFO_HEADER_OUT'); // This seems to be an option? | |
define('CURLINFO_TOTAL_TIME', 'CURLINFO_TOTAL_TIME'); | |
class AECurl | |
{ | |
// Storing the result in here | |
private $result; | |
// The headers of the result will be stored here | |
private $responseHeader; | |
public function AECurl($url) | |
{ | |
$this->CURLOPT_URL = $url; | |
} | |
public function setOpt($option, $value) | |
{ | |
$this->$option = $value; | |
} | |
public function getInfo($opt=0) | |
{ | |
if(!$this->result) | |
{ | |
$this->fetchResult(); | |
} | |
if($opt == CURLINFO_HEADER_SIZE) | |
{ | |
// Calculate header size | |
$responseSize = 0; | |
foreach($this->responseHeader as $header) | |
{ | |
$responseSize += (strlen($header) + 1); // The one is for each newline | |
} | |
return $responseSize; | |
} | |
if($opt == CURLINFO_HTTP_CODE) | |
{ | |
// Return the header status code | |
$matches = array(); | |
preg_match('#HTTP/\d+\.\d+ (\d+)#', $this->responseHeader[0], $matches); | |
return intval($matches[1]); | |
} | |
else | |
{ | |
throw new \Exception("No support in Curl wrapper for: " . $opt); | |
} | |
} | |
public function exec() | |
{ | |
$this->fetchResult(); | |
// Curl normally returns the headers with the content, so that is what we are doing here | |
$headers = implode("\n", $this->responseHeader); | |
$fullResult = $headers . "\n" . $this->result; | |
if($this->CURLOPT_RETURNTRANSFER == false) | |
{ | |
echo $fullResult; | |
} | |
else | |
{ | |
return $fullResult; | |
} | |
} | |
private function fetchResult() | |
{ | |
$parsedUrl = parse_url($this->CURLOPT_URL); | |
// Create the context for this request based on the curl parameters | |
// Determine the method | |
if(!$this->CURLOPT_CUSTOMREQUEST && $this->CURLOPT_POST) | |
{ | |
$method = 'POST'; | |
} | |
else | |
{ | |
$method = $this->getValue(CURLOPT_CUSTOMREQUEST, 'GET'); | |
} | |
// Add the post header if type is post and it has not been added | |
if($method == 'POST') | |
{ | |
if(is_array($this->getValue(CURLOPT_HTTPHEADER))) | |
{ | |
$found = false; | |
foreach($this->CURLOPT_HTTPHEADER as $header) | |
{ | |
if(strtolower($header) == strtolower('Content-type: application/x-www-form-urlencoded')) | |
{ | |
$found = true; | |
} | |
} | |
} | |
else | |
{ | |
$this->CURLOPT_HTTPHEADER[] = 'Content-type: application/x-www-form-urlencoded'; | |
} | |
} | |
// Determine the content which can be an array or a string | |
if(is_array($this->CURLOPT_POSTFIELDS)) | |
{ | |
$content = http_build_query($this->CURLOPT_POSTFIELDS); | |
} | |
else | |
{ | |
$content = $this->CURLOPT_POSTFIELDS; | |
} | |
// 'http' instead of $parsedUrl['scheme']; https doest work atm | |
$options = array( | |
'http' => array( | |
'method' => $method, | |
'header' => $this->getValue(CURLOPT_HTTPHEADER), | |
'content' => $content | |
) | |
); | |
// SSL settings when set | |
// if($parsedUrl['scheme'] == 'https') | |
// { | |
// $context['https']['ssl'] = array( | |
// 'verify_peer' => $this->getValue(CURLOPT_SSL_VERIFYPEER, false) | |
// ); | |
// } | |
$context = stream_context_create($options); | |
try | |
{ | |
$this->result = file_get_contents($this->CURLOPT_URL, false, $context); | |
} | |
catch(\exception $e) | |
{ | |
$this->result = null; | |
} | |
$this->responseHeader = $http_response_header; | |
} | |
private function getValue($value, $default = null) | |
{ | |
if($this->$value) | |
{ | |
return $this->$value; | |
} | |
return $default; | |
} | |
} | |
function curl_init($url = null) | |
{ | |
return new AECurl($url); | |
} | |
function curl_setopt($ch, $option, $value) | |
{ | |
$ch->setOpt($option, $value); | |
} | |
function curl_exec($ch) | |
{ | |
return $ch->exec(); | |
} | |
function curl_getinfo($ch, $opt=0) | |
{ | |
return $ch->getInfo($opt); | |
} | |
} |
Re: "Invalid headers. Must be a string"
Lines 113, 141 - Try changing the associative header array to a string (without url encoding):
if (is_array($this->getValue(CURLOPT_HTTPHEADER))) {
array_walk($this->getValue(CURLOPT_HTTPHEADER), create_function('&$i,$k','$i="$k: $i";'));
$this->CURLOPT_HTTPHEADER[] = implode($this->getValue(CURLOPT_HTTPHEADER),"\r\n");
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi! Very useful piece! :) I'm using it on GAE for a podio php implementation. Everything works fine locally...However, when I deploy, I got errors such as "Invalid headers. Must be a string" on file_get_contents in curlEmulator.php. Is that something you ever encounter?
Thanks!