Giải thích phương thức HTTP QUERY: RFC 10008, QUERY vs GET vs POST

RFC 10008 định nghĩa QUERY, một phương thức HTTP an toàn và lũy đẳng, mang truy vấn trong phần thân yêu cầu. Những gì đặc tả nói về Content-Type, bộ nhớ đệm, Location và Accept-Query, cách QUERY so sánh với GET và POST, và những gì đang hỗ trợ nó hiện nay.

Ashley Innocent

Ashley Innocent

28 tháng 10 2026

Giải thích phương thức HTTP QUERY: RFC 10008, QUERY vs GET vs POST

Apidog cho doanh nghiệp

Triển khai tại chỗ

SSO & RBAC

Tuân thủ SOC 2

Khám phá Apidog Enterprise

Phương thức HTTP QUERY là một phương thức request mới, được định nghĩa trong RFC 10008 (tháng 6 năm 2026), gửi một truy vấn trong phần thân request và vừa safe vừa idempotent. Hãy hình dung nó như GET có body: bạn có được không gian của POST cho các bộ lọc phức tạp và sự đảm bảo của GET về caching và tự động retry.

Nếu bạn từng nhét một bộ lọc 3 KB vào URL, hoặc gửi một tìm kiếm chỉ đọc dưới dạng POST và thấy cache cùng logic retry của mình phớt lờ nó, thì QUERY chính là giải pháp. Hướng dẫn này trình bày những gì spec quy định, QUERY so với GET và POST như thế nào, những gì hỗ trợ nó hiện nay, và cách kiểm thử một endpoint QUERY với coding agent của bạn.

Phương thức HTTP QUERY là gì?

QUERY là một phương thức HTTP yêu cầu resource đích thực thi truy vấn được mô tả trong nội dung request và trả về kết quả. Phần thân request và Content-Type của nó định nghĩa truy vấn. Phương thức này là safe (client không mong đợi thay đổi trạng thái) và idempotent (lặp lại nó có cùng hiệu ứng), nên client, proxy và cache có thể retry và cache nó giống như GET.

Spec là RFC 10008, “The HTTP QUERY Method”, một Proposed Standard được xuất bản vào tháng 6 năm 2026 bởi Julian Reschke (greenbytes), James M. Snell (Cloudflare) và Mike Bishop (Akamai). IANA đã thêm nó vào HTTP Method Registry với “safe: yes, idempotent: yes”, ngay cạnh phương thức SEARCH thời WebDAV mà nó suýt trở thành.

Một request QUERY trông như sau:

QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded
Accept: application/json

select=surname,givenname,email&limit=10&match=%22email=*@example.*%22

Server trả lời bằng 200 OK và kết quả nằm trong body.

Vì sao GET và POST chưa đủ

Trước QUERY, bạn có hai lựa chọn cho một truy vấn đọc phức tạp, và cả hai đều rò rỉ.

GET đặt mọi thứ vào URL. RFC 10008 liệt kê bốn vấn đề với cách này:

  1. Giới hạn kích thước không thể biết trước, vì một request đi qua nhiều hệ thống. RFC 9110 chỉ khuyến nghị rằng bên gửi và bên nhận hỗ trợ ít nhất 8.000 octet.
  2. Mã hóa dữ liệu có cấu trúc thành một URI hợp lệ là lãng phí.
  3. URI bị ghi log và đánh dấu trang thường xuyên hơn nhiều so với phần thân request, đây là vấn đề riêng tư đối với các bộ lọc nhạy cảm.
  4. Mỗi tổ hợp đầu vào truy vấn trở thành một resource riêng.

GET kèm body cũng không phải là câu trả lời. RFC 9110 nói rằng nội dung trong một request GET không có ngữ nghĩa được định nghĩa. Một số server đọc nó, một số bỏ qua, và một số proxy từ chối request. Bạn không thể trông cậy vào nó trên toàn bộ đường đi.

POST hoạt động, nhưng nó nói dối về ý định. Một tìm kiếm bằng POST chạy tốt, nhưng không có gì cho client, cache, proxy hay thư viện retry biết rằng thao tác này chỉ đọc. Vì vậy cache bỏ qua nó và client sẽ không retry nó sau khi kết nối bị ngắt. Nếu bạn từng phải gắn thêm một idempotency key vào một truy vấn chỉ đọc chỉ để retry an toàn, bạn đã cảm nhận được điều này.

QUERY giữ body của POST và thêm các đảm bảo của GET.

QUERY vs GET vs POST

Đây là bảng so sánh, dựa trên Bảng 1 của RFC 10008:

