QUERY: Phương Thức HTTP Mới Cách Mạng Hóa Truy Vấn Dữ Liệu Phức Tạp

Bạn đang làm việc với các REST API? Chắc hẳn bạn đã quá quen thuộc với các phương thức như `GET`, `POST`, `PUT`, `DELETE`… Nhưng bạn có biết rằng một phương thức HTTP hoàn toàn mới đã được chuẩn hóa vào tháng 6 năm 2026 không? Đó chính là `QUERY`, và nó hứa hẹn sẽ giải quyết một vấn đề nan giải mà các nhà phát triển đã phải vật lộn suốt 16 năm qua. Đây là phương thức HTTP tiêu chuẩn mới đầu tiên kể từ `PATCH` (2010), đánh dấu một bước tiến đáng kể trong kiến trúc API.


Thách Thức Với Phương Thức GET Hiện Tại

Khi bạn cần truy xuất thông tin từ backend và áp dụng các bộ lọc phức tạp, `GET` là lựa chọn mặc định theo chuẩn REST vì nó được thiết kế để truy xuất tài nguyên. Thông thường, bạn sẽ thêm các tham số vào URL để lọc kết quả:

GET /orders?select=surname,givenname,email&limit=10&match="email=*@example.*"

Tuy nhiên, cách tiếp cận này lại bộc lộ nhiều hạn chế lớn:

  • Giới hạn kích thước URL: Các URL thường có giới hạn kích thước (thường là tối đa 8000 ký tự). Với các truy vấn hoặc bộ lọc phức tạp, URL có thể dễ dàng vượt quá giới hạn này, dẫn đến lỗi hoặc yêu cầu bị cắt xén.
  • Vấn đề bảo mật: Các tham số trong URL hiển thị rõ ràng trong nhật ký máy chủ, nhật ký proxy và lịch sử trình duyệt. Điều này có thể gây ra rủi ro bảo mật nghiêm trọng nếu thông tin nhạy cảm được truyền qua URL.
  • Khó khăn khi tạo truy vấn phức tạp: `GET` không phù hợp để truyền các truy vấn phức tạp như câu lệnh SQL, biểu thức JSONPath hoặc các bộ lọc đa cấp, đa điều kiện. Việc mã hóa các cấu trúc dữ liệu phức tạp vào URL là rất khó khăn và dễ gây lỗi.
  • Mã hóa phức tạp: Việc mã hóa đúng cách các ký tự đặc biệt trong URL để đảm bảo tính toàn vẹn của truy vấn thường rất phức tạp và dễ mắc lỗi.

Những hạn điểm này đã buộc các nhà phát triển phải tìm kiếm những giải pháp thay thế, thường là không lý tưởng.

Tại Sao POST Không Phải Là Giải Pháp Tối Ưu cho Truy Vấn?

Để khắc phục các vấn đề của `GET`, nhiều nhà phát triển đã chuyển sang sử dụng `POST` để truyền dữ liệu truy vấn trong phần thân yêu cầu (request body):

POST /orders HTTP/1.1
Host: api.example.org
Content-Type: application/x-www-form-urlencoded

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

Mặc dù `POST` cho phép truyền dữ liệu lớn và phức tạp trong body, nhưng nó lại phát sinh những vấn đề khác khi được dùng cho mục đích truy vấn:

  • Không bất biến (Non-idempotent): `POST` không phải là bất biến. Điều này có nghĩa là nếu bạn gửi cùng một yêu cầu `POST` nhiều lần, nó có thể tạo ra các kết quả khác nhau (ví dụ: tạo nhiều bản ghi trùng lặp). Nếu mạng gặp sự cố, bạn không thể gửi lại yêu cầu một cách an toàn mà không lo ngại về việc tạo ra tác dụng phụ không mong muốn.
  • Không hỗ trợ bộ nhớ đệm chuẩn HTTP: Các yêu cầu `POST` theo mặc định không được lưu vào bộ nhớ đệm (cache) bởi các proxy, CDN hoặc trình duyệt. Điều này ảnh hưởng tiêu cực đến hiệu suất và khả năng mở rộng của API, buộc phải tạo ra các cơ chế lưu trữ đệm tùy chỉnh.
  • Proxy không biết cách xử lý an toàn: Do tính chất không bất biến, các proxy không thể biết liệu có an toàn để từ chối hoặc thử lại yêu cầu `POST` trong trường hợp lỗi mạng, gây ra sự không chắc chắn trong việc xử lý lỗi.
  • Giải pháp riêng của từng framework: Mỗi framework hoặc thư viện có thể triển khai hệ thống “POST an toàn” riêng, dẫn đến sự thiếu nhất quán và phức tạp trong kiến trúc.

