HTTP внутри HTTP это, как реторта с
личинками дельфинов - вещь в себе
Если вы разрабатываете REST API, то рано или поздно к вам придут ваши клиенты с просьбой сделать пакетную обработку. Сделать так, что бы сервер приимал произвольный набор запросов одним пакетом и отправлял назад все результаты тоже одновременно. Это касается не только GET запросов, а любых методов - PUT, POST, DELETE и т.д. Ответы тоже будут разные, и будут содержать различные типы данных - например текст в различных encoding-ах и charset-ах, или двоичные данные в произвольном формате. В общем случае, скажут они, было бы полезно уметь обрабатывать пакеты любых HTTP запросов, в том числе запросы к внешним серверам которые необходимо исполнить последовательно с запросами к серверам из локальной сети.
С первого взгляда это кажется замечательной идеей. Клиент делает единственный POST запрос, получает единственный ответ и здорово экономит на сетевых задержках. На самом деле, здесь столько подводных камней, что вы сможете пожалеть что вообще с этим связались. Но выбора обычно нет. Что же тут плохого? Посмотрим сначала на
Религиозные проблемы REST
- Очевидно, что URI этого прокси одинаков для пакетов любых запросов - на вход поступауют произвольные запросы, на выходе мы имеет произвольные ресурсы. Значит этот URI перестаёт уникально идентифицировать ресурсы которые этот прокси обрабатывает
- Требуемая операция содержится не в HTTP verb, а в теле запроса. И несмотря на то, что POST request вроде как является non-idempotent & non-safe - внутри может быть что угодно - как набор совершенно безобидных GET запросов, так и действительно non-idempotent POST запросы, а может быть и вовсе некоторая смесь из них. Только клиент и сервет знают, что же там такое внутри. HTTP метод перестал быть понятным для всех транзитных серверов, таких как HTTP прокси и кеши
- В зависимости от набора запросов в пакете, сервер может создать новые ресурс(ы), обновить или удалить старые, или просто вернуть запрошенный ресурс. Некоторые из этих запросов могли завершиться с ошибкой, а другие были успешными. Передать эту информацию обратно клиенту в HTTP header нелегко, значит она будет втиснута в body ответа. Значит response тоже перестал быть прозрачным для всех транзитных серверов
Ну вот и всё, что бы из REST сделать SOAP больше ничего не нужно. На самом деле, стало даже хуже, чем если бы SOAP использовалось с самого начала - транзитные сервера теперь не знают у каких request/response HTTP headers значат то, что написанно в спецификации, а у каких уже ничего не значат.
Существуют также и
Прочие недостатки пакетирования запросов
Каким бы образом это решение не было бы сделано, результат будет являться тунелированием HTTP протокола внутри HTTP протокола. Задумайтесь на секунду, что это значит.
- Клиенты должны понимать все тонкости HTTP, и не только на этапе создания пакета запросов, но также они должны иметь обработчики ошибок, повторов и т.п. Они должны уметь обрабатывать все фокусы HTTP протокола - chunked и gzipped ответы. Перенаправления и HTTP headers
- Транзитные сервера перестанут кешировать, исчезнет поддержка ETag, If-Modified-Since и т.п. А умные load-balancer-ы перестанут load balance-ить
- Сломается “conversation pattern” если таковой будет подразумеваться конечным сервером.
- Огромная дыра в security, привет системным администраторам
- ~37% overhead в трафике из-за преобразования двоичных данных в текст, а также неизвестный CPU overhead на сервере и клиенте что бы эти данные кодировать-декодировать
- Поддержка атомарности выполнения всего набора запросов
- Определение порядка выполнения запросов в наборе
На самом деле, если заглянуть в спецификацию протокола HTTP 1.1 то можно увидеть, что существует «Идеальное» решение
продолжение см
часть II “Идеальное” решение оригинал:
www.katkovonline.com