Обрабатывая сообщение, SOAP узел берет на себя одну или более ролей, которые влияют на то, как обрабатываются SOAP заголовки. Ролям даются уникальные имена (в форме URI), таким образом, они могут быть идентифицированы во время обработки. SOAP узел, получив сообщение для обработки, сначала должен определить, какие роли он будет выполнять. Для этого он может проверить SOAP сообщение.
Как только он определится с ролями, которые будет выполнять, SOAP узел должен обработать все обязательные заголовки (отмеченные mustUnderstand="1"), направленные на одну из его ролей. Также SOAP узел может выбрать для обработки любой необязательный заголовок (отмеченный mustUnderstand="0"), направленный на одну из его ролей.
SOAP 1.1 определяет только одну роль - http://schemas.xmlsoap.org/soap/actor/next (next для краткости). Каждый SOAP узел должен принять роль next. Таким образом, когда SOAP сообщение приходит в любой данный SOAP узел, узел должен обработать все обязательные заголовки, нацеленные на роль next, и он может обработать необязательные заголовки, также нацеленные на роль next. Кроме next, SOAP 1.2 определяет еще несколько ролей (см. Таблица 3), приложениям разрешено также определять собственные роли.
SOAP заголовки нацеливаются на конкретные роли с помощью глобального атрибута actor (в SOAP 1.2 этот атрибут назван role). Если этого атрибута нет, заголовок по умолчанию нацеливается на конечного получателя. Следующее SOAP сообщение иллюстрирует, как использовать actor:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<wsrp:path xmlns:wsrp="http://schemas.xmlsoap.org/rp"
soap:actor="http://schemas.xmlsoap.org/soap/actor/next"
soap:mustUnderstand="1"
>
...
Поскольку заголовок wsrp:path нацелен на роль next и помечен как обязательный (mustUnderstand="1"), первый SOAP узел, получающий это сообщение, должен обработать его в соответствии со спецификацией блока заголовка, в данном случае WS-Routing. Если SOAP узел разработан так, что не понимает обязательного заголовка, нацеленного на одну из его ролей, он должен сгенерировать SOAP ошибку с кодом состояния soap:MustUnderstand и прервать обработку. Чтобы определить, что вызвало ошибку в прохождении сообщения, элемент SOAP Fault предоставляет дочерний элемент faultactor. Значением атрибута faultactor является URI, который идентифицирует SOAP узел, вызвавший ошибку.
Если SOAP узел успешно обработал заголовок, требуется удалить этот заголовок из сообщения. SOAP узлам разрешено повторно вставлять заголовки, но это изменяет участников контракта – теперь заголовки targets между текущим и следующим узлами. Если SOAP узел оказывается конечным получателем, он также должен обработать и SOAP тело.
Таблица 3. Роли SOAP 1.2
Имя SOAP роли | Описание |
http://www.w3.org/2002/06/soap-envelope/role/next | Каждый SOAP посредник и конечный SOAP получатель ДОЛЖНЫ выполнять эту роль и МОГУТ дополнительно принимать ноль или более других SOAP ролей. |
http://www.w3.org/2002/06/soap-envelope/role/none | SOAP узлы НЕ ДОЛЖНЫ выполнять эту роль. |
http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver | Чтобы объявить себя конечным SOAP получателем, SOAP узел ДОЛЖЕН выполнять эту роль. SOAP посредники НЕ ДОЛЖНЫ выполнять эту роль. |
Взамодействие протоколов
Интересно, что на Рисунке 3 SOAP обеспечивает обмен сообщениями через различные базовые протоколы. Поскольку оболочка обмена SOAP сообщениями не зависит от базовых протоколов, каждый посредник может использовать различные протоколы обмена без влияния на SOAP сообщения. Однако для обеспечения высоких уровней взаимодействия между SOAP приложениями и инфраструктурой необходимы стандартные взаимодействия протоколов.
Конкретное взаимодействие протоколов определяет как именно SOAP сообщения должны передаваться с помощью данного протокола. Иначе говоря, он определяет детали того, как SOAP согласовывается в рамках другого протокола, который, возможно, имеет собственную оболочку обмена сообщениями наряду с разнообразием заголовков. Что действительно определяет взаимодействие протоколов в большой степени зависит от характеристик и возможностей протокола. Например, взаимодействие протоколов для TCP будет сильно отличаться от взаимодействия для MSMQ или SMTP.
Спецификация SOAP 1.1 кодифицирует взаимодействие протоколов только для HTTP из-за его широкого распространения. SOAP используется и с другими протоколами, но реализации не следовали стандартизованному взаимодействию.
HTTP взаимодействие
Взаимодействие протокола HTTP определяет правила использования SOAP поверх HTTP. SOAP запрос/ответ просто преобразовывается в модель HTTP запроса/ответа. Рисунок 4 иллюстрирует многие детали соединения SOAP HTTP.
Рисунок 4. SOAP HTTP взаимодействие
Заголовок Content-Type для HTTP сообщений запроса и ответа должен быть text/xml (application/soap+xml в SOAP 1.2). Что касается сообщения запроса, оно должно использовать в качестве команды слово POST, и URI должен определять SOAP обработчик. Спецификация SOAP также определяет новый HTTP заголовок – SOAPAction, который должен присутствовать во всех SOAP HTTP запросах (даже если они пустые). Заголовок SOAPAction предназначен для выражения цели сообщения. Что касается HTTP ответа, он должен использовать код состояния 200, если не произошла ошибка, или 500, если тело содержит SOAP Fault.
RPC и кодирование
Хотя спецификация SOAP развивалась в сторону от объектов, она до сих пор определяет соглашение для инкапсуляции и обмена RPC вызовами с использованием оболочки обмена сообщениями, описанной выше. Определение стандартного способа преобразования RPC вызовов в SOAP сообщения дает возможность инфраструктуре во время выполнения автоматически проводить преобразования между вызовами методов и SOAP сообщениями без доработки кода на платформе Web сервисов.
Чтобы сделать вызов метода, используя SOAP, инфраструктуре нужна следующая информация:
1. Местоположение (URI)
2. Имя метода
3. Имена/значения параметра
4. Необязательно сигнатура метода
5. Необязательно данные заголовка
Эта информация может переноситься различными способами, включая библиотеки типов, IDL файлы или лучше WSDL файлы. Взаимодействие SOAP RPC определяет, как инкапсулировать или представить эту информацию в SOAP теле. Сначала определяется, как сигнатура метода преобразовывается в простые структуры запроса/ответа, которые затем могут быть кодированы как XML. Соединение RPC устанавливает, что вызов метода будет сделан как struct, названная так же как и метод. Struct будет содержать аксессор для каждого параметра [in] или [in/out], названный так же как и параметр, и в последовательности, определенной сигнатурой сообщения. Ответ метода также будет смоделирован как struct. Имя struct может быть любым, хотя, согласно соглашению, надо использовать имя метода, оканчивающееся словом "Response" (т.е. для операции add ответ метода, соответственно, будет называться addResponse). Struct ответа содержит аксессор для возвращаемого значения (в SOAP 1.1 имя не имеет значения, но в SOAP 1.2 должно быть rpc:result), за которым следует аксессор для каждого параметра [out] или [in/out].
Давайте рассмотрим пример. Следующая сигнатура метода на C# допускается для операции add:
double add(ref double x, double y)
В соответствии с только что описанными правилами RPC соединения, struct запроса, представляющая вызов метода, будет смоделирована следующим образом:
struct add {
double x;
double y;
}
В то время как struct ответа будет выглядеть так:
struct addResponse {
double result;
double x;
}
Теперь вопрос в следующем: как должны эти структуры преобразовываться в XML? Спецификация SOAP именно для этих целей определяет ряд правил кодирования. Правила кодирования SOAP описывают, как преобразовывать наиболее часто используемые сегодня структуры данных (такие как structs и массивы) в общий XML формат. Согласно правилам кодирования SOAP, struct запроса из примера, приведенного выше, преобразуется в следующее XML сообщение (оно будет помещено в SOAP тело):
<add>
<x>33</x>
<y>44</y>
</add>
И ответное сообщение на этот запрос будет преобразован в XML сообщение (которое пойдет в тело ответного сообщения):
<addResponse>
<result>77</result>
<x>33</x>
</addResponse>
Правила SOAP кодирования были введены во время, когда работа над XML Schema только начиналась. Теперь эта XML Schema закончена, разработчики могут просто обеспечить литеральные описания XML Schema, которые точно определяют, как сообщения запроса/ответа должны форматироваться в XML. Из-за того, что, используя описания XML Schema, стало проще достигнуть возможности взаимодействовать, большинство разработчиков решили полностью отказаться от правил SOAP кодирования. Кстати, что касается SOAP 1.2, спецификацией больше официально не требуется поддержка правил SOAP кодирования. Дискуссия на эту тему, почему приведена в The Argument Against SOAP Encoding.
Хотя взаимодействие SOAP RPC и правила кодирования обеспечивают хороший уровень SOAP интеграции для приложений, которые не хотят копаться в таких вещах как XML Schema или WSDL, они сильно вышли за пределы интересов сообщества Web сервисов, потому что больше сместились в сторону вопросов взаимодействия.
SOAP стили
Повторим, сегодня существует два основных стиля обмена SOAP сообщениями: документ и RPC. Стиль документ свидетельствует о том, что тело просто содержит XML документ, формат которого отправитель и получатель должны согласовать. С другой стороны, стиль RPC свидетельствует о том, что тело содержит XML представление вызова метода, как мы только что обсудили.
Также есть две техники для решения того, как сериализовать данные в тело: используя литеральные описания XML Schema и используя правила SOAP кодирования. В первом подходе описание схемы литерально определяет XML формат для тела без неоднозначностей. Во втором подходе, однако, SOAP обработчик должен во время выполнения перебрать различные правила SOAP кодирования, чтобы найти подходящую сериализацию для тела. Очевидно, что эта техника более подвержена ошибкам и проблемам взаимодействия.
Чаще всего используется стиль документа с литеральными описаниями схемы (известен как документ/литеральный) и RPC стиль с правилами SOAP кодирования (известен как rpc/кодированный). Документ/кодированный и rpc/литеральный возможны, но они не общеприняты и не имеют особого смысла. Документ/литеральный – это стиль, на котором сфокусировано большинство платформ Web сервисов, и сегодня он применяется по умолчанию в оболочке WebMethod Microsoft® ASP.NET.
Заключение
SOAP определяет простую и наращиваемую оболочку обмена XML сообщениями, которая может использоваться во многих протоколах с разнообразными моделями программирования, несмотря на то, что спецификация описывает только то, как использовать SOAP с HTTP и RPC вызовами. SOAP также определяет полную модель обработки, которая описывает механизм обработки сообщений. В целом, SOAP предоставляет богатую и гибкую оболочку для определения протоколов высокоуровневых приложений, которые предлагают улучшенную возможность взаимодействия в распределенной, гетерогенной среде.