Property GET QUERY POST
Safe Yes Yes Potentially no
Idempotent Yes Yes Potentially no
Request body Không có ngữ nghĩa được định nghĩa Được mong đợi, định nghĩa truy vấn Được mong đợi
URI cho chính truy vấn Có, theo định nghĩa Tùy chọn, qua Location Không
URI cho kết quả Tùy chọn, qua Content-Location Tùy chọn, qua Content-Location Tùy chọn, qua Content-Location
Cacheable Có Có, body là một phần của cache key Chỉ cho GET hoặc HEAD sau đó
CORS preflight từ trình duyệt Không với các request đơn giản Luôn luôn Không với các request đơn giản

Tóm tắt ngắn: dùng GET khi truy vấn vừa vặn thoải mái trong URL, dùng QUERY khi không, và chỉ dùng POST khi request thay đổi trạng thái. Để ôn lại các phương thức cổ điển, xem hướng dẫn của chúng tôi về HTTP methods và GET vs POST.

RFC 10008 định nghĩa những gì

Content-Type là bắt buộc

Server BẮT BUỘC phải làm thất bại một QUERY có Content-Type bị thiếu hoặc không nhất quán với body. RFC khuyến nghị các mã trạng thái sau:

Location và Content-Location

Server có thể trả về hai header tùy chọn biến một QUERY thành thứ bạn có thể GET sau này:

RFC gợi ý client chuyển sang GET trên URI Location cho các request lặp lại, vì caching GET đơn giản hơn. Nếu bạn trả về một trong hai header cho một truy vấn có dữ liệu nhạy cảm, URI KHÔNG NÊN chứa các phần nhạy cảm của body gốc.

Caching

Các response QUERY có thể cache được. Cache key BẮT BUỘC phải bao gồm nội dung request và metadata liên quan như media type. Cache CÓ THỂ chuẩn hóa body trước, ví dụ bằng cách loại bỏ content encoding hoặc chuẩn hóa JSON cho type +json, để có thêm hit. Spec cảnh báo rằng chuẩn hóa sai có thể trả về response sai, nên hãy mong đợi các CDN phải cẩn trọng ở điểm này.

Chuyển hướng

Một 301, 302, 307 hoặc 308 nghĩa là “gửi cùng QUERY đến URI mới”. Khác với POST, một QUERY không được viết lại thành GET trên 301 hoặc 302. Một 303 See Other nghĩa là “lấy kết quả bằng một GET trên URI này”.

Header Accept-Query

Accept-Query là một response header mới quảng bá hỗ trợ QUERY và các định dạng truy vấn mà một resource chấp nhận. Nó là một danh sách Structured Field, nên hãy parse nó như vậy:

Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"

Client cũng có thể khám phá hỗ trợ bằng OPTIONS và đọc header Allow, hoặc chỉ cần gửi QUERY và xử lý 405 Method Not Allowed.

Những công cụ nào hỗ trợ QUERY hiện nay?

Mức hỗ trợ không đồng đều, nên hãy kiểm thử stack của chính bạn. Đây là những gì chúng tôi đã xác nhận vào ngày 28 tháng 10 năm 2026:

Công cụ Kết quả
Node.js 24 http server http.METHODS bao gồm QUERY; một server thông thường đã nhận được phương thức và body
Node.js 24 fetch Đã gửi một QUERY kèm body JSON
curl 8.7 curl -X QUERY với -d đã gửi phương thức và body
Python 3.14 http.client Đã gửi một QUERY kèm body
OpenAPI 3.2 Path Item Object có trường query cho các thao tác QUERY
Apidog CLI 2.2.12 Schema endpoint-create chấp nhận "method": "query"

Đây là lệnh curl chúng tôi dùng với một server Node cục bộ:

curl -i -X QUERY http://localhost:3000/products \
  -H "Content-Type: application/json" \
  -d '{"q":"running shoe","limit":2}'

Fetch Standard chỉ cấm body trên GET và HEAD, nên trình duyệt có thể gửi QUERY kèm body. Tuy nhiên, QUERY không phải là phương thức nằm trong danh sách an toàn CORS, nên mọi QUERY cross-origin đều kích hoạt preflight. Server của bạn phải liệt kê QUERY trong Access-Control-Allow-Methods.

Các lỗ hổng nằm ở giữa mạng: reverse proxy, API gateway, WAF và CDN — những thứ allowlist phương thức hoặc không key cache theo body. Hãy kiểm tra từng chặng trước khi phát hành. Bản tin APIs You Won’t Hate lưu ý rằng nhiều web framework đã xử lý QUERY trực tiếp hoặc thông qua định tuyến phương thức tùy chỉnh.

Cách áp dụng QUERY mà không làm hỏng client

