From eb1a3fe75a549ce190c5331d26a5fb1ff3157058 Mon Sep 17 00:00:00 2001 From: ajshort Date: Wed, 23 Mar 2011 20:05:29 +1100 Subject: [PATCH] API CHANGE: Separated the actual CURL request generation code from RestfulService::request() into RestfulService::curlRequest(). MINOR: Updated RestfulServiceTest to use a mock service rather than the actual site. This eliminates the need for ?usetestmanifesst. --- api/RestfulService.php | 141 +++++++++++++++++-------------- tests/api/RestfulServiceTest.php | 19 ++++- 2 files changed, 94 insertions(+), 66 deletions(-) diff --git a/api/RestfulService.php b/api/RestfulService.php index dea9de7da..e3f19217d 100644 --- a/api/RestfulService.php +++ b/api/RestfulService.php @@ -121,68 +121,9 @@ class RestfulService extends ViewableData { $response = unserialize($store); } else { - $ch = curl_init(); - $timeout = 5; - $useragent = "SilverStripe/" . SapphireInfo::Version(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_USERAGENT, $useragent); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); - if(!ini_get('open_basedir')) curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); - - // Add headers - if($this->customHeaders) { - $headers = array_merge((array)$this->customHeaders, (array)$headers); - } - - if($headers) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - - // Add authentication - if($this->authUsername) curl_setopt($ch, CURLOPT_USERPWD, "$this->authUsername:$this->authPassword"); - - // Add fields to POST and PUT requests - if($method == 'POST') { - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - } - else if($method == 'PUT') { - $put = fopen("php://temp", 'r+'); - fwrite($put, $data); - fseek($put, 0); - - curl_setopt($ch, CURLOPT_PUT, 1); - curl_setopt($ch, CURLOPT_INFILE, $put); - curl_setopt($ch, CURLOPT_INFILESIZE, strlen($data)); - } + $response = $this->curlRequest($url, $method, $data, $headers, $curlOptions); - // Apply proxy settings - if(is_array($this->proxy)) { - curl_setopt_array($ch, $this->proxy); - } - - // Set any custom options passed to the request() function - curl_setopt_array($ch, $curlOptions); - - // Run request - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - $responseBody = curl_exec($ch); - $curlError = curl_error($ch); - - // Problem verifying the server SSL certificate; just ignore it as it's not mandatory - if(strpos($curlError,'14090086') !== false) { - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - $responseBody = curl_exec($ch); - $curlError = curl_error($ch); - } - - $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if($curlError !== '' || $statusCode == 0) $statusCode = 500; - - $response = new RestfulService_Response($responseBody, $statusCode); - curl_close($ch); - - if($curlError === '' && !$response->isError()) { + if(!$response->isError()) { // Serialise response object and write to cache $store = serialize($response); file_put_contents($cache_path, $store); @@ -204,7 +145,83 @@ class RestfulService extends ViewableData { return $response; } - + + /** + * Actually performs a remote service request using curl. This is used by + * {@link RestfulService::request()}. + * + * @param string $url + * @param string $method + * @param array $data + * @param array $headers + * @param array $curlOptions + * @return RestfulService_Response + */ + public function curlRequest($url, $method, $data = null, $headers = null, $curlOptions = array()) { + $ch = curl_init(); + $timeout = 5; + $useragent = 'SilverStripe/' . SapphireInfo::Version(); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_USERAGENT, $useragent); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); + if(!ini_get('open_basedir')) curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + + // Add headers + if($this->customHeaders) { + $headers = array_merge((array)$this->customHeaders, (array)$headers); + } + + if($headers) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + // Add authentication + if($this->authUsername) curl_setopt($ch, CURLOPT_USERPWD, "$this->authUsername:$this->authPassword"); + + // Add fields to POST and PUT requests + if($method == 'POST') { + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + } elseif($method == 'PUT') { + $put = fopen("php://temp", 'r+'); + fwrite($put, $data); + fseek($put, 0); + + curl_setopt($ch, CURLOPT_PUT, 1); + curl_setopt($ch, CURLOPT_INFILE, $put); + curl_setopt($ch, CURLOPT_INFILESIZE, strlen($data)); + } + + // Apply proxy settings + if(is_array($this->proxy)) { + curl_setopt_array($ch, $this->proxy); + } + + // Set any custom options passed to the request() function + curl_setopt_array($ch, $curlOptions); + + // Run request + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + $responseBody = curl_exec($ch); + $curlError = curl_error($ch); + + // Problem verifying the server SSL certificate; just ignore it as it's not mandatory + if(strpos($curlError,'14090086') !== false) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + $responseBody = curl_exec($ch); + $curlError = curl_error($ch); + } + + $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if($curlError !== '' || $statusCode == 0) $statusCode = 500; + + $response = new RestfulService_Response($responseBody, $statusCode); + curl_close($ch); + + return $response; + } + /** * Returns a full request url * @param string diff --git a/tests/api/RestfulServiceTest.php b/tests/api/RestfulServiceTest.php index 2387e6354..5ea4f0cf2 100644 --- a/tests/api/RestfulServiceTest.php +++ b/tests/api/RestfulServiceTest.php @@ -94,13 +94,13 @@ class RestfulServiceTest extends SapphireTest { */ function testIncorrectData() { $connection = new RestfulService(Director::absoluteBaseURL(), 0); - $test1 = $connection->request('RestfulServiceTest_Controller/invalid?usetestmanifest=1&flush=1'); + $test1 = $connection->request('RestfulServiceTest_Controller/invalid'); $test1->xpath("\\fail"); } function testHttpErrorWithoutCache() { $connection = new RestfulServiceTest_MockRestfulService(Director::absoluteBaseURL(), 0); - $response = $connection->request('RestfulServiceTest_Controller/httpErrorWithoutCache?usetestmanifest=1&flush=1'); + $response = $connection->request('RestfulServiceTest_Controller/httpErrorWithoutCache'); $this->assertEquals(400, $response->getStatusCode()); $this->assertFalse($response->getCachedBody()); @@ -110,7 +110,7 @@ class RestfulServiceTest extends SapphireTest { function testHttpErrorWithCache() { $subUrl = 'RestfulServiceTest_Controller/httpErrorWithCache?usetestmanifest=1&flush=1'; - $connection = new RestfulService(Director::absoluteBaseURL(), 0); + $connection = new RestfulServiceTest_MockErrorService(Director::absoluteBaseURL(), 0); $this->createFakeCachedResponse($connection, $subUrl); $response = $connection->request($subUrl); @@ -271,4 +271,15 @@ class RestfulServiceTest_MockRestfulService extends RestfulService { return $response; } -} \ No newline at end of file +} + +/** + * A mock service that returns a 400 error for requests. + */ +class RestfulServiceTest_MockErrorService extends RestfulService { + + public function curlRequest() { + return new RestfulService_Response('HTTP Error', 400); + } + +}