public function __construct($method, array $params, $strictly_typed = true) { $this->method = $method; $this->handler = $this->buildMethodHandler($method); $param_types = $this->handler->getParamTypes(); foreach ($param_types as $key => $spec) { if (ConduitAPIMethod::getParameterMetadataKey($key) !== null) { throw new ConduitException(pht('API Method "%s" defines a disallowed parameter, "%s". This ' . 'parameter name is reserved.', $method, $key)); } } $invalid_params = array_diff_key($params, $param_types); if ($invalid_params) { throw new ConduitException(pht('API Method "%s" does not define these parameters: %s.', $method, "'" . implode("', '", array_keys($invalid_params)) . "'")); } $this->request = new ConduitAPIRequest($params, $strictly_typed); }
private function decodeConduitParams(AphrontRequest $request, $method) { // Look for parameters from the Conduit API Console, which are encoded // as HTTP POST parameters in an array, e.g.: // // params[name]=value¶ms[name2]=value2 // // The fields are individually JSON encoded, since we require users to // enter JSON so that we avoid type ambiguity. $params = $request->getArr('params', null); if ($params !== null) { foreach ($params as $key => $value) { if ($value == '') { // Interpret empty string null (e.g., the user didn't type anything // into the box). $value = 'null'; } $decoded_value = json_decode($value, true); if ($decoded_value === null && strtolower($value) != 'null') { // When json_decode() fails, it returns null. This almost certainly // indicates that a user was using the web UI and didn't put quotes // around a string value. We can either do what we think they meant // (treat it as a string) or fail. For now, err on the side of // caution and fail. In the future, if we make the Conduit API // actually do type checking, it might be reasonable to treat it as // a string if the parameter type is string. throw new Exception(pht("The value for parameter '%s' is not valid JSON. All " . "parameters must be encoded as JSON values, including strings " . "(which means you need to surround them in double quotes). " . "Check your syntax. Value was: %s.", $key, $value)); } $params[$key] = $decoded_value; } $metadata = idx($params, '__conduit__', array()); unset($params['__conduit__']); return array($metadata, $params); } // Otherwise, look for a single parameter called 'params' which has the // entire param dictionary JSON encoded. $params_json = $request->getStr('params'); if (strlen($params_json)) { $params = null; try { $params = phutil_json_decode($params_json); } catch (PhutilJSONParserException $ex) { throw new PhutilProxyException(pht("Invalid parameter information was passed to method '%s'.", $method), $ex); } $metadata = idx($params, '__conduit__', array()); unset($params['__conduit__']); return array($metadata, $params); } // If we do not have `params`, assume this is a simple HTTP request with // HTTP key-value pairs. $params = array(); $metadata = array(); foreach ($request->getPassthroughRequestData() as $key => $value) { $meta_key = ConduitAPIMethod::getParameterMetadataKey($key); if ($meta_key !== null) { $metadata[$meta_key] = $value; } else { $params[$key] = $value; } } return array($metadata, $params); }