Карта відповідності RFC

На цій сторінці перелічено стандарти, важливі для OxPHP як origin-сервера: HTTP, TLS, статичні файли та шлюз до PHP. Сторінка описує OxPHP 0.13.0. WebDAV, проксіювання та спільні кеші лежать поза її межами.

Стандарт вважається реалізованим, якщо відповідна поведінка є. Частину її забезпечує сам OxPHP, а частину дають бібліотеки HTTP, TLS і стиснення, на яких побудовано OxPHP і які він налаштовує.

Повністю реалізовано

  • RFC 9112, HTTP/1.1: keep-alive, chunked-тіла, Expect: 100-continue і конвеєризація запитів. Тайм-аут обмежує, скільки часу клієнт може витратити на надсилання заголовків.
  • RFC 9113, HTTP/2: через TLS, а також через звичайний TCP для клієнтів, які підключаються з попереднім знанням (prior knowledge). Кількість одночасних потоків і розмір заголовків обмежено, атаки Rapid Reset і MadeYouReset блокуються, а під час дренування сервер повідомляє про це фреймом GOAWAY.
  • RFC 7541, HPACK: стиснення заголовків HTTP/2 з обмеженням розміру декодованих заголовків, яке зупиняє запити типу «HPACK-бомба».
  • RFC 8446 і RFC 5246, TLS 1.3 і 1.2: обидві версії, а мінімальну версію можна підняти до 1.3. Ранні дані 0-RTT вимкнено, тож ранні запити неможливо відтворити повторно.
  • RFC 7301, ALPN: під час TLS-рукостискання обирається h2 або http/1.1.
  • RFC 9110, запити Range: один діапазон байтів для GET і HEAD, відповідь 206 або 416. Запит кількох діапазонів отримує весь файл із 200, і стандарт це дозволяє. Коли відповідь стискається, діапазони вимикаються.
  • RFC 9110, If-Range: враховується лише із сильним валідатором, як вимагає стандарт.
  • RFC 9110, кодування вмісту: Brotli, gzip і Zstandard. Ваги в Accept-Encoding враховуються, а q=0 означає, що клієнт відмовляється від цього кодування. Стиснені відповіді мають Vary: Accept-Encoding і слабкий ETag. Потоки подій ніколи не стискаються.
  • RFC 9110, Retry-After: надсилається з 429 (час, що лишився до кінця вікна обмеження частоти), з 503, поки сервер дренує зʼєднання або завершує роботу, і з 529, коли він перевантажений.
  • RFC 6585, 429 Too Many Requests: обмеження частоти запитів за IP-адресою відповідає 429 із Retry-After.
  • RFC 9110, HTTP-дати: дати в заголовках читаються й записуються в стандартному форматі.
  • RFC 10008, метод QUERY: приймається разом із тілом, яке PHP читає так само, як тіло POST. Для нього діє окремий ліміт розміру тіла. Запит QUERY без Content-Type отримує 400.
  • RFC 7578, multipart/form-data: завантаження файлів працює так само, як у будь-якому розгортанні PHP.
  • RFC 9113 і RFC 6265, розділені заголовки Cookie: коли клієнт надсилає Cookie кількома рядками заголовка, як часто роблять клієнти HTTP/2, OxPHP обʼєднує їх в один, перш ніж їх побачить PHP.
  • RFC 8615, well-known URI: шляхи під /.well-known/ віддаються, хоча інші шляхи з крапкою заблоковано. PHP-файли в цьому каталозі ніколи не виконуються.
  • RFC 1918, RFC 4193 і RFC 3927, приватні мережі: ключове слово private у списку довірених проксі охоплює всі ці діапазони. NAT операторського рівня (RFC 6598) до нього не входить, і його діапазон треба вказати вручну.
  • RFC 7034, X-Frame-Options: за замовчуванням SAMEORIGIN, надсилається разом із відповідним CSP frame-ancestors і X-Content-Type-Options: nosniff. Заголовки, які встановлює ваш застосунок, мають пріоритет.

Охоплено й кілька стандартів поза серією RFC:

