Задача: Баг: проксируемый Accept ломает запросы Apollo Client с 406
Баг: проксируемый Accept ломает запросы Apollo Client с 406
Apollo Client получает проксируемый Accept от исходного HTTP-запроса, из-за чего GraphQL endpoint возвращает 406 Not Acceptable.
Проблема
При выполнении серверного запроса к GraphQL API через Apollo Client в клиент проксируется заголовок Accept исходного HTTP-запроса.
Если исходный запрос предназначен для HTML и содержит, например:
Accept: text/html
то этот же заголовок уходит в Apollo GraphQL endpoint. Apollo Server не может вернуть допустимый для такого Accept тип ответа и отвечает:
406 Not Acceptable
Характерная ошибка:
An 'accept' header was provided for this request which does not accept
application/json; charset=utf-8 or
application/graphql-response+json; charset=utf-8
В наблюдаемом случае запрос уходил на внутренний endpoint:
http://f1s:3000/api/
Причина
В Apollo Client / транспорт GraphQL проксируются входящие HTTP-заголовки без переопределения Accept. Заголовок Accept относится к внешнему запросу пользователя и не должен безусловно наследоваться внутренним GraphQL-запросом.
Что исправить
В месте формирования HTTP-заголовков Apollo Client явно переопределять Accept на значение, совместимое с GraphQL/Apollo Server, вместо использования проксированного значения.
Например:
Accept: application/graphql-response+json, application/json
Допустим и вариант только с application/json, если он соответствует используемой версии Apollo Server и принятому в проекте поведению.
Важно: изменить именно заголовок в клиенте GraphQL, а не требовать от вызывающего кода менять Accept внешнего HTTP-запроса.
Критерии готовности
- Входящий
Accept: text/htmlне проксируется какAcceptвнутреннего GraphQL-запроса. - Apollo Client отправляет GraphQL-совместимый
Accept. - Серверный запрос не получает
406 Not Acceptableиз-за внешнегоAccept. - Остальные необходимые проксируемые заголовки продолжают передаваться без регрессии.
- Добавлен тест, воспроизводящий сценарий с входящим
Accept: text/htmlи подтверждающий успешный GraphQL-запрос.