Читал про Работу с веб-сервисами на php посредством SOAP.
Хочу рассказать очень занятную историю. Как-то раз передо мной встала задача расковырять админку поисковой системы FastSearch. Как говорится — не привыкать. Единственное, что меня смущало, так это то, что админка была написана на пхп 4.0, а я пишу на Джаве.
Ну что же, пхп так пхп. Естественно, гугль мне сразу выдал Pear:Soap. Как бы скормишь ему wsld от веб-сервиса и все начнут смеяться и плакать от счастья. Либо от того, что я не умею читать примеры, либо потому что веб-сервис был написан на Джаве и болтался на IBM WebSphere Application Server 6.0, а, IBM, как вы знаете — впереди планеты всей, очень любит делать стандартизованные вещи по-своему, в общем Pear:Soap не работал.
Ну что же, веб-сервис ты, или не веб-сервис, а работаешь по http и шлешь xml-ку.
Думаю так — вряд ли пхп4 не даст мне послать xml-ку по http.
Для того, чтобы не изобретать велосипед и не наступить на грабли я сосниффил заголовок soap-сообщения, которое отправляет Жабийный ws-client. Эта сволочь, кстати, кушает линк на wsdl (описание веб-сервиса) и предлагает доступные методы сервиса, указывая их тип.
Получилось вот что:
/* sniffed HEADER of SOAP message use it as template
POST /AuditServiceEAR/services/AuditService HTTP/1.1
Host: superhost.ru:9081
Content-Type: text/xml; charset=utf-8
Content-Length: 589
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: IBM Web Services Explorer
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Connection: close
*/
Это уже что-то.
Теперь пора немножко поговнякать код.
Чтобы коллегам-Джавистам было проще, пишу просто и без вкуса:
Теперь смастерю функцию, которая будет слать матерное soap-сообщение веб-сервису. Хвала яйцам, получать ответ от этого чудища мне не нужно.
шикарно, теперь надо сформировать soap-сообщение. В общем, есть такой веб-сервисный конверт (envelope), куда я запихну свои данные. Сделаю-ка я еще одну функцию. Вдруг сигнатура метода веб-сервиса поменяется? Да и в любом случае, хоть я на пхп4 и не кодю, но элементарный элемент реюзабельности я должен привнести.
В общем-то все готово. Веб-сервис находится, получает сообщение и остается доволен.
Порой, обладая самыми современными средствами, можно оказаться в жопе. Да, можно отправить soap-сообщение в три строчки, да пхп4 — позавчерашний день, ну а что теперь делать, если под рукой самые примитивные средства и соснифенный заголовок и тело soap-сообщения.
Так что не все так просто, что пишется двумя строками!
Хочу рассказать очень занятную историю. Как-то раз передо мной встала задача расковырять админку поисковой системы FastSearch. Как говорится — не привыкать. Единственное, что меня смущало, так это то, что админка была написана на пхп 4.0, а я пишу на Джаве.
Ну что же, пхп так пхп. Естественно, гугль мне сразу выдал Pear:Soap. Как бы скормишь ему wsld от веб-сервиса и все начнут смеяться и плакать от счастья. Либо от того, что я не умею читать примеры, либо потому что веб-сервис был написан на Джаве и болтался на IBM WebSphere Application Server 6.0, а, IBM, как вы знаете — впереди планеты всей, очень любит делать стандартизованные вещи по-своему, в общем Pear:Soap не работал.
Ну что же, веб-сервис ты, или не веб-сервис, а работаешь по http и шлешь xml-ку.
Думаю так — вряд ли пхп4 не даст мне послать xml-ку по http.
Для того, чтобы не изобретать велосипед и не наступить на грабли я сосниффил заголовок soap-сообщения, которое отправляет Жабийный ws-client. Эта сволочь, кстати, кушает линк на wsdl (описание веб-сервиса) и предлагает доступные методы сервиса, указывая их тип.
Получилось вот что:
/* sniffed HEADER of SOAP message use it as template
POST /AuditServiceEAR/services/AuditService HTTP/1.1
Host: superhost.ru:9081
Content-Type: text/xml; charset=utf-8
Content-Length: 589
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: IBM Web Services Explorer
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Connection: close
*/
Это уже что-то.
Теперь пора немножко поговнякать код.
Чтобы коллегам-Джавистам было проще, пишу просто и без вкуса:
/*CONSTANTS*/
$URL_TO_WEB_SERVICE =«superhost.ru/AuditServiceEAR/services/AuditService»; //path to web-service
$PORT_NUMBER = 9081;* This source code was highlighted with Source Code Highlighter.
Теперь смастерю функцию, которая будет слать матерное soap-сообщение веб-сервису. Хвала яйцам, получать ответ от этого чудища мне не нужно.
/**
function opens socket, prepares and sends SOAP message. It doesn't read response.
$data is a SOAP message <Envelope>
*/
function do_post_request($data) {
global $PORT_NUMBER, $URL_TO_WEB_SERVICE;
$url=$URL_WEB_SERVICE;
$start = strpos($url,'//')+2;
$end = strpos($url,'/',$start);
$host = substr($url, $start, $end-$start);
$domain = substr($url,$end);
$fp = pfsockopen($host, $PORT_NUMBER);//it is persistent version of fsockopen(). It behaves the same way. But it doesn't close connection
if(!$fp){
return null;
}
fputs ($fp,«POST $domain HTTP/1.1\n»);
fputs ($fp,«Host: $host\n»);
fputs ($fp,«Content-type: text/xml; charset=utf-8\n»);
fputs ($fp,«Content-length: „.strlen($data).“\n»);
fputs ($fp,«Accept: application/soap+xml, application/dime, multipart/related, text/*\n»);
fputs ($fp,«Cache-Control: no-cache\n»);
fputs ($fp,«Pragma: no-cache\n»);
fputs ($fp,'SOAPAction: ""\n');
fputs ($fp,«Connection: close\n\n»);
fputs ($fp,"$data\n\n");
fclose ($fp);
}* This source code was highlighted with Source Code Highlighter.
шикарно, теперь надо сформировать soap-сообщение. В общем, есть такой веб-сервисный конверт (envelope), куда я запихну свои данные. Сделаю-ка я еще одну функцию. Вдруг сигнатура метода веб-сервиса поменяется? Да и в любом случае, хоть я на пхп4 и не кодю, но элементарный элемент реюзабельности я должен привнести.
function write_audit_message($source, $evt, $server, $message, $userIP, $action){
$data = '<soapenv:Envelope xmlns:q0=«audit.service.company» xmlns:soapenv=«schemas.xmlsoap.org/soap/envelope» xmlns:xsd=«www.w3.org/2001/XMLSchema» xmlns:xsi=«www.w3.org/2001/XMLSchema-instance»>'
.'<soapenv:Body>'
.'<q0:addEvent>'
.'<arg_0_0>'.$source.'</arg_0_0>'
.'<arg_1_0>'.$evt.'</arg_1_0>'
.'<arg_2_0>'.$server.'</arg_2_0>'
.'<arg_3_0>'.$message.'</arg_3_0>'
.'<arg_4_0>'.$userIP.'</arg_5_0>'
.'<arg_5_0>'.$action.'</arg_6_0>'
.'</q0:addEvent>'
.'</soapenv:Body>'
.'</soapenv:Envelope>';
//now send prepared envelope
do_post_request($data);
}* This source code was highlighted with Source Code Highlighter.
В общем-то все готово. Веб-сервис находится, получает сообщение и остается доволен.
Порой, обладая самыми современными средствами, можно оказаться в жопе. Да, можно отправить soap-сообщение в три строчки, да пхп4 — позавчерашний день, ну а что теперь делать, если под рукой самые примитивные средства и соснифенный заголовок и тело soap-сообщения.
Так что не все так просто, что пишется двумя строками!