/** * @param RequestInterface $request Request that received an error * @param CommandInterface $command Command that created the request * @param Operation $operation Operation that defines the request and errors * * @return \Closure Returns a closure * @throws ErrorResponseException */ protected function getErrorClosure(RequestInterface $request, CommandInterface $command, Operation $operation) { return function (Event $event) use($request, $command, $operation) { $response = $event['response']; foreach ($operation->getErrorResponses() as $error) { if (!isset($error['class'])) { continue; } if (isset($error['code']) && $response->getStatusCode() != $error['code']) { continue; } if (isset($error['reason']) && $response->getReasonPhrase() != $error['reason']) { continue; } $className = $error['class']; $errorClassInterface = __NAMESPACE__ . '\\ErrorResponseExceptionInterface'; if (!class_exists($className)) { throw new ErrorResponseException("{$className} does not exist"); } elseif (!is_subclass_of($className, $errorClassInterface)) { throw new ErrorResponseException("{$className} must implement {$errorClassInterface}"); } throw $className::fromCommand($command, $response); } }; }
public function testMixedParams() { $this->operation->setUri('bar{?limit,fields}'); $this->operation->addParam(new Parameter(array('name' => 'limit', 'location' => 'uri', 'required' => false))); $this->operation->addParam(new Parameter(array('name' => 'fields', 'location' => 'uri', 'required' => true))); $this->command['fields'] = array('id', 'name'); $request = $this->serializer->prepare($this->command); $this->assertEquals('http://foo.com/baz/bar?fields=' . urlencode('id,name'), (string) $request->getUrl()); }
public function testUsesParentParser() { $p = new OperationResponseParser(new VisitorFlyweight()); $operation = new Operation(); $operation->setServiceDescription(new ServiceDescription()); $op = new OperationCommand(array(), $operation); $op->setResponseParser($p)->setClient(new Client()); $op->prepare()->setResponse(new Response(200, array('Content-Type' => 'application/xml'), '<F><B>C</B></F>'), true); $this->assertInstanceOf('SimpleXMLElement', $op->execute()); }
/** * Checks if the excepted response is Multi or Single * * @param Operation $operation * @return bool */ protected function isMulti($operation) { if ($operation->getHttpMethod() != 'GET') { return false; } if ($operation->hasParam('id')) { return false; } return true; }
/** * @dataProvider iteratorProvider */ public function testDescribeIteratorTest(Operation $operation) { switch ($operation->getName()) { case 'DescribeImages': case 'DescribeReservedInstancesListings': case 'DescribeLicenses': self::log('Not running ' . $operation->getName()); return; } self::log('Testing iterator: ' . $operation->getName()); $iterator = $this->client->getIterator($operation->getName(), null, array('limit' => 25)); $this->assertLessThanOrEqual(25, iterator_count($iterator)); foreach ($iterator as $result) { $this->assertInternalType('array', $result); } }
/** * Create the root XML element to use with a request * * @param Operation $operation Operation object * * @return \SimpleXMLElement */ protected function createRootElement(Operation $operation) { static $defaultRoot = array('name' => 'Request'); // If no root element was specified, then just wrap the XML in 'Request' $root = $operation->getData('xmlRoot') ?: $defaultRoot; // Create the wrapping element with no namespaces if no namespaces were present if (empty($root['namespaces'])) { return new \SimpleXMLElement("<{$root['name']}/>"); } else { // Create the wrapping element with an array of one or more namespaces $xml = "<{$root['name']} "; foreach ((array) $root['namespaces'] as $prefix => $uri) { $xml .= is_numeric($prefix) ? "xmlns=\"{$uri}\" " : "xmlns:{$prefix}=\"{$uri}\" "; } return new \SimpleXMLElement($xml . "/>"); } }
protected function createRootElement(Operation $operation) { static $defaultRoot = array('name' => 'Request'); $root = $operation->getData('xmlRoot') ?: $defaultRoot; $encoding = $operation->getData('xmlEncoding'); $xmlWriter = $this->startDocument($encoding); $xmlWriter->startElement($root['name']); if (!empty($root['namespaces'])) { foreach ((array) $root['namespaces'] as $prefix => $uri) { $nsLabel = 'xmlns'; if (!is_numeric($prefix)) { $nsLabel .= ':' . $prefix; } $xmlWriter->writeAttribute($nsLabel, $uri); } } return $xmlWriter; }
/** * Create the root XML element to use with a request * * @param Operation $operation Operation object * * @return \XMLWriter */ protected function createRootElement(Operation $operation) { static $defaultRoot = array('name' => 'Request'); // If no root element was specified, then just wrap the XML in 'Request' $root = $operation->getData('xmlRoot') ?: $defaultRoot; // Allow the XML declaration to be customized with xmlEncoding $encoding = $operation->getData('xmlEncoding'); $xmlWriter = $this->startDocument($encoding); $xmlWriter->startElement($root['name']); // Create the wrapping element with no namespaces if no namespaces were present if (!empty($root['namespaces'])) { // Create the wrapping element with an array of one or more namespaces foreach ((array) $root['namespaces'] as $prefix => $uri) { $nsLabel = 'xmlns'; if (!is_numeric($prefix)) { $nsLabel .= ':' . $prefix; } $xmlWriter->writeAttribute($nsLabel, $uri); } } return $xmlWriter; }
/** * Create the root XML element to use with a request * * @param Operation $operation Operation object * * @return \SimpleXMLElement */ protected function createRootElement(Operation $operation) { static $defaultRoot = array('name' => 'Request'); // If no root element was specified, then just wrap the XML in 'Request' $root = $operation->getData('xmlRoot') ?: $defaultRoot; // Allow the XML declaration to be customized with xmlEncoding $declaration = '<?xml version="1.0"'; if ($encoding = $operation->getData('xmlEncoding')) { $declaration .= ' encoding="' . $encoding . '"'; } $declaration .= "?>"; // Create the wrapping element with no namespaces if no namespaces were present if (empty($root['namespaces'])) { return new \SimpleXMLElement("{$declaration}\n<{$root['name']}/>"); } else { // Create the wrapping element with an array of one or more namespaces $xml = "{$declaration}\n<{$root['name']} "; foreach ((array) $root['namespaces'] as $prefix => $uri) { $xml .= is_numeric($prefix) ? "xmlns=\"{$uri}\" " : "xmlns:{$prefix}=\"{$uri}\" "; } return new \SimpleXMLElement($xml . "/>"); } }
public function testHasAdditionalParameters() { $o = new Operation(array('additionalParameters' => array('type' => 'string', 'name' => 'binks'), 'parameters' => array('foo' => array('type' => 'integer')))); $this->assertEquals('string', $o->getAdditionalParameters()->getType()); $arr = $o->toArray(); $this->assertEquals(array('type' => 'string'), $arr['additionalParameters']); }
/** * Add a Swagger Api declaration which may consist of multiple operations * @param array consisting of path, description and array of operations * @param string URL inferring the base location for api path * @throws \Exception * @return Swizzle */ public function addApi(array $api, $baseUrl = '') { $service = $this->getServiceDescription(); if (!$baseUrl) { $baseUrl = $service->getBaseUrl(); } // resolve URL relative to base path for all operations $uri = implode('/', array(rtrim($baseUrl, '/'), ltrim($api['path'], '/'))); // keep domain only if not under service base path if (0 === strpos($uri, $service->getBaseUrl())) { $uri = preg_replace('!^https?://[^/]+!', '', $uri); } $this->debug('+ adding api %s ...', $uri); // no need for full url if relative to current // operation keys common to both swagger and guzzle static $common = array('items' => 1, 'summary' => 1); // translate swagger -> guzzle static $trans = array('type' => 'responseType', 'notes' => 'responseNotes', 'method' => 'httpMethod'); static $defaults = array('httpMethod' => 'GET'); foreach ($api['operations'] as $op) { $config = $this->transformArray($op, $common, $trans) + $defaults; $config['uri'] = $uri; // command must have a name, and must be unique across methods if (isset($op['nickname'])) { $id = $config['name'] = $op['nickname']; } else { $method = strtolower($config['httpMethod']); $id = $config['name'] = $method . '_' . str_replace('/', '_', trim($uri, '/')); } // allow custom command class, or global class for all commands if (isset($this->commandClasses[$id])) { $config['class'] = $this->commandClasses[$id]; } else { if (isset($this->commandClasses[''])) { $config['class'] = $this->commandClasses['']; } } // allow registered response class to override all response type logic if (isset($this->responseClasses[$id])) { $config['responseType'] = 'class'; $config['responseClass'] = $this->responseClasses[$id]; } else { if (isset($config['responseType'])) { // Check for primitive values first $type = $this->transformSimpleType($config['responseType']) or $type = $config['responseType']; // Array primitive may be typed with 'items' spec, but Guzzle operation ignores at top level if ('array' === $type) { if (isset($op['items'])) { $this->debug("! no modelling support for root arrays. Item types won't be validated"); } } else { if ('object' === $type) { $model = $this->addModel($op); $type = $model->getName(); } else { if ('number' === $type) { $this->debug('! number type defaulted to string as responseClass'); $type = 'string'; } else { if ('null' === $type) { $this->debug('! empty type "%s" defaulted to empty responseClass', $config['responseType']); $type = ''; } } } } // Ensure service contructor calls inferResponseType by having class but no type // This will handle Guzzle primatives, models and fall back to class $config['responseClass'] = $type; unset($config['responseType']); } } // handle parameters if (isset($op['parameters'])) { $config['parameters'] = $this->transformParams($op['parameters']); } else { $config['parameters'] = array(); } // handle responseMessages -> errorResponses if (isset($op['responseMessages'])) { $config['errorResponses'] = $this->transformResponseMessages($op['responseMessages']); } else { $config['errorResponses'] = array(); } // @todo how to deny additional parameters in command calls? // $config['additionalParameters'] = false; $operation = new Operation($config, $service); // Sanitize custom response class because Guzzle doesn't know it doesn't exist yet if (Operation::TYPE_CLASS === $operation->getResponseType()) { $class = $operation->getResponseClass(); if (empty($this->responseClasses[$id]) || $class !== $this->responseClasses[$id]) { throw new \Exception('responseType defaulted to class "' . $class . '" but class not registered'); } } $service->addOperation($operation); // next operation - } return $this; }
public function testHasResponseType() { // infers in the constructor $o = new Operation(array('responseClass' => 'array')); $this->assertEquals('primitive', $o->getResponseType()); // Infers when set $o = new Operation(); $this->assertEquals('primitive', $o->getResponseType()); $this->assertEquals('model', $o->setResponseType('model')->getResponseType()); }