Skip to content

Instantly share code, notes, and snippets.

@hakre
Created December 26, 2011 13:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakre/1521174 to your computer and use it in GitHub Desktop.
Save hakre/1521174 to your computer and use it in GitHub Desktop.
Example of a request and response object with cUrl
<?php
/*
* @link http://codepad.viper-7.com/OtahKC
* @link http://stackoverflow.com/q/8632366/367456
*/
/**
* curl based request class that fullfils my needs
*/
class MyRequest
{
const GET = 1;
const POST = 2;
private $url;
private $method;
private $postFields = array();
private $cookieFile = 'cookies.txt';
private $returnHeaders = FALSE;
public function __construct($url, $method = self::GET)
{
$this->setURL($url);
$this->setMethod($method);
}
public function setURL($url)
{
if (!parse_url($url, PHP_URL_SCHEME))
throw new InvalidArgumentException(sprintf("Not a valid URL: %s.", $url));
$this->url = $url;
}
/**
* set request method
*
* @param int $method
* @throws InvalidArgumentException
* @return MyRequest (chaining)
*/
public function setMethod($method)
{
if (! in_array($method, array(self::GET, self::POST)))
throw new InvalidArgumentException(sprintf('Invalid method %d.', $method));
$this->method = $method;
return $this;
}
/**
* set post fields, will automatically set method to POST.
*
* @param array|string $postFields, empty array or string will result in clearing fields
* @throws InvalidArgumentException
* @return MyRequest (chaining)
*/
public function setPostFields($postFields)
{
if (is_string($postFields))
parse_str($postFields, $postFields);
if (!is_array($postFields))
throw new InvalidArgumentException('Post-Fields must be either string or array.');
$this->postFields = $postFields ? $postFields + $this->postFields : array();
$this->method = self::POST;
return $this;
}
public function returnHeaders($bool)
{
$this->returnHeaders = (bool) $bool;
return $this;
}
public function execute()
{
$curlHandle = curl_init($this->url);
if (!$curlHandle)
throw new RuntimeException(sprintf('Unable to initialize for %s.', $this->url));
// my request uses always cookies because I know it needs them:
curl_setopt($curlHandle, CURLOPT_COOKIEJAR, $this->cookieFile);
curl_setopt($curlHandle, CURLOPT_COOKIEFILE, $this->cookieFile);
// return headers in the output?
if ($this->returnHeaders)
{
curl_setopt($curlHandle, CURLOPT_HEADER, TRUE);
}
// my request should ignore some SSL errors because I know the site I request does
// not handle them properly (which is bad style):
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, FALSE);
// my request
if ($this->method === self::POST)
{
curl_setopt($curlHandle, CURLOPT_POST, 1); // Use POST (not GET)
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $this->postFields); // Insert headers
}
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
$buffer = curl_exec($curlHandle); // Get the results
if ($errorNo = curl_errno($curlHandle))
{
$error = curl_error($curlHandle);
curl_close($curlHandle);
throw new RuntimeException(sprintf('Request failed: (%d) %s.', $errorNo, $error));
}
curl_close($curlHandle);
return $buffer;
}
public function __toString()
{
return $this->execute();
}
}
class MyResponse
{
/**
* @var string
*/
private $buffer;
/**
* @var string
*/
private $headers;
/**
* @var DOMDocument
*/
private $doc;
public function __construct($buffer)
{
if (is_object($buffer))
{
$buffer = (string) $buffer;
}
if (!is_string($buffer))
{
throw new InvalidArgumentException(sprintf('Response takes a string, %s given.', gettype($buffer)));
}
$this->buffer = $buffer;
}
public function getDOMDocument()
{
if (!$this->doc)
{
$doc = new DOMDocument();
$setting = libxml_use_internal_errors(TRUE);
$result = $doc->loadHTML($this->buffer);
libxml_use_internal_errors($setting);
if (!$result)
{
throw new RuntimeException('Failed to parse HTML.');
}
$this->doc = $doc;
}
return $this->doc;
}
/**
* run xpath expression on response buffer
*
* @param string $expression
* @return array|SimpleXMLElement array if there are multiple matches, otherwise the single SimpleXMLElement
*/
public function xpath($expression)
{
$result = simplexml_import_dom($this->getDOMDocument())->xpath($expression);
if (count($result) === 1)
{
list($result) = $result;
}
return $result;
}
/**
* take out headers from buffer
*/
public function splitHeaders()
{
list($this->headers, $this->buffer) = explode("\r\n\r\n", $this->buffer, 2) + array('', '');
return $this;
}
public function getHeaders()
{
return $this->headers;
}
public function __toString()
{
return $this->buffer;
}
}
# simple get request
$request = new MyRequest('http://hakre.wordpress.com/');
$response = new MyResponse($request);
foreach($response->xpath('//div[@id="container"]//div[contains(normalize-space(@class), " post ")]') as $node)
{
if (!$node->h2->a) continue;
echo $node->h2->a, "\n<", $node->h2->a['href'] ,">\n\n";
}
# simple post request
$request = new MyRequest('https://example.wordpress.com/wp-login.php');
$postFields = array(
'log' => 'username',
'pwd' => 'password',
);
$request->setPostFields($postFields);
$response = new MyResponse($request->returnHeaders(1)->execute());
echo (string) $response; # output to view headers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment