From 318a954400de9e6587455e754ebb8b9ab96c3fc5 Mon Sep 17 00:00:00 2001 From: Evan Seguin Date: Fri, 31 Aug 2012 16:36:51 -0700 Subject: [PATCH] Refactored library. Added new validation and excpetions. Added JSON input support --- .../mashape/exceptions/ExceptionConstants.php | 23 +++- main/mashape/http/HttpClient.php | 109 ++++++++++-------- main/mashape/http/HttpMethod.php | 3 +- main/mashape/http/HttpUtils.php | 87 ++++++++++++++ main/mashape/http/UrlUtils.php | 78 +------------ 5 files changed, 173 insertions(+), 127 deletions(-) create mode 100644 main/mashape/http/HttpUtils.php diff --git a/main/mashape/exceptions/ExceptionConstants.php b/main/mashape/exceptions/ExceptionConstants.php index 3a6ddb6..e6385ee 100755 --- a/main/mashape/exceptions/ExceptionConstants.php +++ b/main/mashape/exceptions/ExceptionConstants.php @@ -25,13 +25,30 @@ */ define("EXCEPTION_NOTSUPPORTED_HTTPMETHOD_CODE", 1003); -define("EXCEPTION_NOTSUPPORTED_HTTPMETHOD", "HTTP method not supported. Only DELETE, GET, POST, PUT are supported"); +define("EXCEPTION_NOTSUPPORTED_HTTPMETHOD", + "HTTP method not supported. Only DELETE, GET, POST, PUT are supported"); + +define("EXCEPTION_CONTENT_TYPE_JSON_ARRAY_CODE", 1004); +define("EXCEPTION_CONTENT_TYPE_JSON_ARRAY", + "Content Type JSON does not accept array parameters. Parameters should be" + ." a JSON string"); + +define("EXCEPTION_CONTENT_TYPE_NON_ARRAY_CODE", 1005); +define("EXCEPTION_CONTENT_TYPE_NON_ARRAY", + "Parameters must be an array unless content type is set to JSON"); + +define("EXCEPTION_CONTENT_TYPE_JSON_QUERYAUTH_CODE", 1006); +define("EXCEPTION_CONTENT_TYPE_JSON_QUERYAUTH", + "Query Authentication cannot be used in conjunction with content type JSON"); define("EXCEPTION_NOTSUPPORTED_CONTENTTYPE_CODE", 415); -define("EXCEPTION_NOTSUPPORTED_CONTENTTYPE", "Content Type not supported. Currently only application/x-www-form-urlencoded and multipart/form-data are supported"); +define("EXCEPTION_NOTSUPPORTED_CONTENTTYPE", + "Content Type not supported. Currently only application/x-www-form-urlencoded, " + ."application/json, and multipart/form-data are supported"); define("EXCEPTION_GET_INVALID_CONTENTTYPE_CODE", 415); -define("EXCEPTION_GET_INVALID_CONTENTTYPE", "A GET request must have a content type of application/x-www-form-urlencoded"); +define("EXCEPTION_GET_INVALID_CONTENTTYPE", "A GET request must have a content" + ." type of application/x-www-form-urlencoded or application/json"); define("EXCEPTION_SYSTEM_ERROR_CODE", 2000); define("EXCEPTION_JSONDECODE_REQUEST", "Can't deserialize the response JSON: %s"); diff --git a/main/mashape/http/HttpClient.php b/main/mashape/http/HttpClient.php index 755b9a2..fda6585 100755 --- a/main/mashape/http/HttpClient.php +++ b/main/mashape/http/HttpClient.php @@ -28,6 +28,7 @@ require_once(dirname(__FILE__) . "/../exceptions/MashapeClientException.php"); require_once(dirname(__FILE__) . "/HttpMethod.php"); require_once(dirname(__FILE__) . "/ContentType.php"); require_once(dirname(__FILE__) . "/UrlUtils.php"); +require_once(dirname(__FILE__) . "/HttpUtils.php"); require_once(dirname(__FILE__) . "/MashapeResponse.php"); require_once(dirname(__FILE__) . "/../authentication/HeaderAuthentication.php"); require_once(dirname(__FILE__) . "/../authentication/BasicAuthentication.php"); @@ -37,13 +38,15 @@ require_once(dirname(__FILE__) . "/../authentication/QueryAuthentication.php"); class HttpClient { - public static function doRequest($httpMethod, $url, $parameters, $authHandlers, $contentType = ContentType::FORM, $encodeJson = true) { + public static function doRequest($httpMethod, $url, $parameters, + $authHandlers, $contentType = ContentType::FORM, $encodeJson = true) { + HttpUtils::cleanParameters($parameters); - if (!($httpMethod == HttpMethod::DELETE || $httpMethod == HttpMethod::GET || - $httpMethod == HttpMethod::POST || $httpMethod == HttpMethod::PUT)) { - throw new MashapeClientException(EXCEPTION_NOTSUPPORTED_HTTPMETHOD, EXCEPTION_NOTSUPPORTED_HTTPMETHOD_CODE); + if ($authHandlers == null) { + $authHandlers = array(); } + self::validateRequest($httpMethod, $url, $parameters, $authHandlers, $contentType); $response = self::execRequest($httpMethod, $url, $parameters, $authHandlers, $contentType); if ($encodeJson) { @@ -53,66 +56,72 @@ class HttpClient { return $response; } - private static function execRequest($httpMethod, $url, $parameters, $authHandlers, $contentType) { - $data = null; - if ($parameters == null) { - $parameters = array(); + private static function validateRequest($httpMethod, $url, $parameters, $authHandlers, $contentType) { + if ( !($httpMethod == HttpMethod::DELETE + || $httpMethod == HttpMethod::GET + || $httpMethod == HttpMethod::POST + || $httpMethod == HttpMethod::PUT + || $httpMethod == HttpMethod::PATCH)) { + // we only support these HTTP methods. + throw new MashapeClientException(EXCEPTION_NOTSUPPORTED_HTTPMETHOD, + EXCEPTION_NOTSUPPORTED_HTTPMETHOD_CODE); } - if ($authHandlers == null) { - $authHandlers = array(); + if ($contentType == ContentType::JSON && is_array($parameters)) { + // Content type JSON does not allow array parameters. + throw new MashapeClientException( + EXCEPTION_CONTENT_TYPE_JSON_ARRAY, + EXCEPTION_CONTENT_TYPE_JSON_ARRAY_CODE); } - - $headers = array(); - $headers[] = UrlUtils::generateClientHeaders(); - // Authentication - foreach($authHandlers as $handler) { - if ($handler instanceof QueryAuthentication) { - $parameters = array_merge($parameters, $handler->handleParams()); - } else if ($handler instanceof HeaderAuthentication) { - $headers[] = $handler->handleHeader(); - } + if (!is_array($parameters) && $contentType != ContentType::JSON) { + // Raw parameters are only allows for ContentType::JSON + throw new MashapeClientException( + EXCEPTION_CONTENT_TYPE_NON_ARRAY, + EXCEPTION_CONTENT_TYPE_NON_ARRAY_CODE); } - - UrlUtils::prepareRequest($url, $parameters, ($httpMethod != HttpMethod::GET) ? true : false); - - if ($httpMethod != HttpMethod::GET) { - switch ($contentType) { - case ContentType::FORM: - $data = http_build_query($parameters); - break; - case ContentType::MULTIPART: - $data = $parameters; - break; - case ContentType::JSON: - // TODO support json - default: - throw new MashapeClientException( - EXCEPTION_NOTSUPPORTED_CONTENTTYPE, - EXCEPTION_NOTSUPPORTED_CONTENTTYPE_CODE); - } - } else if ($contentType != ContentType::FORM) { + if ($httpMethod == HttpMethod::GET && $contentType != ContentType::FORM) { // if we have a GET request that is anything other than urlencoded // form data, we shouldn't allow it. throw new MashapeClientException( EXCEPTION_GET_INVALID_CONTENTTYPE, EXCEPTION_GET_INVALID_CONTENTTYPE_CODE); } - $ch = curl_init (); + if ($contentType == ContentType::JSON) { + foreach ($authHandlers as $handler) { + if ($handler instanceof QueryAuthentication) { + // bad. No room for query auth parameters if the whole body is json + throw new MashapeClientException( + EXCEPTION_CONTENT_TYPE_JSON_QUERYAUTH, + EXCEPTION_CONTENT_TYPE_JSON_QUERYAUTH_CODE); + } + } + } + } - // prepare the request - curl_setopt ($ch, CURLOPT_URL , $url); - if ($httpMethod != HttpMethod::GET) { + private static function execRequest($httpMethod, $url, $parameters, $authHandlers, $contentType) { + // first, collect the headers and parameters we'll need from the authentication handlers + list($headers, $authParameters) = HttpUtils::handleAuthentication($authHandlers); + if (is_array($parameters)) { + $parameters = array_merge($parameters, $authParameters); + } + + // prepare the request + $ch = curl_init (); + + if ($httpMethod == HttpMethod::GET) { + $url = UrlUtils::buildUrlWithQueryString($url, $parameters); + } else { + $data = HttpUtils::buildDataForContentType($contentType, $parameters, $headers); curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, $httpMethod); - //curl_setopt ($ch, CURLOPT_POST, 1); - curl_setopt ($ch, CURLOPT_POSTFIELDS, $parameters); - } + curl_setopt ($ch, CURLOPT_POSTFIELDS, $data); + } + curl_setopt ($ch, CURLOPT_URL , $url); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers); - curl_setopt ($ch, CURLINFO_HEADER_OUT, true); - $response = curl_exec($ch); + curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt ($ch, CURLINFO_HEADER_OUT, true); + $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $responseHeaders = curl_getinfo($ch, CURLINFO_HEADER_OUT); - curl_close($ch); + curl_close($ch); return new MashapeResponse($response, $httpCode, $responseHeaders); } diff --git a/main/mashape/http/HttpMethod.php b/main/mashape/http/HttpMethod.php index 43cf83a..3984db6 100755 --- a/main/mashape/http/HttpMethod.php +++ b/main/mashape/http/HttpMethod.php @@ -30,6 +30,7 @@ class HttpMethod const GET = "GET"; const POST = "POST"; const PUT = "PUT"; + const PATCH = "PATCH"; } -?> \ No newline at end of file +?> diff --git a/main/mashape/http/HttpUtils.php b/main/mashape/http/HttpUtils.php new file mode 100644 index 0000000..00ff336 --- /dev/null +++ b/main/mashape/http/HttpUtils.php @@ -0,0 +1,87 @@ +. + * + * + * The author of this software is Mashape, Inc. + * For any question or feedback please contact us at: support@mashape.com + * + */ + +class HttpUtils { + + public static function cleanParameters(&$parameters) { + if ($parameters == null) { + $parameters = array(); + } else if (is_array($parameters)) { + // Remove null parameters + $keys = array_keys($parameters); + for ($i = 0;$ihandleParams()); + } else if ($handler instanceof HeaderAuthentication) { + $headers[] = $handler->handleHeader(); + } + } + return array($headers, $parameters); + } + + public static function generateClientHeaders() { + $headers = "User-Agent: mashape-php/1.0: "; + return $headers; + } +} + diff --git a/main/mashape/http/UrlUtils.php b/main/mashape/http/UrlUtils.php index 75dd4e2..fe842ef 100755 --- a/main/mashape/http/UrlUtils.php +++ b/main/mashape/http/UrlUtils.php @@ -24,82 +24,14 @@ * */ -define("PLACEHOLDER_REGEX", "/\{([\w\.]+)\}/"); class UrlUtils { - public static function prepareRequest(&$url, &$parameters, $addRegularQueryStringParameters = false) { - if ($parameters == null) { - $parameters = array(); + public static function buildUrlWithQueryString($url, $parameters) { + foreach ($parameters as $paramKey => $paramValue) { + $delimiter = (strpos($url, "?") === false) ? "?" : "&"; + $url .= $delimiter . $paramKey . "=" . urlencode($paramValue); } - // Remove null parameters - $keys = array_keys($parameters); - for ($i = 0;$i 1) { - $bracketedMatches = $matches[0]; - $plainMatches = $matches[1]; - foreach ($plainMatches as $index => $key) { - if (array_key_exists($key, $parameters)) { - $finalUrl = str_replace($bracketedMatches[$index], rawurlencode($parameters[$key]), $finalUrl); - unset($parameters[$key]); - } else { - $finalUrl = preg_replace("/&?[\w]*=?\{" . $key . "\}/", "", $finalUrl); - } - } - } - - $finalUrl = str_replace("?&", "?", $finalUrl); - $finalUrl = preg_replace("/\?$/", "", $finalUrl); - - if ($addRegularQueryStringParameters) { - // Get regular query string parameters - self::addRegularQueryStringParameters($finalUrl, $parameters); - } else { - foreach ($parameters as $paramKey => $paramValue) { - $delimiter = (strpos($finalUrl, "?") === false) ? "?" : "&"; - $finalUrl .= $delimiter . $paramKey . "=" . urlencode($paramValue); - } - } - - $url = $finalUrl; - } - - private static function addRegularQueryStringParameters($url, &$parameters) { - $urlParts = explode("?", $url); - if (count($urlParts) > 1) { - $queryString = $urlParts[1]; - $queryStringParameters = explode("&", $queryString); - - foreach ($queryStringParameters as $queryStringParameter) { - $queryStringParameterParts = explode("=", $queryStringParameter); - if (count($queryStringParameterParts) > 1) { - list($paramKey, $paramValue) = $queryStringParameterParts; - if (!self::isPlaceHolder($paramValue)) { - $parameters[$paramKey] = $paramValue; - } - } - } - } - } - - private static function isPlaceHolder($value) { - return preg_match(PLACEHOLDER_REGEX, $value); - } - - public static function generateClientHeaders() { - $headers = "User-Agent: mashape-php/1.0: "; - return $headers; + return $url; } }