Как выбрать между разными портами в SOAP WSDL в PHP? - PullRequest
2 голосов
/ 22 июля 2010

WSDL Amazon AWS SQS (по адресу https://sqs.us -east-1.amazonaws.com / doc / 2009-02-01 / QueueService.wsdl ) перечисляет несколько «портов» с разными «адресами»(в нижней части файла), в котором указываются адреса HTTP и HTTPS для службы.

Использование объекта PHP SOAP:

$aws_ns = 'http://security.amazonaws.com/doc/2007-01-01/';
$sc = new SoapClient('https://sqs.us-east-1.amazonaws.com/doc/2009-02-01/QueueService.wsdl');
$sc->__setSoapHeaders(new SoapHeader($aws_ns, 'AWSAccessKeyId', 'MyAccessKey'));
$action = "ListQueues";
$ts = date('c');
$hash = base64_encode(hash_hmac('sha1', $action.$ts, 'MyPrivateKey', true));
try {
  $rs = $sc->__soapCall($action, array(), NULL, array(
    new SoapHeader($aws_ns, 'Signature', $hash),
    new SoapHeader($aws_ns, 'Timestamp', $ts)
  ));
} catch (SoapFault $f) {
  echo "ERROR: ".$f->faultcode."-".$f->faultstring."\n";
}

Запуск этого кода дает «ОШИБКУ: aws:Требуется соединение Client.RequiresSSL-SSL для обратно совместимой аутентификации SOAP. ";он использует первый «порт» (HTTP) для связи со службой AWS, что не разрешено при такой аутентификации.

Если я добавлю $sc->__setLocation('https://queue.amazonaws.com'); (URL-адрес скопирован и вставлен из WSDLfile) до строки __soapCall, она работает нормально, но как я могу сказать объекту SoapClient использовать другой порт в WSDL, вместо того, чтобы указывать его в качестве статической строки, если они изменят URL-адрес HTTPS в будущем?

1 Ответ

1 голос
/ 25 июля 2010

Насколько я знаю, нет простого способа сказать SoapClient использовать другой.Если необходимо изменить только с http на https, а все остальные вещи равны, вы можете переопределить какой-либо метод своим собственным классом:

class HttpsPortSoapClient extends Soapclient {
  function __doRequest($request,$location,$action,$version,$one_way = 0 ){
    $locationparts = parse_url($location);
    if(isset($locationparts['scheme']) && $locationparts['scheme'] == 'http'){
      if(function_exists('http_build_url')){
        $location = http_build_url($locationparts,array('scheme'=>'https'));
      } else {
        //the long way around:
        $location = 'https://';
        if(isset($locationparts['user'])){
          $location .= $locationparts['user'];
          if(isset($locationparts['pass']))$location .= ':'.$locationparts['pass'];
          $location .= '@';
        }
        if(isset($locationparts['host']))  $location .= $locationparts['host'];
        if(isset($locationparts['port']))  $location .= ':'.$locationparts['port'];
        if(isset($locationparts['path']))  $location .= $locationparts['path'];
        if(isset($locationparts['query'])) $location .= '?'.$locationparts['query'];
      }
    }
    return parent::__doRequest($request,$location,$action,$version,$one_way);
  }
}

Если методы действительно отличаются, выхотите переопределить метод __construct и загрузить XML, а также очистить или удалить все ссылки на порт http вместо ссылки https.Хотя это все больше и больше похоже на написание собственного мыльного клиента:)

...