QUERY: Giải Pháp Toàn Diện Cho Truy Vấn Phức Tạp

Phương thức `QUERY` được thiết kế để kết hợp những ưu điểm tốt nhất của `GET` và `POST`, mang lại một giải pháp mạnh mẽ và chuẩn hóa cho các yêu cầu truy vấn phức tạp.

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

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

Dưới đây là những lợi ích vượt trội mà `QUERY` mang lại:

Không Giới Hạn Kích Thước URL

Với `QUERY`, dữ liệu truy vấn được gửi trong phần thân yêu cầu (request body), loại bỏ hoàn toàn các giới hạn về kích thước URL. Điều này cho phép bạn gửi các truy vấn phức tạp không giới hạn độ dài, bao gồm các câu lệnh SQL, biểu thức JSONPath, hoặc các đối tượng lọc đa chiều mà không cần phải lo lắng về việc vượt quá giới hạn ký tự.

Tính Bất Biến (Idempotent)

Một trong những điểm mạnh cốt lõi của `QUERY` là tính bất biến. Một thao tác được gọi là bất biến nếu việc gọi nó nhiều lần sẽ tạo ra cùng một kết quả như gọi một lần.

  • ✅ `GET /users/123` (bất biến) → 1 lần gọi = 10 lần gọi = cùng dữ liệu.
  • ✅ `QUERY /users` (bất biến) → gửi lại yêu cầu = cùng kết quả.
  • ❌ `POST /users` (KHÔNG bất biến) → 1 lần gọi tạo 1 người dùng, 2 lần gọi tạo 2 người dùng.

Điều này cực kỳ quan trọng vì nếu mạng gặp sự cố, bạn có thể an toàn gửi lại yêu cầu `QUERY` mà không lo tạo ra các bản ghi trùng lặp hoặc làm hỏng dữ liệu trên máy chủ.

Khả Năng Lưu Trữ Đệm (Cacheable)

Tương tự như `GET`, các yêu cầu `QUERY` có thể được lưu trữ vào bộ nhớ đệm bởi các proxy, CDN và trình duyệt. Điều này cải thiện đáng kể hiệu suất API, giảm tải cho máy chủ và mang lại trải nghiệm người dùng nhanh hơn, đặc biệt với các truy vấn được thực hiện thường xuyên.

Hỗ Trợ Request Body

`QUERY` cho phép bạn gửi dữ liệu phức tạp trong phần thân yêu cầu, giống như `POST`, thay vì phải nhồi nhét tất cả vào URL. Điều này giúp cấu trúc truy vấn rõ ràng, dễ đọc và dễ quản lý hơn rất nhiều.

An Toàn (Safe)

Phương thức `QUERY` được định nghĩa là an toàn (safe), nghĩa là nó sẽ không bao giờ thay đổi trạng thái của máy chủ. Nó chỉ thực hiện các thao tác đọc dữ liệu, giúp đảm bảo tính toàn vẹn và ổn định của hệ thống.

Có Thể Gửi Lại An Toàn (Safely Replayable)

Với tính chất bất biến và an toàn, yêu cầu `QUERY` có thể được gửi lại một cách tự tin nếu có lỗi mạng hoặc các vấn đề khác mà không sợ gây ra tác dụng phụ không mong muốn.

URI Cho Yêu Cầu (URI for the Request)

`QUERY` cho phép máy chủ tạo ra một URL vĩnh viễn cho chính yêu cầu truy vấn đó, không phải chỉ cho kết quả.

  • Với `POST` truyền thống (URI của kết quả):
    POST /orders → 200 OK
    
    Content-Location: /results/xyz789
            

    Đây là URI của *kết quả* được tạo ra.

  • Với `QUERY` (URI của yêu cầu):
    QUERY /orders → 200 OK
    
    Location: /saved-queries/42
            

    Đây là URI của *yêu cầu* đã được lưu.

Điểm đặc biệt ở đây là khi bạn gửi lại yêu cầu `GET /saved-queries/42`, máy chủ sẽ thực thi lại truy vấn SQL hoặc JSONPath gốc. Điều này có nghĩa là bạn luôn nhận được kết quả *cập nhật* dựa trên dữ liệu mới nhất mà không cần phải gửi lại toàn bộ phần thân yêu cầu ban đầu.

