XmlErrorParser.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <?php
  2. namespace Aws\Api\ErrorParser;
  3. use Aws\Api\Parser\PayloadParserTrait;
  4. use Aws\Api\Parser\XmlParser;
  5. use Aws\Api\Service;
  6. use Aws\Api\StructureShape;
  7. use Aws\CommandInterface;
  8. use Psr\Http\Message\ResponseInterface;
  9. /**
  10. * Parses XML errors.
  11. */
  12. class XmlErrorParser extends AbstractErrorParser
  13. {
  14. use PayloadParserTrait;
  15. protected $parser;
  16. public function __construct(Service $api = null, XmlParser $parser = null)
  17. {
  18. parent::__construct($api);
  19. $this->parser = $parser ?: new XmlParser();
  20. }
  21. public function __invoke(
  22. ResponseInterface $response,
  23. CommandInterface $command = null
  24. ) {
  25. $code = (string) $response->getStatusCode();
  26. $data = [
  27. 'type' => $code[0] == '4' ? 'client' : 'server',
  28. 'request_id' => null,
  29. 'code' => null,
  30. 'message' => null,
  31. 'parsed' => null
  32. ];
  33. $body = $response->getBody();
  34. if ($body->getSize() > 0) {
  35. $this->parseBody($this->parseXml($body, $response), $data);
  36. } else {
  37. $this->parseHeaders($response, $data);
  38. }
  39. $this->populateShape($data, $response, $command);
  40. return $data;
  41. }
  42. private function parseHeaders(ResponseInterface $response, array &$data)
  43. {
  44. if ($response->getStatusCode() == '404') {
  45. $data['code'] = 'NotFound';
  46. }
  47. $data['message'] = $response->getStatusCode() . ' '
  48. . $response->getReasonPhrase();
  49. if ($requestId = $response->getHeaderLine('x-amz-request-id')) {
  50. $data['request_id'] = $requestId;
  51. $data['message'] .= " (Request-ID: $requestId)";
  52. }
  53. }
  54. private function parseBody(\SimpleXMLElement $body, array &$data)
  55. {
  56. $data['parsed'] = $body;
  57. $prefix = $this->registerNamespacePrefix($body);
  58. if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
  59. $data['code'] = (string) $tempXml[0];
  60. }
  61. if ($tempXml = $body->xpath("//{$prefix}Message[1]")) {
  62. $data['message'] = (string) $tempXml[0];
  63. }
  64. $tempXml = $body->xpath("//{$prefix}RequestId[1]");
  65. if (isset($tempXml[0])) {
  66. $data['request_id'] = (string)$tempXml[0];
  67. }
  68. }
  69. protected function registerNamespacePrefix(\SimpleXMLElement $element)
  70. {
  71. $namespaces = $element->getDocNamespaces();
  72. if (!isset($namespaces[''])) {
  73. return '';
  74. }
  75. // Account for the default namespace being defined and PHP not
  76. // being able to handle it :(.
  77. $element->registerXPathNamespace('ns', $namespaces['']);
  78. return 'ns:';
  79. }
  80. protected function payload(
  81. ResponseInterface $response,
  82. StructureShape $member
  83. ) {
  84. $xmlBody = $this->parseXml($response->getBody(), $response);
  85. $prefix = $this->registerNamespacePrefix($xmlBody);
  86. $errorBody = $xmlBody->xpath("//{$prefix}Error");
  87. if (is_array($errorBody) && !empty($errorBody[0])) {
  88. return $this->parser->parse($member, $errorBody[0]);
  89. }
  90. }
  91. }