Skip to content

Instantly share code, notes, and snippets.

@yattias
Created November 17, 2011 14:49
Show Gist options
  • Save yattias/1373304 to your computer and use it in GitHub Desktop.
Save yattias/1373304 to your computer and use it in GitHub Desktop.
A very good function for executing service calls
<?php
/* @author: K0b3 Attias
* Executes a services call to a specific endpoint using curl with a number of options
* TODO: Modify the params to be a single object with multiple options
* @since 09/02/11
* @param <string> $service: The service to execute the call on (defined as a constant in one of the includes files)
* @param <string> $method: The method that will be called on the service (defined as a constant in one of the includes files)
* @param <string> $http_method: HTTP method
* @param <array> $params: Params which will be passed to the endpoint
* @param <bool> $verbosity: Return values can either be just the response or an array
* containing the http code, method, url, params, and response if this flag is set to TRUE
* @param <array> $options: Array of CURL options (for curl_setopt_array)
* @return FALSE on error OR the server response on a 2XX reply and verbosity = 0 OR array of all params and http status if verbosity = 1
* */
function rtr_services_exec($service, $method, $params, $http_method, $verbosity = 0, $options = array()) {
global $user;
$response = NULL;
try {
//Initialize connection and save curl handler
$ch = curl_init();
$url = $service . "/" . $method;
$serialized_params = NULL;
//Serialize params...http_build_query DOES NOT PLAY WELL with curl! Do Not use!
foreach ($params as $key => $value) {
if (is_array($params[$key])) {
foreach ($params[$key] as $k => $v) {
$serialized_params .= urlencode($key) . "=" . urlencode($v) . "&";
}
} else {
$serialized_params .= urlencode($key) . "=" . urlencode($value) . "&";
}
}
$serialized_params = rtrim($serialized_params, '&');
//Notify log
rtr_info("### SERVICE CALL -- SERVICE: " . $service . " -- METHOD: " . $method . " -- PARAMS: " . $serialized_params . " ### ");
//Set maximum number of seconds to connect with the service
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, RTR_API_TIMEOUT_SECONDS);
//Set maximum number of seconds to try and execute request
curl_setopt($ch, CURLOPT_TIMEOUT, RTR_API_TIMEOUT_SECONDS);
//This could be a liability if someone is passing URL, HTTPGET, POST, etc options)
if (sizeof($options)) {
//ASSERT: options specified, set them.
curl_setopt_array($ch, $options);
}
//Set curl method
switch (strtoupper($http_method)) {
case 'GET':
//Set URL
curl_setopt($ch, CURLOPT_URL, $url . "?" . $serialized_params);
curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
break;
case 'POST':
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, sizeof($params));
curl_setopt($ch, CURLOPT_POSTFIELDS, $serialized_params);
break;
default:
curl_setopt($ch, CURL_HTTPGET, $serialized_params); // default to get
break;
}
//TODO: Add support for PUT requests
//Return response as string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//Execute curl
$response = curl_exec($ch);
//Info
$response_info = curl_getinfo($ch);
//TODO: Don't rely on a 200 only response code as sucess, talk to infra on proper response set
if ($response_info['http_code'] != 200 && $verbosity == 0) {
//ASSERT: Error has occured
throw new Exception('bad_http_code');
} else {
switch($verbosity) {
case 0:
$return = $response;
break;
case 1:
if ($response_info['http_code'] != 200) {
watchdog("rtr_services", __FUNCTION__ . ": TOOK " . curl_getinfo( $ch, CURLINFO_TOTAL_TIME ) . " SECS, RETURNED HTTP CODE " . $response_info['http_code'] . " AND CURL ERROR " . curl_error($ch) . " " . $url);
} else {
watchdog("rtr_services", __FUNCTION__ . ": TOOK " . curl_getinfo( $ch, CURLINFO_TOTAL_TIME ) . " SECS, RETURNED HTTP CODE " . $response_info['http_code'] . " AND RESPONSE " . $response . " " . $url . ". REQUEST TOOK " . curl_getinfo( $ch, CURLINFO_TOTAL_TIME ) . " SECONDS");
}
$return = array(
"http_code" => $response_info['http_code']
, "url" => $url
, "params" => $serialized_params
, "method" => $http_method
, "response" => $response
);
break;
default:
$return = $response;
break;
}
}
//Close curl handler
curl_close($ch);
} catch (Exception $e) {
switch ($e->getMessage()) {
case 'bad_http_code':
rtr_warn('Request to URL failed: ' . $url . PHP_EOL . 'Reason: HTTP Code' . $response_info['http_code']);
break;
default:
rtr_warn('An exception occured while trying to execute service call o_0' . PHP_EOL . 'Error: ' . $e->getMessage());
break;
}
$return = FALSE;
}
return $return;
}
?>
@yattias
Copy link
Author

yattias commented Nov 17, 2011

Actually, the only thing left to do to make it even better is to have different behavior depending on http codes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment