Permalink
Browse files

API now processing JSON

  • Loading branch information...
1 parent b0157dd commit 7dd59d6181863d22fefa91c2ce70507a69bea2d7 @benkeen committed Jan 13, 2015
View
@@ -2,5 +2,5 @@
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
-RewriteRule ^api/v1/(.*)$ /generatedata/api/process.php?v=1&request=$1 [L]
+RewriteRule api/v1/(.*)$ api/process.php?request=$1 [QSA,NC,L]
</IfModule>
View
@@ -9,15 +9,15 @@
}
// requests from the same server don't have a HTTP_ORIGIN header
-if (!array_key_exists('HTTP_ORIGIN', $_SERVER)) {
- $_SERVER['HTTP_ORIGIN'] = $_SERVER['SERVER_NAME'];
+if (!array_key_exists("HTTP_ORIGIN", $_SERVER)) {
+ $_SERVER["HTTP_ORIGIN"] = $_SERVER["SERVER_NAME"];
}
-try {
- $API = new MyAPI($_REQUEST['request'], $_SERVER['HTTP_ORIGIN']);
- echo "...";
+header("Content-Type: application/json");
- //echo $API->processAPI();
+try {
+ $API = new GenerateDataAPI($_REQUEST["request"]);
+ echo json_encode($API->processAPI());
} catch (Exception $e) {
- echo json_encode(Array('error' => $e->getMessage()));
+ echo json_encode(array('error' => $e->getMessage()));
}
View
@@ -15,8 +15,8 @@
require_once(__DIR__ . "/resources/classes/Account.class.php");
require_once(__DIR__ . "/resources/classes/AjaxRequest.class.php");
-//require_once(__DIR__ . "/resources/classes/API.abstract.class.php");
-//require_once(__DIR__ . "/resources/classes/API.class.php");
+require_once(__DIR__ . "/resources/classes/API.abstract.class.php");
+require_once(__DIR__ . "/resources/classes/API.class.php");
require_once(__DIR__ . "/resources/classes/Constants.class.php");
require_once(__DIR__ . "/resources/classes/Core.class.php");
require_once(__DIR__ . "/resources/classes/CountryPlugin.abstract.class.php");
@@ -70,6 +70,9 @@ public function __construct($request) {
case 'DELETE':
case 'POST':
$this->request = $this->_cleanInputs($_POST);
+
+ // when we post raw JSON content, $_POST is empty. We need to access the information this way
+ $this->rawRequest = file_get_contents("php://input");
break;
case 'GET':
$this->request = $this->_cleanInputs($_GET);
@@ -88,16 +91,16 @@ public function processAPI() {
if ((int)method_exists($this, $this->endpoint) > 0) {
return $this->_response($this->{$this->endpoint}($this->args));
}
- return $this->_response("No Endpoint: $this->endpoint", 404);
+ return $this->_response("Sorry, that endpoint wasn't found.", 404);
}
private function _response($data, $status = 200) {
header("HTTP/1.1 " . $status . " " . $this->_requestStatus($status));
- return json_encode($data);
+ return $data;
}
private function _cleanInputs($data) {
- $clean_input = Array();
+ $clean_input = array();
if (is_array($data)) {
foreach ($data as $k => $v) {
$clean_input[$k] = $this->_cleanInputs($v);
@@ -1,38 +1,87 @@
<?php
-class MyAPI extends API
+/*
+
+*/
+class GenerateDataAPI extends API
{
-// protected $User;
+ public function data() {
- public function __construct($request, $origin) {
+ // validate the incoming JSON data to ensure it's valid
+ $errors = $this->validateJSON();
+ if ($errors) {
+ return $errors;
+ }
+
+ $json = @json_decode($this->rawRequest);
+
+ // validate the JSON contains the appropriate settings for the Code
+ $errors = $this->validateCoreSettings($json);
+ if ($errors) {
+ return $errors;
+ }
+ $errors = $this->validateDataTypeSettings($json);
+ if ($errors) {
+ return $errors;
+ }
+ $errors = $this->validateExportTypeSettings($json);
+ if ($errors) {
+ return $errors;
+ }
+ }
-// parent::__construct($request);
-/*
- // Abstracted out for example
- $APIKey = new Models\APIKey();
- $User = new Models\User();
- if (!array_key_exists('apiKey', $this->request)) {
- throw new Exception('No API Key provided');
- } else if (!$APIKey->verifyKey($this->request['apiKey'], $origin)) {
- throw new Exception('Invalid API Key');
- } else if (array_key_exists('token', $this->request) &&
- !$User->get('token', $this->request['token'])) {
+ // --------------------------------------------------------------------------------------------
+ // helpers
- throw new Exception('Invalid User Token');
+ private function validateJSON() {
+ if ($this->method !== "POST") {
+ return array("error" => "Sorry, this endpoint only accepts POST requests. Please see the help documentation.");
}
- $this->User = $User;
-*/
+ // try decoding the input to see if it's valid or not
+ $data = @json_decode($this->rawRequest);
+ if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
+ $errorMessage = Utils::getJSONErrorMessage(json_last_error());
+ return array("error" => ErrorCodes::API_INVALID_JSON, "error_details" => $errorMessage);
+ }
}
- protected function example() {
- echo "in example.";
+ /**
+ * The bare minimum valid JSON structure for the core is an object with the following keys:
+ * {
+ * "numRows": N, // where N is a number > 0
+ * "rows": [] // must be an array
+ * "export": {} // must be an object
+ * }
+ *
+ * Additional finer-tuned validation is performed later on.
+ * @param $json
+ * @return array
+ */
+ private function validateCoreSettings($json) {
+ if (!property_exists($json, "numRows")) {
+ return array("error" => ErrorCodes::API_INVALID_JSON_CONTENT, "error_details" => "Missing `numRows` property");
+ }
+ if (!is_int($json->numRows) || $json->numRows < 1) {
+ return array("error" => ErrorCodes::API_INVALID_JSON_CONTENT, "error_details" => "The `numRows` property must be an integer >= 1");
+ }
+ if (!property_exists($json, "rows")) {
+ return array("error" => ErrorCodes::API_INVALID_JSON_CONTENT, "error_details" => "Missing `rows` property");
+ }
+ if (!is_array($json->numRows)) {
+ return array("error" => ErrorCodes::API_INVALID_JSON_CONTENT, "error_details" => "The `rows` property must be an array");
+ }
+ if (!property_exists($json, "export")) {
+ return array("error" => ErrorCodes::API_INVALID_JSON_CONTENT, "error_details" => "Missing `export` property");
+ }
+ }
+
+ private function validateDataTypeSettings($json) {
+
+ }
-// if ($this->method == 'GET') {
-// return "Your name is " . $this->User->name;
-// } else {
-// return "Only accepts GET requests";
-// }
+ private function validateExportTypeSettings($json) {
+
}
}
@@ -13,4 +13,7 @@ class ErrorCodes {
const INVALID_PARAMS = 4;
const INVALID_REQUEST = 5;
const ACCOUNT_ALREADY_EXISTS = 6;
-}
+
+ const API_INVALID_JSON = "API_INVALID_JSON";
+ const API_INVALID_JSON_CONTENT = "API_INVALID_JSON_CONTENT";
+}
@@ -377,7 +377,8 @@ public static function isHash($var) {
/**
* A method to recursively encode an array (associative or indexed).
- * @param $array
+ * @param array
+ * @return array
*/
public static function utf8_encode_array($array) {
@@ -412,4 +413,36 @@ public static function utf8_encode_array($array) {
}
return $resultArray;
}
+
+ /**
+ * Returns a human-readable version of the JSON error codes, listed here:
+ * http://php.net/manual/en/function.json-last-error.php
+ * @param error
+ * @return string
+ */
+ public static function getJSONErrorMessage($errorCode) {
+ $map = array(
+ JSON_ERROR_NONE => "No error has occurred (JSON_ERROR_NONE)",
+ JSON_ERROR_DEPTH => "The maximum stack depth has been exceeded (JSON_ERROR_DEPTH)",
+ JSON_ERROR_STATE_MISMATCH => "Invalid or malformed JSON (JSON_ERROR_STATE_MISMATCH)",
+ JSON_ERROR_CTRL_CHAR => "Control character error, possibly incorrectly encoded (JSON_ERROR_CTRL_CHAR)",
+ JSON_ERROR_SYNTAX => "Syntax error (JSON_ERROR_SYNTAX)"
+ );
+
+ // now add the lah-de-dah fancy ones added in PHP versions > 5.3
+ if (defined('JSON_ERROR_UTF8')) {
+ $map[JSON_ERROR_UTF8] = "Malformed UTF-8 characters, possibly incorrectly encoded (JSON_ERROR_UTF8)";
+ }
+ if (defined('JSON_ERROR_RECURSION')) {
+ $map[JSON_ERROR_UTF8] = "One or more recursive references in the value to be encoded (JSON_ERROR_RECURSION)";
+ }
+ if (defined('JSON_ERROR_INF_OR_NAN')) {
+ $map[JSON_ERROR_UTF8] = "One or more NAN or INF values in the value to be encoded (JSON_ERROR_INF_OR_NAN)";
+ }
+ if (defined('JSON_ERROR_UNSUPPORTED_TYPE')) {
+ $map[JSON_ERROR_UTF8] = "A value of a type that cannot be encoded was given (JSON_ERROR_UNSUPPORTED_TYPE)";
+ }
+
+ return (array_key_exists($errorCode, $map)) ? $map[$errorCode] : "Unknown JSON error" . JSON_ERROR_SYNTAX;
+ }
}

0 comments on commit 7dd59d6

Please sign in to comment.