Bạn không cần phải loại bỏ các endpoint tìm kiếm POST của mình.

  1. Thêm QUERY song song với route POST. Trỏ cả hai vào cùng một handler. Client mới dùng QUERY; client cũ vẫn tiếp tục hoạt động.
  2. Quảng bá nó. Trả về Accept-Query trên resource và thêm QUERY vào Allow trong các response OPTIONS và 405.
  3. Thực thi Content-Type. Trả về 400 hoặc 415 như RFC khuyến nghị, và 422 cho các truy vấn parse được nhưng không chạy được.
  4. Dự phòng bằng 405 hoặc 501. Client nên thử lại cùng body dưới dạng POST khi một chặng từ chối QUERY.
  5. Sửa CORS. Thêm QUERY vào Access-Control-Allow-Methods cho client trình duyệt.
  6. Quyết định về caching. Chỉ bật shared caching ở nơi cache của bạn key theo body. Nếu không, hãy trả về URI Location và để client GET nó.
  7. Ghi tài liệu cho nó. Trong OpenAPI 3.2, định nghĩa thao tác dưới query: trên path item:
openapi: 3.2.0
paths:
  /products:
    query:
      summary: Search products
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductQuery'
      responses:
        '200':
          description: Matching products

Các bộ lọc ngắn, đơn giản có thể vẫn là query string trên GET. Chính RFC 10008 nói rằng nếu truy vấn của bạn ngắn như vậy, GET có lẽ là lựa chọn tốt hơn.

Để coding agent của bạn kiểm thử một endpoint QUERY với Apidog CLI

Một phương thức mới đồng nghĩa với việc phải kiểm tra luồng thành công, mọi mã lỗi và route dự phòng. Hãy giao việc đó cho Claude Code, Codex hoặc Cursor và để nó điều khiển Apidog CLI.

Cài đặt CLI, đăng nhập, và thêm skill Apidog vào agent của bạn:

npm install -g apidog-cli@latest
apidog login --with-token <YOUR_TOKEN>
npx -y skills add https://apidog.com   # pick your agent when prompted

Sau đó đưa cho agent của bạn một prompt:

In Apidog project <projectId>, add a QUERY /products endpoint that takes a
JSON body {q, limit}. Create test cases that assert 200 with an array for a
valid body, 415 for Content-Type text/plain, and 400 with no Content-Type.
Run them against the staging environment and summarize any failures.

Agent đọc từng schema, xác thực payload của nó và chỉ sau đó mới ghi:

apidog cli-schema get endpoint-create
apidog cli-schema validate endpoint-create --file endpoint.json
apidog endpoint create --project <projectId> --file endpoint.json
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file case.json
apidog test-case create --project <projectId> --file case.json
apidog run --test-case <caseId> --project <projectId> -e <envId> -r cli,json

endpoint.json mà nó ghi sẽ đặt "method": "query", mà schema endpoint-create của CLI liệt kê cùng với get, post và các phương thức WebDAV. Thêm --upload-report để xem lần chạy trong ứng dụng Apidog. Cùng lệnh apidog run với -r junit có thể đưa vào CI; xem cách chạy kiểm thử API trong CI với apidog run và cách dùng Apidog CLI trong Claude Code. Gói Free của Apidog hỗ trợ tối đa 4 người dùng.

FAQ

Phương thức HTTP QUERY có phải là tiêu chuẩn chính thức không? Có. RFC 10008 là một RFC thuộc Standards Track, Proposed Standard, được xuất bản vào tháng 6 năm 2026, và IANA liệt kê QUERY trong HTTP Method Registry là safe và idempotent.

QUERY có phải chỉ là GET kèm body không? Gần đúng, nhưng nó được định nghĩa rõ ràng hơn. RFC 9110 không gán ngữ nghĩa nào cho body của GET, nên các intermediary có thể bỏ qua hoặc từ chối nó. QUERY biến body thành truy vấn, yêu cầu một Content-Type, và đưa body vào cache key.

Khi nào tôi nên dùng QUERY thay vì POST? Dùng QUERY cho bất kỳ tìm kiếm hay bộ lọc chỉ đọc nào quá lớn hoặc quá nhạy cảm để đặt trong URL. Giữ POST cho các request tạo mới hoặc thay đổi thứ gì đó.

Trình duyệt có thể gửi request QUERY không? Có, thông qua fetch với một phương thức tùy chỉnh. Các request QUERY cross-origin luôn cần CORS preflight, nên server của bạn phải cho phép phương thức này.

Các response QUERY có được cache không? Có thể. Cache phải bao gồm phần thân request và metadata của nó trong cache key. Nhiều CDN và proxy chưa làm điều đó, nên hãy kiểm tra của bạn hoặc trả về URI Location mà client có thể GET.

OpenAPI có hỗ trợ QUERY không? OpenAPI 3.2 thêm trường query vào Path Item Object cho các thao tác QUERY, nên bạn có thể ghi tài liệu cho chúng mà không cần extension.

Thực hành thiết kế API trong Apidog

Khám phá cách dễ dàng hơn để xây dựng và sử dụng API