# Sau đó...

GET /saved-queries/42

# → Máy chủ thực thi lại truy vấn SQL gốc
# → Bạn nhận được kết quả mới nhất

Tính năng này cực kỳ hữu ích cho việc:

  • Chia sẻ một truy vấn (gửi liên kết cho đồng nghiệp).
  • Đánh dấu (bookmark) một tìm kiếm.
  • Lưu trữ bộ đệm cho truy vấn (không chỉ kết quả).
  • Tự động thực hiện lại truy vấn định kỳ mà không cần gửi lại toàn bộ phần thân yêu cầu mỗi lần.

Nhờ `QUERY`, cuối cùng chúng ta có bộ nhớ đệm HTTP chức năng cho các yêu cầu phức tạp. Các proxy, CDN và trình duyệt giờ đây có thể lưu trữ bộ đệm cho các yêu cầu có phần thân. Điều này cực kỳ quan trọng đối với hiệu suất.

Tối Ưu Thiết Kế API Với QUERY

`QUERY` không chỉ cải thiện hiệu suất mà còn mang đến một sự tiến hóa trong thiết kế REST API. Thay vì phải tạo ra nhiều endpoint `GET` khác nhau cho các trạng thái hoặc bộ lọc cụ thể:

GET /api/users/active
GET /api/users/inactive
GET /api/users/premium

Giờ đây, bạn có thể đơn giản hóa thành một endpoint duy nhất:

QUERY /api/users

Với một endpoint duy nhất, việc **duy trì**, **bảo mật** và **giám sát** API trở nên dễ dàng và hiệu quả hơn rất nhiều. Điều này giúp giảm thiểu sự phức tạp, tăng cường tính nhất quán và cải thiện tổng thể kiến trúc API của bạn.

Tóm Tắt: GET vs POST vs QUERY

Để có cái nhìn tổng quan, hãy so sánh ba phương thức này:

Tính năng GET POST QUERY
An toàn ✅ Có ❌ Không ✅ Có
Bất biến ✅ Có ❌ Không ✅ Có
Cho phép body ❌ Không ✅ Có ✅ Có
Có thể cache ✅ Có ⚠️ Phức tạp ✅ Có
Có thể gửi lại an toàn ✅ Có ❌ Rủi ro ✅ Có
URI cho yêu cầu ✅ Mặc định ❌ Không ✅ Tùy chọn

Kết Luận: Một Bước Tiến Nhỏ, Tác Động Lớn

Phương thức `QUERY` cuối cùng đã mang đến một giải pháp chuẩn hóa cho việc thực thi các yêu cầu truy vấn dữ liệu phức tạp. Đây là một sự thay đổi “nhỏ” nhưng có tác động “lớn”, giải quyết một vấn đề thực tế mà các nhà phát triển đã phải tìm cách khắc phục trong nhiều năm.

Phương thức này chỉ mới được chuẩn hóa gần đây (tháng 6 năm 2026), theo RFC 10008, vì vậy sẽ mất một thời gian để nó được áp dụng rộng rãi.

⚠️ Tình Trạng Triển Khai

  • Đã chuẩn hóa: RFC 10008 (tháng 6 năm 2026)
  • Triển khai: Rất ít máy chủ/client hỗ trợ tính năng này.
  • 🚀 Thời gian áp dụng dự kiến: Có thể vào năm 2027-2028.

Trước khi sử dụng `QUERY` trong môi trường sản xuất, hãy chờ đợi cho đến khi các triển khai trở nên phổ biến hơn. Hiện tại, điều quan trọng nhất là bạn cần nắm vững khái niệm và ghi nhớ nó cho kiến trúc API trong tương lai của mình.


Bước Tiếp Theo: QUERY Trong Thực Tế

Bài viết này đã cung cấp cái nhìn tổng quan về lý thuyết và các khái niệm chính của `QUERY`. Nhưng làm thế nào để bạn áp dụng nó vào thực tế?

Trong một bài viết sắp tới, chúng tôi sẽ đi sâu vào việc **triển khai thực tế `QUERY` với một REST API**, trình bày cách xây dựng một REST API hỗ trợ phương thức HTTP mới này và cách tích hợp nó vào một kiến trúc thế giới thực.

Hãy theo dõi để không bỏ lỡ những thông tin hữu ích này nhé! 🚀

Chỉ mục