soap сообщения что это
Soap сообщения что это
Применение SOAP при интеграции систем
Для начинающих аналитиков,
не имеющих опыта web-разработки
В предыдущей статье мы говорили про то, что REST — это архитектурный стиль, который Рой Филдинг сформулировал в своей диссертации в 2000 году.
С протоколом SOAP дела обстоят несколько иначе.
SOAP — это не стиль, а протокол. Аббревиатура SOAP так и расшифровывается: Simple Object Access Protocol — простой протокол доступа к объектам. То есть правила передачи информации в SOAP строго стандартизированы, есть спецификация, которой нужно соответствовать.
SOAP появился 1998 году и был передан в организацию World Wide Web Consortium (W3C) — международная организация, которая курирует развитие интернета.
Если сравнить это с тем фактом, что Рой Филдинг просто представил REST в своей диссертации, то вы поймете, почему SOAP завоевал популярность очень быстро.
Тем не менее на данный момент можно говорить о том, что в основном для интеграции систем используется REST.
Для того, чтобы наглядно показать отличие REST от SOAP, приведем вот такую аналогию. Представьте себе дерево, в котором есть дупло, и из этого дупла выглядывает птичка. Когда вы обращаетесь к какому-то приложению, вы как будто обращайтесь к такому дереву и стучитесь в окошко. Условно можно считать, что в это окошко выглядывает некоторая функция.
Если вы работаете с REST, то можно себе представить дерево, в котором есть много таких окошек — большое количество птичек, каждая из которых выглядывает из своего дупла. Это дупло называется Endpoint, но это отдельный разговор. Важно, что каждый раз, обращаясь к дуплу, вы обращаетесь только к одной функции.
SOAP основывается на технологии удаленного вызова процедур. Сервис, который работает на базе SOAP — это дерево с одним-единственным дуплом. Но каждый раз, обращаясь к этому дуплу, вы должны указать название процедуры, то есть название функции, которую вы хотите вызвать, потому что функций там может быть несколько. И, разумеется, вы должны передать те входные данные, которые нужны для процедуры, которую вы собираетесь вызвать.
В SOAP передача данных идет по протоколу HTTP, то есть также, как это происходит и в случает REST-запросов.
Давайте рассмотрим на примере. Если я зайду на сайт какой-нибудь биржи акций, то могу узнать курс интересующей меня акции. Откуда поступает эта информация? Давайте разберемся.
Я открываю на своем компьютере браузер, который является клиентом. По протоколу HTTP он обращается к серверу (назовем его HTTP-server).
На этом HTTP-сервере живёт приложение, которое отдает мне информацию, о том, что акция Facebook стоит, к примеру, 252 доллара. Однако, откуда само приложение, живущее на HTTP-сервере, знает стоимость акции?
А все очень просто — приложение в данном случае выступило как SOAP-client и запросило эту информацию на другом сервере (назовем его SOAP-server).
Взаимодействие SOAP-client и SOAP-server происходит по протоколу SOAP поверх HTTP. Что значит поверх? Это значит, что клиент и сервер общаются по протоколу HTTP, но по этому протоколу передаётся не просто стандартное сообщение HTTP, а некий конвертик с письмом, причем это письмо написано по правилам протокола SOAP.
То есть сайт, который передал мне информацию о Facebook, сам запросил SOAP-server (то есть биржу акций) по протоколу HTTP и вложил сообщение в конвертик SOAP.
Таким образом, информация о курсе акции пришла ко мне не напрямую с биржи, а через посредника — через SOAP-client.
Когда мы работаем по сети, мы работаем с протоколами TCP/IP — это нижний, сетевой уровень протоколов. Весь интернет базируется на протоколе HTTP, который мы рассматривали в предыдущей статье. HTTP является просто транспортом, с помощью которого информация передается по сети.
Чтобы передать какое-либо сообщение по сети, оно должно соответствовать правилам протокола HTTP. А дальше в пакетик, передаваемый по протоколу HTTP, вкладывается сообщение по протоколу SOAP. И все это живет по правилам, описанным в файле WSDL.
Представьте себе, что вы хотите передать по сети некоторую записочку. И вы хотите, чтобы информация в ней была структурирована так, чтобы записку могла прочитать программа.
В качестве примера приведу записку, которую Анна пишет Марии: «Приходи ко мне в гости в воскресенье!». И заголовок: «Напоминалка» (Reminder). Здесь могла бы быть ещё подпись signature, но, как видите, подпись оказалась пустой, информация в теге не передана (такое тоже возможно).
Тег — это текстовая строка, завернутая в уголочки (<>).
То есть, когда мы передаем XML-документ, мы информацию «заворачиваем» в теги. Они предназначены для того, чтобы объяснять, что лежит внутри. Теги бывают открывающие (перед текстовым содержимым) и закрывающие (начинается с символа «/»).
В HTML такие же теги, но они применяются немного по-другому: в языке XML эти теги предназначены для того, чтобы объяснить приложению, которое принимает сообщение, что именно вложено внутрь.
Приложение, которое принимает записку, заранее знает, какие должны прийти данные внутри каких тегов. И знает оно это благодаря WSDL.
Что такое WSDL? В SOAP для описания своего сервиса нужно использовать строгие правила в виде файлов WSDL. Ниже мы разберем это подробнее, но вообще WSDL — это Web Services Description Language, ещё один язык описания веб-сервисов и доступа к ним.
Разберем приведенный ранее пример детальнее.
Первая строка документа — XML-декларация, она указывает на версию XML ( version=»1.0″ ) и тип кодировки документа ( encoding=»utf-8″ ).
Что ещё есть в xml-документе?
Всё XML-сообщение (наша записочка) заворачивается в так называемый корневой тег. В данном случае, корневым является тег note, который выделен зеленым.
Правильно оформленный XML это такой XML, который соответствует стандартам языка и может быть разобран приложением, то есть приложение его получит, проверит синтаксис и начнет разбирать.
Важно понимать, что приложение не будет разбирать XML если он не будет правильно оформлен. В этом случае приложение придёт к выводу, что XML повредили или подменили по дороге.
Если мы посмотрим на XML-документ внимательно, то сможем построить вот такое дерево:
То есть с точки зрения приложения XML представляет собой дерево, состоящее из узлов. Например на картинке вы можете видеть имена узлов: note, to, from, heading, body, signature.
Узлы вкладываются друг друга, и получается, что XML-документ можно представить в виде перевернутого дерева, только дерево растет вниз. Тeг note является корнем и в него вложены остальные теги, все они являются детьми этого корня. Кроме того, есть ещё текстовых узлы Мария, Анна и т. д.
Разговоры о том, что какая-то буква потерялась, не очень актуальны сейчас, так как современные протоколы обеспечивают целостную доставку. Данный пример призван продемонстрировать, что XML-документ в первую очередь создаётся для того, чтобы информацию вкладывать в теги.
Атрибуты — это пары имя/значение, поставленные в соответствие одному из элементов. Они должны находиться при открывающем теге, но не при закрывающем.
Атрибуты всегда должны иметь значение, даже если значением является всего лишь пустая строка. Значения атрибутов должны заключаться в кавычки. При этом согласно синтаксису XML допускаются как двойные, так и одинарные кавычки.
Если вам придется руками формировать XML-документ, никогда не пишите в одном документе и двойные и одинарные кавычки, просто потому что вам лень аккуратненько расставить однотипные, поскольку это может привести к ошибкам.
Чтобы наглядно объяснить, что такое пространство имён, рассмотрим следующий пример.
Например, в первом случае тег table — это текст, который используется в языке HTML для указания того факта, что дальше идет описание таблицы. А во втором — предназначен для того, чтобы описать африканский кофейный стол и его размеры.
Как сделать так, чтобы приложение определило, что это разные теги table?
Чтобы раскрыть тему, давайте рассмотрим бытовую аналогию: как учителя различают детей, которые приходят в класс.
У себя дома имя мальчика Серёжи, скорее всего, является уникальным идентификатором. То есть, вероятнее всего, ни одного Серёжи в семье больше нет. Но когда Серёжа приходит в школу, он обнаруживает, что в классе ещё три Серёжи, и учителю их надо как-то различать.
Как это сделать? Как правило, в классе для этого используется фамилия ребенка. Но если в классе есть однофамильцы Серёжи? Что ж, и такое бывает. В этом случае отличать Серёж можно по их домашнему адресу.
Интересный момент: если учитель знает, что Серёжа Васильев живёт по этому адресу, а тут в класс приходит некая Аня Васильева, живущая по этому же адресу, то можно сделать логичный вывод, что, скорее всего, Серёжа и Аня — брат и сестра. Именно адрес и указывает учителю на то, какая это семья и где она живёт. В XML-документах точно такая же логика.
Если нам нужно определить пространство имён (семью), к которому относится тег, мы заводим специальный атрибут. Этот атрибут называется XML namespace, сокращенно xmlns. Именно в xmlns мы пишем адрес — то место, где публикуется стандарт стандарта языка (то есть в атрибуте xmlns указывается адрес документа, в котором явно описано, что такое table для документа HTML).
В случае с кофейным столиком мы, разумеется, пишем другой адрес. Интересно, что это может быть абсолютно любой адрес, он может даже не существовать на самом деле, поскольку используется только для идентификации. То есть, вот этот тег table живет по этому конкретному адресу, и там же живёт вся его семья.
Что из себя представляет семья тегов?
Правило такое: если тег, у которого указано пространство имён, содержит вложенные теги, то эти вложенные теги относятся к тому же пространству имён.
Ранее в примерах мы говорили про обмен данными между сайтом и биржей акций. Как это происходит?
Чтобы отправить запрос в биржу акций, нужно ответить на простой вопрос. Facebook и сайт биржи акций должны ответить «252.36» — это содержимое, которое надо передать. Протокол SOAP предполагает, что это текстовое содержимое вложено внутрь XML-тегов и прописано в стандарте в виде XML-дерева.
Давайте разберем на составляющие данный запрос.
Envelope и Body — теги, которые прописаны в протоколе SOAP. То есть, если вы отправляете запрос по протоколу SOAP, то у вас должен быть тег Envelope и вложенный в него тег Body. Это нужно просто запомнить.
SOAP-ENV — обозначение пространства имён, то есть теги Envelope и Body относятся к пространству имён SOAP-овского окружения и это не что иное, как краткое указание на то, что есть определенное семейство тегов. А где описывается пространство имён, мы разберем немного позже.
getQuote (получить котировку) — имя процедуры, которую мы хотим вызвать. Она относится уже к другому пространству имён, а именно «ns1».
« Faсebook » — это входной параметр, который мы передаем, и он завернут в тег Symbol. Обратите внимание на атрибут, который есть в этом теге «string» — он описывает, что передаваться должно не число, а строка.
Давайте теперь вернемся к WSDL — документу, благодаря которому приложение заранее знает, какие должны прийти данные внутри каких тегов.
Основные теги с которыми вы столкнетесь в описании WSDL-сервера:
Как все это выглядит?
На веб-сервисе лежит файл WSDL. И клиент, и сервер руководствуются в своей работе этим файлом: читают его и разбираются, как устроен сервис. И клиент, и сервер умею читать этот файл и получать из него информацию, так как они знают стандарт SOAP и то, как должен быть устроен файл WSDL.
Давайте разберем этот wsdl-файл:
Operation — это тег, который описывает функции. То есть он указывает на имя функции и то, как должен выглядеть запрос и ответ.
Вложенные в operation теги input и output содержат информацию о входных и выходных параметрах функции. То есть getQuoteRequest — это запрос, который представляет собой строку и должен иметь вид числа с плавающей точкой.
Тег binding описывает все технические сведения, о том, что из себя представляет сервис.
Тег servisce описывает, где живет наш сервис. Если бы мы установили веб-сервисом на локальной машине, то адрес написали бы следующим образом: localhost/server1. php/.
Если вы захотите расписать WSDL в виде дерева, то получите следующую картину:
Корневой тег definitions содержит 2 тега message, описывающие входной и выходной параметры.
Далее идет тег portType, включающий в себя тег operation, который также описывает входной и выходной параметры. PortType же собирает вместе информацию из двух тегов message.
Тег binding описывает все технические особенности нашего сервера. Считается довольно сложным в прочтении для начинающих.
Тег service содержит описание нашего сервера.
Главным недостатком SOAP является то, что при его использовании для передачи сообщений, он увеличивает их объём и снижает скорость обработки.
Мы смогли в этом убедиться на примере вопроса «Facebook» и ответа «252.36», которые требуют огромного количества тегов, в которые заворачивается вопрос.
Для того, чтобы еще раз сравнить SOAP и REST, я привела преимущества приложения, созданного на основании REST:
Для SOAP необходимо специальное приложение, чтобы разобрать XML-документ, распарсить его, как говорят в ИТ-среде.
Относительно легкости внесения изменений хочется заметить: для того, чтобы изменить WSDL, мы, разумеется, можем изменить адрес, но это непросто. SOAP — консервативный протокол, он используется преимущественно в Legacy-системах, но, тем ни менее, знание SOAP пользуется достаточно большим спросом.
Пишем SOAP клиент-серверное приложение на PHP
Всем привет!
Так случилось, что в последнее время я стал заниматься разработкой веб-сервисов. Но сегодня топик не обо мне, а о том, как нам написать свой XML Web Service основанный на протоколе SOAP 1.2.
1 Постановка задачи
1.1 Границы
В начале предлагаю разобраться с тем результатом, которого мы достигнем в конце топика. Как было объявлено выше, мы будем писать сервис по отправке sms-сообщений, а если еще точнее, то к нам будут поступать сообщения из разных источников по протоколу SOAP. После чего, мы рассматрим в каком виде они приходят на сервер. Сам процесс постановки сообщений в очередь для их дальнейшей отправки провайдеру, к сожалению, выходит за рамки данного поста по многим причинам.
1.2 Какими данными будем меняться?
Отлично, с границами мы определились! Следующий шаг, который необходимо сделать – решить какими данными мы будем обмениваться между сервером и клиентом. На эту тему предлагаю долго не мудрить и сразу для себя ответить на главные вопросы:
И все же, я что-то забыл! Если еще немного порефлексировать, то стоит отметить, что клиент за раз может отправить на сервер как одно sms-сообщение, так и некоторое их количество. Другими словами, в одном пакете данных может быть от одного до бесконечности сообщений.
В результате мы получаем, что для отправки sms-сообщения нам необходимы следующие данные:
На первый вопрос мы ответили, теперь необходимо ответить на второй вопрос. И пожалуй, я позволю себе немного с халтурить. Поэтому, с сервера мы будем присылать только булевы данные, значение которых имеет следующий смысл:
На этом мы закончили описание постановки задачи! И наконец-то приступим к самому интересному – будем разбираться что за диковинный зверь этот SOAP!
2 С чем есть SOAP?
Вообще, изначально я не планировал ничего писать о том, что такое SOAP и хотел ограничиться ссылками на сайт w3.org с нужными спецификациями, а также ссылками на Wikipedia. Но в самом конце решил написать коротенькую справочку об этом протоколе.
И начну я свое повествование с того, что данный протокол обмена данными относится к подмножеству протоколов основанных на так называемой парадигме RPC (Remote Procedure Call, удалённый вызов процедур) антиподом которой является REST (Representational State Transfer, передача репрезентативного состояния). Более подробно об этом можно прочесть в Wikipedia, ссылки на статьи находятся в самом конце топика. Из этих статей нам надо уяснить следующее: «Подход RPC позволяет использовать небольшое количество сетевых ресурсов с большим количеством методов и сложным протоколом. При подходе REST количество методов и сложность протокола строго ограничены, из-за чего количество отдельных ресурсов может быть большим». Т.е., применительно к нам это означает, что на сайте в случае RPC подхода будет всегда один вход (ссылка) на сервис и какую процедуру вызывать для обработки поступающих данных мы передаем вместе с данными, в то время как при REST подходе на нашем сайте есть много входов (ссылок), каждая из которых принимает и обрабатывает только определенные данные. Если кто-то из читающих знает, как еще проще объяснить различие в данных подходах, то обязательно пишите в комментариях!
Следующее, что нам надо узнать про SOAP – данный протокол в качестве транспорта использует тот самый XML, что с одной стороны очень хорошо, т.к. сразу же в наш арсенал попадает вся мощь стека технологий основанных на данном языке разметки, а именно XML-Schema – язык описания структуры XML-документа (спасибо Wikipedia!), который позволяет производит автоматическую валидацию поступающих на сервер данных от клиентов.
И так, теперь мы знаем, что SOAP – протокол используемый для реализации удаленного вызова процедур и в качестве транспорта он использует XML! Если почитать статью на Wikipedia, то оттуда можно узнать еще и о том, что он может использоваться поверх любого протокола прикладного уровня, а не только в паре с HTTP (к сожалению, в данном топике мы будем рассматривать только SOAP поверх HTTP). И знаете, что мне во всем этом больше всего нравится? Если нет никаких догадок, то я дам подсказку – SOAP!… Всеравно не появилось догадок?… Вы точно прочли статью на Wikipedia?… В общем, не буду вас дальше мучить. Поэтому, сразу перейду к ответу: «SOAP (от англ. Simple Object Access Protocol — простой протокол доступа к объектам; вплоть до спецификации 1.2)». Самое примечательное в этой строчке выделено курсивом! Я не знаю какие выводы сделали вы из всего этого, но мне видится следующее – поскольку данный протокол ну никак нельзя назвать «простым» (и видимо с этим согласны даже в w3), то с версии 1.2 он вообще перестал как-то расшифровываться! И стал называться SOAP, просто SOAP и точка.
Ну да ладно, прошу меня извинить, занесло немного в сторону. Как я писал ранее, в качестве транспорта используется XML, а пакеты, которые курсируют между клиентом и сервером называются SOAP-конвертами. Если рассматривать обобщенную структуру конверта, то он вам покажется очень знакомым, т.к. напоминает структуру HTML-страницы. В нем есть основной раздел – Envelop, который включает разделы Header и Body, либо Fault. В Body передаются данные и он является обязательным разделом конверта, в то время как Header является опциональным. В Header может передаваться авторизация, либо какие-либо иные данные, которые на прямую не относятся к входным данным процедур веб-сервиса. Про Fault особо рассказывать нечего, кроме того, что он приходит в клиент с сервера в случае возникновения каких-либо ошибок.
На этом мой обзорный рассказ про протокол SOAP заканчивается (более детально сами конверты и их структуру мы рассмотрим когда наши клиент и сервер наконец-то научатся запускать их друг в друга) и начинается новый – про компаньона SOAP под названием WSDL (Web Services Description Language). Да-да, это та самая штука, которая отпугивает большинство из нас от самой попытки взять и реализовать свое API на данном протоколе. В результате чего, мы обычно изобретаем свой велосипед с JSON в качестве транспорта. И так, что такое WSDL? WSDL – язык описания веб-сервисов и доступа к ним, основанный на языке XML (с) Wikipedia. Если из этого определения вам не становится понятным весь сакральный смысл данной технологии, то я попытаюсь описать его своими словами!
3 Введение в XML-Schema
Теперь мы много чего знаем о то, что такое SOAP, что находится у него внутри и имеем обзорное представление о том, какой стек технологий его окружает. Поскольку, прежде всего SOAP представляет собой способ взаимодействия между клиентом и сервером, и в качестве транспорта для него используется язык разметки XML, то в данном разделе мы немного разберемся каким образом происходит автоматическая валидация данных посредством XML-схем.
Предлагаю далеко не ходить и написать XML-схему для нашего sms-сообщения! Ниже представлено xml-описание sms-сообщения:
Схема нашего комплексного типа будет выглядеть следующим образом:
Эта запись читается следующим образом: у нас есть переменная «message» типа «Message» и есть комплексный тип с именем «Message», который состоит из последовательного набора элементов «phone» типа string, «text» типа string, «date» типа dateTime, «type» типа decimal. Эти типы простые и уже определены в описании схемы. Поздравляю! Мы только что написали нашу первую XML-схему!
Думаю, что значение элементов «element» и «complexType» вам стало все более-менее понятно, поэтому не будем на них больше заострять внимание и переключимся сразу же на элемент-композитор «sequence». Когда мы используем элемент-композитор «sequence» мы сообщаем о том, что элементы включенные в него должны всегда располагаться в указанной в схеме последовательности, а также все из них являются обязательными. Но не стоит отчаиваться! В XML-схемах есть еще два элемента-композитора: «choice» и «all». Композитор «choice» сообщает о том, что должен быть какой-то один из перечисленных в нем элементов, а композитор «all» – любая комбинация перечисленных элементов.
Как вы помните, то в первом разделе топика мы договорились о том, что в пакете может передаваться от одного до бесконечности sms-сообщений. Поэтому предлагаю разобраться как такие данные декларируются в XML-схеме. Общая структура пакета может выглядеть следующим образом:
Схема для такого комплексного типа будет выглядеть так:
В первом блоке идет знакомое нам декларирование комплексного типа «Message». Если вы заметили, то в каждом простом типе, входящем в «Message», были добавлены новые уточняющие атрибуты «minOccurs» и «maxOccurs». Как не трудно догадаться из названия, первый (minOccurs) сообщает о том, что в данной последовательности должно быть минимум по одному элементу типа «phone», «text», «date» и «type», в то время как следующий (maxOccurs) атрибут нам декларирует, что таких элементов в нашей последовательности максимум по-одному. В результате, когда мы пишем свои схемы для каких-либо данных, нам предоставляется широчайший выбор по их настройке!
Второй блок схемы декларирует элемент «messageList» типа «MessageList». Видно, что «MessageList» представляет собой комплексный тип, который включает минимум один элемент «message», но максимальное число таких элементов не ограничено!
На этом будем считать, что ЛикБез по схемам завершен и далее нас ждет еще одно не менее увлекательное приключение – мы будем писать свой собственный WSDL!
4 Пишем свой WSDL
Вы помните о том, что WSDL и есть наш веб-сервис? Надеюсь, что помните! Как мы его напишем, так на нем наш маленький веб-сервис и поплывет. Поэтому, предлагаю не халтурить.
Вообще, для того, чтобы у нас все работало правильно нам надо передавать клиенту WSDL-файл с правильным MIME-типом. Для этого необходимо настроить ваш веб-сервер соответствующим образом, а именно – установить для файлов с расширением «*.wsdl» MIME-тип равный следующей строке:
Но на практике, я обычно отправлял посредством PHP HTTP-заголовок«text/xml»:
и все прекрасно работало!
Хочу сразу предупредить, наш простенький веб-сервис будет иметь довольно внушительное описание, поэтому не пугайтесь, т.к. большая часть текста является обязательной водой и написав ее один раз можно постоянно копировать от одного веб-сервиса к другому!
Поскольку WSDL – это XML, то в самой первой строке необходимо прямо об этом и написать. Корневой элемент файла всегда должен называться «definitions»:
Обычно, WSDL состоит из 4-5 основных блоков. Самый первый блок – определение веб-сервиса или другими словами – точки входа.
Здесь написано, что у нас есть сервис, который называется – «SmsService». В принципе, все имена в WSDL-файле могут быть вами изменены на какие только пожелаете, т.к. они не играют абсолютно никакой роли.
После этого мы объявляем о том, что в нашем веб-сервисе «SmsService» есть точка входа («port»), которая называется «SmsServicePort». Именно в эту точку входа и будут отправляться все запросы от клиентов к серверу. И указываем в элементе «address» ссылку на файл-обработчик, который будет принимать запросы.
После того, как мы определили веб-сервис и указали для него точку входа – необходимо привязать к нему поддерживаемые процедуры:
Для этого перечисляется какие операции и в каком виде у будут вызываться. Т.е. для порта «SmsServicePort» определена привязка под именем «SmsServiceBinding», которая имеет тип вызова «rpc» и в качестве протокола передачи (транспорта) используется HTTP. Т.о., мы здесь указали, что будем осуществлять RPC вызов поверх HTTP. После этого мы описываем какие процедуры (operation) поддерживаются в веб-сервисе. Мы будем поддерживать всего одну процедуру – «sendSms». Через эту процедуру будут отправляться на сервер наши замечательные сообщения! После того, как была объявлена процедура, необходимо указать в каком виде будут передаваться данные. В данном случае указано, что будут использоваться стандартные SOAP-конверты.
После этого нам необходимо привязать процедуру к сообщениям:
Для этого мы указываем, что наша привязка («binding») имеет тип «SmsServicePortType» и в элементе «portType» с одноименным типу именем указываем привязку процедур к сообщениям. И так, входящее сообщение (от клиента к серверу) будет называться «sendSmsRequest», а исходящее (от сервера к клиенту) «sendSmsResponse». Как и все имена в WSDL, имена входящих и исходящих сообщения – произвольные.
Теперь нам необходимо описать сами сообщения, т.е. входящие и исходящие:
Для этого мы добавляем элементы «message» с именами «sendSmsRequest» и «sendSmsResponse» соответственно. В них мы указываем, что на вход должен прийти конверт, структура которого соответствует типу данных «Request». После чего с сервера возвращается конверт содержащий тип данных – «Response».
Теперь надо сделать самую малость – добавить описание данных типов в наш WSDL-файл! И как вы думаете, как описываются в WSDL входящие и исходящие данные? Думаю, что вы уже все давно поняли и сказали сами себе, что при помощи XML-схем! И вы будете абсолютно правы!
Можно нас поздравить! Наш первый WSDL был написан! И мы еще на один шаг приблизились к достижению поставленной цели.
Далее мы разберемся с тем, что нам предоставляет PHP для разработки собственных распределенных приложений.
5 Наш первый SOAP-сервер
Ранее я писал, что для создания SOAP-сервера на PHP мы будем использовать встроенный класс SoapServer. Для того, чтобы все дальнейшие действия происходили также как и у меня, вам понадобиться немного подкрутить свой PHP. Если быть еще точнее, то необходимо убедиться, что у вас установлено расширение «php-soap». Как его поставить на ваш веб-сервере лучше всего прочитать на официальном сайте PHP (см. список литературы).
После того, как все было установлено и настроено нам необходимо будет создать в корневой папке вашего хостинга файл «smsservice.php» со следующим содержанием:
То, что находится выше строчки с функцией «ini_set», надеюсь, что объяснять не надо. Т.к. там определяется какие HTTP-заголовки мы будем отправлять с сервера клиенту и настраивается окружение. В строчке с «ini_set» мы отключаем кеширование WSDL-файла для того, чтобы наши изменения в нем сразу же вступали в действие на клиенте.
Теперь мы подошли к серверу! Как видим, весь SOAP-сервер занимает всего лишь три строки! В первой строке мы создаем новый экземпляр объекта SoapServer и передаем ему в конструктор адрес нашего WSDL-описания веб-сервиса. Теперь мы знаем, что он будет располагаться в корне хостинга в файле с говорящим именем «smsservice.wsdl.php». Во второй строке мы сообщаем SOAP-серверу какой класс необходимо дергать для того, чтобы обработать поступивший с клиента конверт и вернуть конверт с ответом. Как вы могли догадаться, именно в этом классе будет описан наш единственный метод sendSms. В третьей строке мы запускаем сервер! Все, наш сервер готов! С чем я нас всех и поздравляю!
Теперь нам необходимо создать WSDL-файл. Для этого можно либо просто скопировать его содержимое из предыдущего раздела, либо позволить себе вольности и немного его «шаблонизировать»:
На этом этапе получившийся сервер нас должен устроить полностью, т.к. поступающие к нему конверты мы можем логировать и потом спокойно анализировать приходящие данные. Для того, чтобы мы могли что-либо получать на сервер, нам необходим клиент. Поэтому давайте им и займемся!
6 SOAP-клиент на подходе
Прежде всего нам надо создать файл, в котором будем писать клиент. Как обычно, мы его создадим в корне хоста и назовем «client.php», а внутри напишем следующее:
Опишем наши объекты. Когда мы писали WSDL в нем для входящего на сервер конверта описывались три сущности: Request, MessageList и Message. Соответственно классы Request, MessageList и Message являются отражениями этих сущностей в нашем PHP-скрипте.
После того, как мы определили объекты, нам необходимо создать объект ($req), который будем отправлять на сервер. После чего идут две самые заветные для нас строки! Наш SOAP-клиент! Верите или нет, но этого достаточно для того, чтобы на наш сервер начали сыпаться сообщения от клиента, а также для того, чтобы наш сервер успешно их принимал и обрабатывал! В первой из них мы создаем экземпляр класса SoapClient и передаем в его конструктор адрес расположения WSDL-файла, а в параметрах явно указываем, что работать мы будем по протоколу SOAP версии 1.2. В следующей строке мы вызываем метод sendSms объекта $client и сразу же выводим в браузере результат.
Давайте запусти и посмотрим что-же у нас наконец-то получилось!
Мне с сервера вернулся следующий объект:
И это замечательно, т.к. теперь мы точно знаем о том, что наш сервер работает и не просто работает, но еще и может возвращать на клиент какие-то значения!
Теперь посмотрим на лог, который мы предусмотрительно ведем на серверной стороне! В первой его части мы видим необработанные данные, которые поступили на сервер:
Это и есть конверт. Теперь вы знаете как он выглядит! Но постоянно на него любоваться нам вряд ли будет интересно, поэтому давайте десереализуем объект из лог-файла и посмотрим все ли у нас хорошо:
Как видим, объект десериализовался правильно, с чем я нас всех хочу поздравить! Далее нас ждет что-то более интересно! А именно – мы будем отправлять клиентом на сервер не одно sms-сообщение, а целую пачку (если быть точнее, то целых три)!
7 Отправляем сложные объекты
Давайте подумаем над тем, как же нам передать целую пачку сообщений на сервер в одном пакете? Наверно, самым простым способом будет организация массива внутри элемента messageList! Давайте это сделаем:
В наших логах числится, что пришел следующий пакет от клиента:
Что за ерунда, скажете вы? И будете правы в некотором смысле, т.к. только что мы узнали о том, что какой объект ушел от клиента, то абсолютно в том же виде он пришел к нам на сервер в виде конверта. Правда, sms-сообщения сериализовались в XML не так, как нам было необходимо – они должны были быть обернуты в элементы message, а не в Struct. Теперь посмотрим в каком виде приходит такой объект в метод sendSms:
Что нам дает это знание? Только то, что выбранный нами путь не является верным и мы не получили ответа на вопрос – «Как нам на сервере получить правильную структуру данных?». Но я предлагаю не отчаиваться и попробовать привести наш массив к типу объект:
В этом случае, нам придет уже другой конверт:
Пришедший в метод sendSms объект имеет следующую структуру:
Как по мне, то «от перемены мест слагаемых – сумма не меняется» (с). Что BOGUS, что Struct – цель нами до сих пор не достигнута! А для ее достижения нам необходимо сделать так, чтобы вместо этих непонятных названий отображалось наше родное message. Но как этого добиться, автору пока не известно. Поэтому единственное, что мы можем сделать – избавить от лишнего контейнера. Другими словами, мы сейчас сделаем так, чтобы вместо message стал BOGUS! Для этого изменим объект следующим образом:
Вдруг нам повезет и из схемы подтянется правильное название? Для этого посмотрим на пришедший конверт:
Да, чуда не произошло! BOGUS – не победим! Пришедший в sendSms объект в этом случае будет выглядеть следующим образом:
Как говорится – «Почти»! На этой (немного печальной) ноте предлагаю потихонечку закругляться и сделать некоторые для себя выводы.