Извлечение данных из объектов MTOM/XOP#
Для начала подготовим данные, которые будут возвращаться заглушкой в качестве объекта MTOM/XOP.
mtom_response.xml:
--MIME_boundary
Content-Type: application/soap+xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: <claim@insurance.com>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xop='http://www.w3.org/2004/08/xop/include'
xmlns:xop-mime='http://www.w3.org/2005/05/xmlmime'>
<soap:Body>
<submitClaim>
<accountNumber>5XJ45-3B2</accountNumber>
<eventType>accident</eventType>
<archive xop-mime:content-type='application/gzip'><xop:Include href="cid:archive@insurance.com"/></archive>
</submitClaim>
</soap:Body>
</soap:Envelope>
--MIME_boundary
Content-Type: application/gzip
Content-Transfer-Encoding: binary
Content-ID: <image@insurance.com>
H4sICJNri14AA3Rlc3QAAQAE//v78FKopyaULbG8dl6AEtqxMx595YlgwpbBKS53ywNdf6KxAplsspeKDRMo2OIhni5G0j6m79LW0CSZaEXM6IvHGu2+ml07YmsO1Jv+mFYWiO2Gf+L5nebOGPJe0lyoEasElioisBc+s92792L2MPOkJ/OuqDgFu3iDOXNpS4brV3SdIe70DzHDNzhTdnq4CwVYztJw6D49Bjq0beCo5hXOujmwTLMKOkP/yk8QwxsajrL1Ysxvu9E1UsfSZDFWYKiKrZy6qBDc9Kp3G2iTOc2/8oHErewk40OetYG9iyrT+8tIEqrRQNW1bLMcfC5eIu+4TnHa021vqhUSob3vb7yEnvusi3ucaQ7plpt6bvDB/E8Dg6kyuuhc9vgjX3H27R/OP5f+P1Up4TeArAS25sL3KeLdZJ7F2d/b1bVjd3593D3MO84Ye4t/8I+eDFXlKflPWRqA3yqVVzgPawtSL1DFhK6e1jg7zBGC1FrosoFTtYeuuqAgyePMuOUZYdJmgHe6fk6NRs5jEC9sXGhnOGs1KxU+nFWpPAYDhUSwbrE8AbBggkxHKaqVjmJYjV2QQrZpNaHWOpqA0hAUdF/KK9iglJF/mGX93mlDyOz683ULAQs6edXCBQrYptwKGyuQfrOF+sHfhBzrW675qsI+pazZPOKBISB8+waXgvtIpLQoJiqcsdZxZxDcdQcMv+csJpQRaSMNW6Uv94tZyFuSUXUTvN3QI1FXRKd2SBzC5/YM26qmB+b/AM7m3bWqWySzk2tjaLd8pZg/AucOcpqTt2Ur89d/lzrxS3lu5kBpSS0Zr2fAeSpIJL8GnlphK8Pfw7EU1KnR5k7tfu3iQyy1RTPJ7p8wDdHQtPQZzPb40gCMG7Nt15fdSGxytUsleAgH+LKOwoPrxcUIx5VPpYfyg1S6sUkMOTfOhvPLmlcIZagvqPdsOHLNdXyPTBfeyO9rGgo09eEyPzbAg7+Uoa7d+B9OCZPf08o3vpBIe5Iri/LZy8eMBJNFpX/jaBprSVWGHqtWlq6/Gz5mnYP9n7is6B0RXQnvS0Ek+O4Nz1COagrm/u2AxnsUhfOCKqXW9YqCGaQFpFpK8Xpg6H2zWIsEJtGF3SquJthNYqyYVb34HY8OEC7p8Q1plva9gg+lhiq6CLnBa9U40FHJZ8TYZRoQ6/T0J4MDWFcxrHfkT3fnCcx3GpP9zXrG8iKml5Ar7NmkwOr1RfRdhOx7uQt59GRy4P79+OHy+Xm9HfwPNnSKrg0EgF2fPQs3CCdovba0MKsds4PGP9BCbbR58JrE6rIsqO6wOYmisztffwKKoECIyaKtHJgryy8k6+xuwb7aZnO3pfykL8pOAD19jOuKvuyhcbvkoCqcDAAEAAA=
--MIME_boundary--
Здесь представлен простейший пример с закодированным в Base64 архивом test.gz, который был сформирован ранее.
Создадим каталог /sowa/profile_storage/custom/chain_stub/test и скопируем полученный файл mtom_response.xml.
Создадим в профиле chain_stub сервис заглушку со следующим содержимым:
- id: 3
name: simple_3
listen:
- port: 30002
url: /test
optional:
index: mtom_response.xml
response_headers:
- name: IDENT
value: $server_addr:$server_port
- name: Content-Type
value: Multipart/Related; boundary=MIME_boundary; type=\"application/soap+xml\"; start=\"<claim@insurance.com>\"
Остановим профиль заглушку, сконфигурируем, запустим и проверим что все работает.
curl -v http://localhost:30002/test/
В ответ должны прийти данные из созданного файла.
Перейдем к созданию сервиса профиля шлюза:
- id: 6
allowed_queries:
- method: get
url: /balancer
listen:
- port: 20206
chains:
response_chains:
- actions:
conditions:
- {var: "sent_http_content_type", val: ".*application/soap+xml.*", operator: "~" }
- action: MtomExtractor
params:
content_type_var: $sent_http_content_type
actions:
- action: Base64Decode
conditions:
- {var: $clj_message_mime_type, val: "^application.*", operator: "~"}
actions:
- action: CheckDataSize
params:
max_allowable_size: 5k
- action: CheckMimeType
params:
file_filter_type: extension
allowable_types: gz
message: $clj_response_body
upstream_group_id: 1
upstream_groups:
- id: 1
servers:
- server: 127.0.0.1:30002
rewrite_uri:
- from: /balancer
to: /test/
Итак, рассмотрим нашу цепочку действий подробнее:
В отличие от предыдущих примеров, здесь в качестве исходного сообщения используется ответ клиенту.
Для входного сообщения корневым действием указываем MtomExtractor, при этом явно задаем условие, что данная цепочка должна отрабатывать только для случаев, когда Content-Type содержит application/soap+xml. Это сделано для того, чтобы, например на стандартных html-ответах с ошибкой от заглушки, данное действие не отрабатывало.
Задаем обязательный параметр content_type_var со значением sent_http_content_type, т.к. само действие не знает, для запроса или ответа выполняется, а служебные значения, содержащиеся в Content-Type, для него нужны.
Далее определяем для действия MtomExtractor дочернее действие Base64Decode, так как данные закодированы в Base64. Тут важно, что нужно наложить ограничения на то, когда данное действие будет выполняться. Это необходимо, потому что кроме вложений извлекается также и так называемый root-элемент, представляющий собой нашу wsdl. Соответственно, для нее не нужно производить декодирование, а, например, требуется произвести валидацию. Условия можно задать различным способом, либо как в примере, используя сравнение с mime-type извлеченного вложения, либо накладывая ограничения по Content-Id - для root-сообщения это всегда будет "root", для вложений соответствующие Content-Id из заголовка. Для сравнения необходимо использовать сравнение с переменной $clj_message_id.
Далее идут два известных уже действия на сравнения по размеру и Mime-Type содержимого.
Сконфигурируем и запустим профиль.
Отправим запрос:
curl -v http://localhost:20206/balancer
И убедимся, что ответ приходит успешно:

Теперь попробуем заменить в исходном файле mtom_response.xml, закодированный в Base64 gzip, на закодированный Base64 случайный набор байт.
[sowacfg@741037ad695c chains_examples]$ head -c 1k </dev/urandom >data
[sowacfg@741037ad695c chains_examples]$ base64 -w 0 data > encodedData
После чего скопируем и вставим данные из encodedData в файл mtom_response.xml вместо предыдущей Base64 последовательности.
Отправим запрос и убедимся, что вместо ответа мы получили 403.