Частково реалізовано

  • RFC 3875, CGI/1.1: стандартні змінні CGI є в $_SERVER, а кожен заголовок запиту потрапляє туди як HTTP_*. Чого бракує: обʼєднання заголовка, надісланого кількома рядками, в одне значення, як того вимагає стандарт. $_SERVER зберігає останній рядок, тоді як API HTTP-запиту зберігає перший. REMOTE_HOST не встановлюється.
  • RFC 7239, Forwarded: OxPHP читає Forwarded і X-Forwarded-* від довірених проксі, а за Cloudflare також CF-Connecting-IP. Чого бракує: значення в лапках, що містить кому або крапку з комою, розбивається не в тому місці. X-Real-IP не підтримується.
  • RFC 9110, умовні запити: статичні файли підтримують If-None-Match і If-Modified-Since і відповідають 304. Чого бракує: If-Match, If-Unmodified-Since і 412 Precondition Failed.
  • RFC 9111, HTTP-кешування: статичні файли отримують Cache-Control з налаштовуваним max-age, а також ETag, Last-Modified і Vary. Чого бракує: immutable, а кожен файл отримує ту саму політику незалежно від свого типу чи шляху.
  • RFC 9110, методи запиту: тіла читаються для POST, PUT, PATCH, DELETE і QUERY, а завелике тіло відхиляється з 413 ще до того, як його прочитано. Чого бракує: статичний файл відповідає на будь-який метод, зокрема POST і DELETE, кодом 200 і своїм вмістом, тоді як nginx відповідає 405 із заголовком Allow.
  • RFC 7617, автентифікація Basic: заголовок Authorization доходить до PHP як HTTP_AUTHORIZATION. Чого бракує: заповнення PHP_AUTH_USER, PHP_AUTH_PW і AUTH_TYPE.
  • RFC 3986, URI: percent-декодування і розбір хоста працюють, зокрема для IPv6-адрес, а шляхи із сегментами . або .. отримують 404. Чого бракує: кінцева скісна риска відкидається ще до маршрутизації, тож /dir віддає індекс каталогу без переспрямування на /dir/, а файл відповідає ще й за адресою /file/.
  • RFC 6265, cookie: cookie, які плагіни OxPHP встановлюють для себе, мають SameSite, HttpOnly, Secure і Max-Age. Cookie вашого застосунку, як і зазвичай, проходять через setcookie() у PHP. Чого бракує: для некоректної пари cookie cookie() з API HTTP-запиту і $_COOKIE можуть повертати різні значення.

Дорожня карта

Це пропозиції, впорядковані за пріоритетом. Жодну з них не заплановано на конкретний реліз.

Високий пріоритет

  • RFC 3875: обʼєднувати заголовок, що надходить кількома рядками, в одне значення через кому, щоб PHP бачив увесь ланцюжок X-Forwarded-For від низки проксі.
  • RFC 7617: заповнювати PHP_AUTH_USER і PHP_AUTH_PW з даних автентифікації Basic. Зараз застосунки, які їх читають, отримують порожні значення без жодної помилки.
  • RFC 6797, HSTS: надсилати Strict-Transport-Security у кожній HTTPS-відповіді, зокрема для статичних файлів і сторінок помилок. PHP не може додати його до статичних файлів, бо ці запити до нього не доходять.

Середній пріоритет

  • RFC 7239: правильно розбирати значення в лапках у Forwarded.
  • RFC 9110: відповідати 405 з Allow: GET, HEAD, коли статичний файл отримує будь-який інший метод, як це робить nginx.
  • RFC 3986: у режимі маршрутизації Traditional переспрямовувати /dir на /dir/ з 301, щоб у старіших застосунках працювали відносні посилання.
  • Поля заголовків RateLimit (чернетка IETF): надсилати RateLimit і RateLimit-Policy, щоб клієнт бачив свій ліміт ще до того, як у нього впреться. Зараз заголовки X-RateLimit-* зʼявляються лише у відповіді 429.
  • W3C Server-Timing: повідомляти час очікування в черзі та час виконання PHP у заголовку Server-Timing. OxPHP уже вимірює обидва значення для метрик і трасування.

Низький пріоритет

  • RFC 9110: If-Match, If-Unmodified-Since і 412 для статичних файлів. Статичні файли доступні лише для читання, тож це рідко мало б значення.
  • RFC 6455 і RFC 8441, WebSocket: WebSocket через HTTP/1.1 і HTTP/2. Архітектуру рішення ще опрацьовують.
  • RFC 8297, Early Hints: 103 Early Hints, щоб браузери могли почати попереднє завантаження ресурсів ще до того, як відповідь буде готова.
  • RFC 8446, клієнтські сертифікати: взаємний TLS для середовищ, побудованих за моделлю нульової довіри.
  • RFC 9114, HTTP/3, разом із RFC 7838, Alt-Svc: великий обсяг роботи, і незрозуміло, чи вона окупиться.

Розглянуто й відхилено

Межа проходить між обробкою HTTP, за яку відповідає сервер, і вмістом конкретного сайту, за який він не відповідає.

  • RFC 9116, security.txt: цей файл містить контакти з питань безпеки тих, хто керує сайтом, а сервер їх не знає. Вбудований варіант за замовчуванням був би порожнім або помилково вказував би на супровідників OxPHP. Покладіть файл у корінь документів, і OxPHP віддаватиме його як будь-який інший статичний файл. nginx, Apache і FrankenPHP теж не генерують такого файлу.
  • RFC 3875, PATH_TRANSLATED: стандарт рекомендує встановлювати цю змінну, коли задано PATH_INFO. Вона існує для CGI-скриптів, які обробляють якийсь інший файл. В OxPHP скриптом, що виконується, завжди є SCRIPT_FILENAME, а типова звʼязка nginx із PHP-FPM і php -S цю змінну теж не встановлюють. Її значення будувалося б із PATH_INFO, який надіслав клієнт, тож старий код, що підключає $_SERVER['PATH_TRANSLATED'], завантажив би файл на вибір клієнта.
  • RFC 7540, перехід на h2c: RFC 9113 прибрав рукостискання Upgrade: h2c. OxPHP обслуговує HTTP/2 без TLS для клієнтів із попереднім знанням, і цього достатньо.

Див. також