За последние 24 часа нас посетили 64125 программистов и 1741 робот. Сейчас ищут 895 программистов ...

Передать HTTP-заголовок перед SOAP запросом

Тема в разделе "PHP для новичков", создана пользователем Алексей_М, 28 фев 2016.

  1. Алексей_М

    Алексей_М Активный пользователь

    С нами с:
    1 дек 2012
    Сообщения:
    30
    Симпатии:
    0
    Добрый день,

    Когда-то давно писал код для работы с API через SOAP.

    Код (PHP):
    1. $wsdl = 'https://...URL....';
    2. ini_set("soap.wsdl_cache_enabled", "0");
    3. # SOAP object
    4. $client = new SoapClient($wsdl,
    5.     array(
    6.         'encoding' => 'UTF-8',
    7.     )
    8. );
    9.  
    10. # Login and OAuth token
    11. $token = '...........';
    12.  
    13. # SOAP headers
    14. $client->__setSoapHeaders(
    15.    array(
    16.       new SoapHeader('API', 'token', $token, false)
    17.    )
    18. );
    19. $result = $client->.......
    20.  
    Авторизация по Токену работала передаваясь в заголовке SOAP запроса.
    Всё было ок.

    Тех.поддержка API , поменяла принцип авторизации, и теперь просит указывать токен в HTTP-заголовке, а не в SOAP запросе.

    То есть, требуется послать нечто:
    POST /....URL.../ HTTP/1.1
    Authorization: Bearer token
    Accept-Language: ru
    Content-Type: charset=utf-8

    т.е. теперь нужно как-то обернуть SOAP чтобы перед этим он посылал необходимый токен в HTTP запросе типа Authorization: Bearer token?
    может кто подсказать код? не пойму как это сделать

    Подсказка от модератора:
    Любой код или текст конфигурации пишите между тегом [code=php] и [/code].
    Используйте отступы в коде для форматирования текста.
    Это помогает быстрее понять вас, увеличивает шанс на получение ответа.
    Что выделять? Например: PHP, HTML, CSS, JavaScript, SQL, XML, .htaccess, ini, регулярные выражения, код шаблонизаторов, любая другая разметка, результаты array/object dump и т. д.
     
  2. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
  3. Алексей_М

    Алексей_М Активный пользователь

    С нами с:
    1 дек 2012
    Сообщения:
    30
    Симпатии:
    0
    denis01, да, уже несколько дней гуглю, что-то не получается :(

    вариант этот тоже пробовал.
    делаю так:
    Код (PHP):
    1. $wsdl = 'https://domen.com/service?wsdl/';
    2. $token = '.....................';
    3.  
    4. ini_set("soap.wsdl_cache_enabled", "0");
    5. $client = new SoapClient($wsdl,
    6.                  array(
    7.          "exceptions" => 0,
    8.                   "trace" => 1, 
    9.                   "encoding" => 'UTF-8', 
    10.               'stream_context' => stream_context_create(
    11.           array('http' => 
    12.               array('header' => 'Authorization: Bearer $token')))));
    13.  
    14. $result = $client->check();
    15. print_r($client);
    16.  
    17.  
    Может неправильный синтаксис выше, насчёт Bearer:
    array('header' => 'Authorization: Bearer $token')))));

    получаю ответ что авторизация не прошла, т.к. Токен не введён:
    print_r($client); выдаёт:
    Код (Text):
    1.  
    2. SoapClient Object
    3. (
    4.     [trace] => 1
    5.     [_exceptions] =>
    6.     [_encoding] => UTF-8
    7.     [_stream_context] => Resource id #2
    8.     [_soap_version] => 1
    9.     [sdl] => Resource id #5
    10.     [__last_request] => <?xml version="1.0" encoding="UTF-8"?>
    11. <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://domen.com/service"><SOAP-ENV:Body><ns1:CheckRequest/></SOAP-ENV:Body></SOAP-ENV:Envelope>
    12.  
    13.     [httpurl] => Resource id #7
    14.     [__last_request_headers] => POST /service HTTP/1.1
    15. Host: soap.domen.com
    16. Connection: Keep-Alive
    17. User-Agent: PHP-SOAP/5.2.13
    18. Content-Type: text/xml; charset=utf-8
    19. SOAPAction: "https://domen.com/service/check"
    20. Content-Length: 240
    21.  
    22.  
    23.     [__last_response_headers] => HTTP/1.1 200 OK
    24. Server: nginx
    25. Date: Sun, 28 Feb 2016 12:00:54 GMT
    26. Content-Type: text/xml
    27. Transfer-Encoding: chunked
    28. Connection: close
    29. X-Frame-Options: SAMEORIGIN
    30. X-XSS-Protection: 1; mode=block
    31. X-Content-Type-Options: nosniff
    32.  
    33.     [__last_response] => <?xml version="1.0" encoding="UTF-8"?>
    34. <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Client</faultcode><faultstring>Authorization error</faultstring><detail><ns3:FaultResponse xmlns:ns3="http://domen.com/general"><requestId>12345</requestId><errorCode>12345</errorCode><errorDetail>Token not entered</errorDetail></ns3:FaultResponse></detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
    35.  
    36.     [__soap_fault] => SoapFault Object
    37.         (
    38.             [message:protected] => Authorization error
    39.             [string:private] =>
    40.             [code:protected] => 0
    41.             [file:protected] => api.php
    42.             [line:protected] => 53
    43.             [trace:private] => Array
    44.                 (
    45.                     [0] => Array
    46.                         (
    47.                             [function] => __call
    48.                             [class] => SoapClient
    49.                             [type] => ->
    50.                             [args] => Array
    51.                                 (
    52.                                     [0] => check
    53.                                     [1] => Array
    54.                                         (
    55.                                         )
    56.  
    57.                                 )
    58.  
    59.                         )
    60.  
    61.                     [1] => Array
    62.                         (
    63.                             [file] => api.php
    64.                             [line] => 53
    65.                             [function] => check
    66.                             [class] => SoapClient
    67.                             [type] => ->
    68.                             [args] => Array
    69.                                 (
    70.                                 )
    71.  
    72.                         )
    73.  
    74.                 )
    75.  
    76.             [faultstring] => Authorization error
    77.             [faultcode] => SOAP-ENV:Client
    78.             [detail] => stdClass Object
    79.                 (
    80.                     [FaultResponse] => stdClass Object
    81.                         (
    82.                             [requestId] => 12345
    83.                             [errorCode] => 12345
    84.                             [errorDetail] => Token not entered
    85.                         )
    86.  
    87.                 )
    88.  
    89.         )
    90.  
    91. )
    Добавлено спустя 13 минут 16 секунд:
    + есть:
    Адрес WSDL-описания
    https://domen.com/service?wsdl

    Адрес для SOAP-запросов
    https://domen.com/service
    Может надо стрим_контекст с Авторизацией посылать на УРЛ Адрес для SOAP-запросов? А не на wsdl? В моём коде речь ведь только про wsdl:
    $wsdl = 'https://domen.com/service?wsdl/';

    или это не важно? Хотя вроде пишут что если SOAP поддерживает WSDL то не важно, там само опредлеяется.
     
  4. Ke1eth

    Ke1eth Активный пользователь

    С нами с:
    16 мар 2012
    Сообщения:
    1.073
    Симпатии:
    11
    Адрес:
    заблудилса
    Алексей, сам же ссылаешься на топик: http://php.ru/forum/viewtopic.php?t=50318, а ведь именно там и есть ответ на вопрос, заголовки отдавай.
     
  5. Алексей_М

    Алексей_М Активный пользователь

    С нами с:
    1 дек 2012
    Сообщения:
    30
    Симпатии:
    0
    Ke1eth
    делаю:

    Код (PHP):
    1. <span class="syntaxdefault"><br />var_dump</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"REQUEST"</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> $client</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">__getLastRequest</span><span class="syntaxkeyword">());<br /></span><span class="syntaxdefault">var_dump</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"RESPONSE"</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> $client</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">__getLastResponse</span><span class="syntaxkeyword">());<br /></span><span class="syntaxdefault"></span>
    получаю:
    Код (Text):
    1.  
    2. string(7) "REQUEST"
    3. string(240) "<?xml version="1.0" encoding="UTF-8"?>
    4. <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://domen.com/service"><SOAP-ENV:Body><ns1:CheckRequest/></SOAP-ENV:Body></SOAP-ENV:Envelope>
    5. "
    6. string(8) "RESPONSE"
    7. string(505) "<?xml version="1.0" encoding="UTF-8"?>
    8. <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Client</faultcode><faultstring>Authorization error</faultstring><detail><ns3:FaultResponse xmlns:ns3="http://domen.com/general"><requestId>12345</requestId><errorCode>53</errorCode><errorDetail>Token not entered</errorDetail></ns3:FaultResponse></detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
    9. "
    Добавлено спустя 37 минут 1 секунду:
    а почему:
    Код (PHP):
    1. var_dump("REQUEST", $client->__getLastRequest());
    2.  
    и то что он отдал выше: string(240) и т.д., не показывает что мы делали заголовок стрим_контекстом stream_context:
    Код (PHP):
    1. array('header' => 'Authorization: Bearer $token'))))); 
    Добавлено спустя 32 минуты 24 секунды:нашёл что в php 5.2. но в каких точно версиях не ясно, есть баг со stream_context:
    https://bugs.php.net/bug.php?id=41051

    но делая замену
    Код (PHP):
    1. array('http' =>
    2.               array('header' => 'Authorization: Bearer $token')))));
    3.  
    на
    Код (PHP):
    1. array('http' =>
    2.                  array('header' =>
    3.                       array('Authorization' => 'Bearer $token')))))); 
    ответ тот же самый как и выше - нет токена.

    Добавлено спустя 4 минуты 54 секунды:
    посмотрел по print_r($client) который приводил выше тут viewtopic.php?f=13&t=56916&p=458453#p458431:

    Код (Text):
    1.    [httpurl] => Resource id #7
    2.     [__last_request_headers] => POST /service HTTP/1.1
    3. Host: soap.domen.com
    4. Connection: Keep-Alive
    5. User-Agent: PHP-SOAP/5.2.13
    6. Content-Type: text/xml; charset=utf-8
    7. SOAPAction: "https://domen.com/service/check"
    8. Content-Length: 240
    так у нас же никакой Authorization Bearer токен не передаётся?!
    Получается stream_context не работает?

    Добавлено спустя 9 минут 32 секунды:
    или он там и не должен быть? потому что это SoapClient Object, а токен надо передать ВНЕ SoapClient Object, а не внутри как это обычно деают по new SoapHeader.

    Добавлено спустя 6 минут 39 секунд:
    нет:)
    токен там быть должен, т.к. если мы делаем заголовок для СОАП-запроса, то он будет как:
    Код (Text):
    1. SoapClient Object
    2. (
    3.     [trace] => 1
    4.     [_exceptions] =>
    5.     [_encoding] => UTF-8
    6.     [_soap_version] => 1
    7.     [sdl] => Resource id #3
    8.     [__default_headers] => Array
    9.         (
    10.             [0] => SoapHeader Object
    11.                 (
    12.                     [namespace] => API
    13.                     [name] => token
    14.                     [data] =>                    
    15. [mustUnderstand] =>
    16.                 )
    17.  
    18.         )
    а нам нужно отддать токен именно в заголовке HTTP last_request_headers
    Код (Text):
    1.  [__last_request_headers] => POST /service HTTP/1.1
    2.     Host: soap.domen.com
    3.     Connection: Keep-Alive
    4.     User-Agent: PHP-SOAP/5.2.13
    5.     Content-Type: text/xml; charset=utf-8
    6.     SOAPAction: "https://domen.com/service/check"
    7.     Content-Length: 240
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    А токен верный? Может быть проблема в том, что вы его расчитали неправильно.
     
  7. Алексей_М

    Алексей_М Активный пользователь

    С нами с:
    1 дек 2012
    Сообщения:
    30
    Симпатии:
    0
    верный точно,
    на принимающем сервере 2 версии API.
    старая работает по токену который передаётся ВНУТРИ соап-объекта, через:
    Код (PHP):
    1.       new SoapHeader('API', 'token', $token, false)
    2.  
    так всё ок.

    а новая версия "смотрит" заголовки не СОАП объека, а именно HTTP-заголовки.
    т.е. она ждёт:
    Код (Text):
    1.  
    2. POST url HTTP/1.1
    3. Host: domen.com
    4. Authorization: Bearer
    5. Accept-Language: ru
    6. Content-Type: application/json; charset=utf-8
    а делая print_r($client)
    вижу что мы отдаём:
    Код (Text):
    1. [__last_request_headers] => POST /service HTTP/1.1
    2.     Host: soap.domen.com
    3.     Connection: Keep-Alive
    4.     User-Agent: PHP-SOAP/5.2.13
    5.     Content-Type: text/xml; charset=utf-8
    6.     SOAPAction: "https://domen.com/service/check"
    7.     Content-Length: 240
    без всяких Authorization: Bearer

    но Authorization: Bearer -то мы прописывает же в stream_context. Почему его тогда нет в [__last_request_headers].

    об этом кстати в БАГе и сказано:
    https://bugs.php.net/bug.php?id=41051
     
  8. Алексей_М

    Алексей_М Активный пользователь

    С нами с:
    1 дек 2012
    Сообщения:
    30
    Симпатии:
    0
    вроде бы нашёл баг
    какой-то там косяк в SOAP со stream_context
    только какой не особо пока понял, но решения указать 'protocol_version' => 1.1 и закрыть соединение "Connection: close" ни к чему не приводит всё равно.
    https://bugs.php.net/bug.php?edit=1&id=49853

    может кто объяснить в чём там суть?
    Добавлено спустя 27 минут 37 секунд:
    на php 5.4.41 stream_context вместе c SOAP работает! и в [__last_request_headers] есть токен по print_r($client);
    на 5.2.13-17 - не работает stream_context с SOAP. Но на многих серверах он стоит:(, как можно пофиксить?
     
  9. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Сейчас PHP 7 актуальная (ещё поддерживают 5.6 и 5.5), зачем писать под неподдержимую 5.2 и т. д.
    На хостингах есть обычно возможность переключения версий PHP.