Рад сообщить, что по состоянию на 06:00 18 мая 2015 года PSR-7 (HTTP Message Interfaces) был принят!
UPD. Хороший перевод «PSR-7 в примерах».
Дорога к PSR-7
Путь к PSR-7 был долгим и извилистым. Все началось летом 2012 года с проекта предложения по работе с HTTP клиентами за авторством Бенджамина Эберлея (Benjamin Eberlei), в течение обсуждения которого другие участники предложили, что, возможно, небольшой стандарт на http-сообщения — вот что позволило бы решить все проблемы.
Старт
Крис Уилкинсон (Chris Wilkinson) подхватил идею и создал формальный черновик, который и стал впоследствии PSR-7. В нем был разработан оригинальный интерфейс для работы HTTP сообщений. Во время своего пребывания на посту редактора Крис также начал составление сопутствующего предложения по URI, но оно так никогда и не вошло в PSR. PSR-7 полировался в течение значительного срока, особенно раздел об аспекте сохранения заголовка как части сообщения и имел
MessageInterface
, описывающий общие черты между двумя типами сообщений с описанием отличий запроса и ответа.В определенный момент (я точно не знаю, до сих пор не нашел никакого формального анонса в архивах группы) эстафету передали Майклу Доулингу (Michael Dowling). Самым большим его вкладом стало предложение моделирования тела сообщения в виде потока. Внедрение показалось довольно спорным, и в итоге вытекло в большой пост с подробным описанием почему и зачем принято такое решение. По-моему, это потрясающе! Я проверил, каждый хороший язык имеет превосходную HTTP абстракцию, моделирующую тело сообщения в виде потока: это позволяет работать асинхронно (что, увы, довольно долго не поддерживалось в PHP), и гарантирует, что большие сообщения не съедят всю доступную память. Сам PHP имеет модель сообщений в виде стримов (
php://input
и выходной буфер), именно этот путь является самым естественным.Влияние node.js
Вскоре после появления этого поста, я сильно заигрался с node.js и был поражен тем, как работают различные модули в плане обработки http. Это в значительной степени обусловлено наличием по-умолчанию хорошо разработанной абстракции протокола http с отличным побочным эффектом в виде возможности использования одинаковой работы с http практически везде.
Я решил портировать Connect, промежуточную библиотеку, поставляемую с Express, возможно самым распространенным фреймворком в node.js. Но делая это я столкнулся с непреодолимым препятствием: http абстракция.
Конечно, каждый фреймворк имеет HTTP абстракцию. Я даже контрибьютил в один, предназначенный для Zend Framework. Ход мыслей был таким: я хочу разобраться, как и многие PHP-разработчики, в этих понятиях, узнать как это работает, но выбор конкретной http абстракции может повлиять на дальнейшее развитие проекта. И тут я вспомнил о посте Майкла про PSR-7 и потоки. Тогда-то и пришло понимание — «мне нужно нацелиться на PSR-7!»
Проблема заключалась в отсутствии имплементации.
Итак, за выходные был реализован первоначальный вариант. Примерно через пару дней после публикации Майкла стали ходить слухи о том, что он собирается отказаться от PSR-7 из-за нехватки времени.
Мой приход
После нескольких недель обсуждений и тяжелых раздумий я решил подхватить черновик и попробовать сдвинуть его с мертвой точки. Фил Стерджен (Phil Sturgeon) и Бо Сименесен (Beau Simensen) договорились продолжать в качестве спонсора и координатора. Так и началось мое пребывание на посту редактора.
Это стало интересным вызовом. Когда я начинал, еще не утихли дебаты об использовании потоков. Пришлось в срочном порядке наращивать базу аргументов Майкла в пользу именно такого решения и подумать, согласен ли я защищать его или действительно есть варианты лучше.
Обнаружился еще один аспект, который следовало устранить: сообщения работали превосходно для клиентской стороны, но сервер был в проигрыше: пользователям приходилось разбирать URI для запроса строковых аргументов и парсить тело сообщения вручную, и заголовки для куков, и… в общем, я пришел к выводу, что получается как в node.js: либо ты делаешь все руками, либо сваливаешь всю работу на микрофреймворк.
Где-то в глубине было чувство, что мы могли бы сделать лучше. Таким образом родился
ServerRequestInterface
, обеспечивающий доступ к данным, находящимся в суперглобальных переменных PHP, а также дающий некоторые необходимые абстракции для заполнения данных, для тех случаев, когда PHP работает плохо (например, вы не можете получить заполненный $_POST
для не-POST запросов или для POST запросов без специфических media-типов).Прогресс
Ушел декабрь 2014 и вместе с ним ушел в отставку Фил, оставив меня в поисках дополнительного спонсора. Пол Джонс (Paul M Jones) любезно предложил свою кандидатуру.
Часть стандарта, касающаяся серверных запросов множество раз вызывала кучу критики, но в итоге мы достигли консенсуса в этом вопросе. Множество обеспокоенных людей высказывались по поводу мутабельности объектов. В январе я глубоко погрузился в понимание неизменности объектов и прикладных концепций спецификации. В итоге мы получили нечто очень надежное, без побочных эффектов, устраняющее целые категории возможных проблем из-за изменяющегося состояния. Но и это решение сообщество приняло со скрипом, ребята не успокаивались, пока не увидели реальных примеров.
Также был введен
UriInterface
для упорядочивания URI компонентов. Мы обнаружили, что очень часто приходится разбирать URI для получения таких вещей, как схема, путь, хост и т.д. Довольно утомительное и нудное занятие, чреватое ошибками. Наличие абстракции расставило все на свои места. Она сделана таким образом, чтобы можно было иметь совместимость с более поздними предложениями по URI и в значительной степени заимствовала подходы, сделанные ранее Крисом Уилкинсоном.Голосования
В этот момент мы решили выставить черновик на голосование. Первоначальные результаты были весьма позитивными и это выглядело так, как будто дело в шляпе. Но где-то на второй неделе стали приходить люди, которые видели предложение в первый раз. Ничего не сравнится с въедливым вниманием разработчиков к деталям, именно они и помогли понять, что есть ряд изъянов. Ключевым среди них стало то, что мы не сделали большую работу по описанию связей между URI и заголовками хоста, не была хорошо проработана загрузка файлов.
Отменив голосование примерно за 24 часа до принятия, мы вернулись к этапу проектирования. Бернхард Шуссек (Bernhard Schussek) предоставил некоторые отличные обоснования по абстракции передачи файлов, которые мы в итоге включили, также проработали отношения URI/Host в сторону упрощения по отношению к предыдущей версии.
И это привело нас к повторному голосованию, которое в свою очередь пришло к логическому завершению: новый PSR был принят!
Спасибо
Я, как редактор и в значительной степени публичное лицо, не могу не отметить, что это был результат многолетней работы множества людей. И особенно я хочу поблагодарить:
- Ларри Гарфилда (Larry Garfield), который протестировал PSR-7 на некоторых проектах, и позволил получить фидбек о перспективах использования.
- Эверта Пота (Evert Pot), который в конечном итоге проголосовал против принятия стандарта, но предоставил фантастические отзывы, принимая участие в обсуждении на протяжении всей жизни черновика. Его помощь была неоценима.
- Фила, Бо, и Пол, которые читали мои тирады, полные разочарования и неуверенности в себе на протяжении последних нескольких месяцев!