Nhiệm vụ: Lỗi: Accept bị proxy làm hỏng các yêu cầu của Apollo Client với mã 406
Lỗi: Accept bị proxy làm hỏng các yêu cầu của Apollo Client với mã 406
Apollo Client nhận được header Accept được proxy từ yêu cầu HTTP gốc, khiến cho GraphQL endpoint trả về lỗi 406 Not Acceptable.
Vấn đề
Khi thực hiện một yêu cầu phía máy chủ (server-side) tới GraphQL API thông qua Apollo Client, header Accept của yêu cầu HTTP ban đầu sẽ bị proxy sang phía client.
Nếu yêu cầu ban đầu dành cho HTML và chứa, ví dụ:
Accept: text/html
thì chính header này sẽ được gửi tới Apollo GraphQL endpoint. Apollo Server không thể trả về loại phản hồi hợp lệ cho kiểu Accept đó và trả về:
406 Not Acceptable
Lỗi đặc trưng:
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
Trong trường hợp quan sát được, yêu cầu đi tới endpoint nội bộ:
http://f1s:3000/api/
Nguyên nhân
Các HTTP header đến bị proxy vào Apollo Client / transport của GraphQL mà không ghi đè Accept. Header Accept thuộc về yêu cầu bên ngoài của người dùng và không nên được kế thừa một cách vô điều kiện bởi yêu cầu GraphQL nội bộ.
Cách khắc phục
Tại nơi khởi tạo các HTTP header trong Apollo Client, hãy chủ động ghi đè Accept thành một giá trị tương thích với GraphQL/Apollo Server thay vì sử dụng giá trị bị proxy.
Ví dụ:
Accept: application/graphql-response+json, application/json
Phương án chỉ dùng application/json cũng được chấp nhận nếu nó phù hợp với phiên bản Apollo Server đang sử dụng và hành vi quy ước trong dự án.
Quan trọng: Thay đổi chính header trong GraphQL client, thay vì bắt mã nguồn gọi phải thay đổi Accept của yêu cầu HTTP bên ngoài.
Tiêu chí hoàn thành
- Header
Accept: text/htmlđến không bị proxy thànhAcceptcủa yêu cầu GraphQL nội bộ. - Apollo Client gửi
Accepttương thích với GraphQL. - Yêu cầu phía máy chủ không nhận lỗi
406 Not AcceptabledoAcceptbên ngoài gây ra. - Các header cần thiết bị proxy khác vẫn tiếp tục được truyền đi mà không bị hồi quy (regression).
- Đã thêm bài kiểm thử (test) tái hiện kịch bản với
Accept: text/htmlđi đến và xác nhận yêu cầu GraphQL thành công.