HTTP QUERY method ใหม่ใน RFC 10008 ปิดช่องว่างระหว่าง GET กับ POST ที่ค้างมา 30 ปี
HTTP QUERY คือ method ใหม่ที่เพิ่งเป็นมาตรฐานใน RFC 10008 เมื่อ June 2026 · ใช้ส่ง query ยาว ๆ ไว้ใน body ได้เหมือน POST แต่ยัง cache และ retry ได้ปลอดภัยเหมือน GET จึงช่วยแก้ปัญหาที่นักพัฒนาเว็บเจอมานานว่าจะวาง query ก้อนใหญ่ไว้ตรงไหนดี

ทุกครั้งที่หน้าเว็บคุยกับ server มันต้องเลือกวิธีส่งคำขอ หรือที่เรียกว่า HTTP method · สองตัวที่ใช้กันบ่อยที่สุดคือ GET (วิธี "ขอดูข้อมูล") กับ POST (วิธี "ส่งข้อมูลไปทำอะไรสักอย่าง") ปัญหาจะโผล่ทันทีเมื่อต้องยิง query ก้อนใหญ่ไปค้นหา · เช่น GraphQL ซึ่งเป็นภาษา query สำหรับขอข้อมูลจาก API ที่เขียนยาวเป็นสามสิบบรรทัด หรือเงื่อนไขค้นหาซ้อนกันหลายชั้น เพราะถ้าเลือก GET ก็ต้องเอา query ไปต่อท้าย URL ซึ่งพอยาวเกินก็โดนตัด · หลุดไปโผล่ใน log แบบเปิดเผย · แถมแคชแตกเป็นคนละหน้ากันเพราะ URL ไม่ซ้ำ แต่ถ้าเลือก POST ก็แนบ query ใน body ได้สบาย กลับโดนระบบมองว่ามันเป็น "การกระทำที่เปลี่ยนข้อมูล" จึงไม่กล้าแคชและไม่กล้า retry ให้
นักพัฒนาเว็บเจอช่องว่างตรงนี้มานานเป็นสิบปี และตอนนี้ก็มีคำตอบที่เป็นมาตรฐานแล้ว · HTTP QUERY · method ตัวใหม่ที่ IETF เพิ่งรับรองใน RFC 10008 เมื่อ June 2026 หัวใจของมันคือการเอาข้อดีของทั้งสองฝั่งมารวมกัน · ส่ง query ไว้ใน request body ได้เหมือน POST แต่ยังคงเป็น safe และ idempotent เหมือน GET ระบบกลางระหว่างทางจึงแคชและ retry ให้ได้อย่างมั่นใจ
ทำไม GET กับ POST ถึงไม่พอ
ปัญหาไม่ได้อยู่ที่ GET หรือ POST ทำงานพลาด แต่อยู่ที่ทั้งคู่ถูกออกแบบมาเพื่องานคนละแบบ และไม่มีตัวไหนอยู่ตรงกลางพอดี
spec นิยาม GET ว่าเป็น safe · คือมันแค่ "ขอดู" ไม่เปลี่ยนแปลงอะไรบน server และเป็น idempotent · คือยิงซ้ำกี่ครั้งผลก็เหมือนเดิม คุณสมบัติสองข้อนี้คือเหตุผลที่ระบบกลางอย่าง CDN หรือ proxy กล้าแคชผลของ GET ไว้ และกล้า retry ให้อัตโนมัติเวลาเน็ตสะดุด แต่ปัญหาคือ GET ไม่มีพื้นที่มาตรฐานสำหรับ body · ตัว spec บอกตรง ๆ ว่าไม่ได้กำหนดความหมายของ body ใน GET ไว้ เลยเหลือทางเดียวคือยัด query ลงไปใน URL ซึ่งพอเป็น query ใหญ่ ๆ ก็เริ่มเจอเพดานความยาว · เริ่มหลุดเข้า log · เริ่มแคชแตก
POST แก้เรื่อง body ได้ทันที · แนบ query ก้อนใหญ่แค่ไหนก็ได้ แต่ต้องแลกกับข้อเสียว่า POST ไม่ใช่ safe และไม่ใช่ idempotent โดยปริยาย · ในสายตาของระบบ POST แปลว่า "อาจเปลี่ยนข้อมูล" เช่นสร้างออเดอร์ใหม่หรือตัดเงิน เมื่อความหมายเป็นแบบนั้น ระบบกลางจึงไม่กล้าแคชผลและไม่กล้ายิงซ้ำให้ เพราะถ้ายิงซ้ำผิดจังหวะอาจกลายเป็นตัดเงินสองรอบ สรุปคือเราใช้ POST ส่ง query ได้ก็จริง แต่ต้องยอมทิ้งการแคชและการ retry ที่ได้มาฟรี ๆ จาก GET
QUERY อยู่ตรงกลางพอดี

QUERY ออกแบบมาเพื่อช่องว่างนี้โดยเฉพาะ · มันรับ request body ที่ server ตีความได้เหมือน POST แต่ประกาศตัวเองว่าเป็น safe และ idempotent เหมือน GET ความต่างเล็ก ๆ แค่คำประกาศนี้แหละที่เปลี่ยนทุกอย่าง เพราะพอ method บอกว่า "ฉันแค่ค้นหา ไม่เปลี่ยนข้อมูล และยิงซ้ำได้" ระบบกลางก็กลับมาแคชผลและ retry ให้ได้อีกครั้ง · แม้ query จะอยู่ใน body ไม่ใช่ URL
ลองเทียบสามตัวนี้ จะเห็นชัดขึ้นว่าแต่ละตัวเหมาะกับงานแบบไหน
| GET | QUERY | POST | |
|---|---|---|---|
| Safe (แค่ขอดู) | ใช่ | ใช่ | อาจไม่ใช่ |
| Idempotent (ยิงซ้ำผลเดิม) | ใช่ | ใช่ | อาจไม่ใช่ |
| แคชผลได้ | ได้ | ได้ | ได้เฉพาะของ GET/HEAD |
| ส่ง query ใน body | ไม่มีความหมายมาตรฐาน | ใส่ได้ตามคาด | ใส่ได้ตามคาด |
สรุปตารางนี้เป็นประโยคเดียวได้ว่า · ถ้า query สั้นและอยากให้ทุกอย่างง่ายที่สุด ใช้ GET ต่อท้าย URL ก็ยังดีอยู่ · ถ้าเป็นการกระทำที่เปลี่ยนข้อมูลจริง ๆ เช่นสร้างหรือลบ ใช้ POST · แต่ถ้าเป็นการ "ค้นหาด้วย query ก้อนใหญ่" ที่อยากได้ทั้ง body ขนาดเต็มและการแคช นี่คืองานของ QUERY
ส่ง QUERY จริงหน้าตาเป็นยังไง

ขั้นตอนพื้นฐานสั้นกว่าที่คิด ลองดูเป็นลำดับสามขั้น แล้วค่อยลงรายละเอียด
- ฝั่ง client ยิง
QUERYไปที่ URI ปลายทาง โดยใส่ query ไว้ใน request body - ใส่
Content-Typeให้ตรงกับรูปแบบของ query · เช่นapplication/graphqlสำหรับ GraphQL หรือapplication/sqlสำหรับ SQL - ฝั่ง server ประมวลผล query นั้นกับ resource ปลายทาง แล้วตอบ
200 OKกลับมาพร้อมผลลัพธ์
ตัวอย่างที่จับต้องได้ที่สุดคือ GraphQL · เดิมทีหลายระบบยิง GraphQL query ผ่าน POST ทำให้แคชไม่ได้เลย พอย้ายมาใช้ QUERY ก็แค่ส่ง body เป็น application/graphql ไปที่ /api/graphql แล้ว server จะตอบผลลัพธ์กลับมาพร้อม header Content-Location ที่บอก URI ของผลลัพธ์ก้อนนั้น เผื่อ client อยากกลับมาดูผลเดิมซ้ำด้วย GET ธรรมดาในภายหลัง
จุดที่ต้องระวังเป็นพิเศษคือ Content-Type · มันไม่ใช่เรื่องที่ข้ามได้ แต่เป็นข้อบังคับ ถ้า client ส่ง QUERY มาโดยไม่ระบุรูปแบบของ query หรือระบุไม่ตรงกับ body จริง · spec กำหนดให้ server ต้องปฏิเสธ request นั้น เพราะ server ต้องรู้ว่ากำลังอ่าน query ภาษาอะไรอยู่ ถึงจะประมวลผลถูก
มีอีกสอง header ที่ทำให้ชีวิตง่ายขึ้น · ฝั่ง server ตอบ Accept-Query กลับมาได้ เช่น Accept-Query: application/graphql, application/sql เพื่อบอก client ล่วงหน้าว่า endpoint นี้รับ query รูปแบบไหนได้บ้าง · และถ้า server แนบ Location กลับมา client ก็เปลี่ยนไปยิง GET ที่ URI นั้นในครั้งถัดไปได้เลย ไม่ต้องส่ง body ซ้ำ ซึ่งช่วยให้การแคชง่ายขึ้นอีกขั้น
ของจริงวันนี้ยังต้องเผื่อใจ
ตรงนี้คือด้านที่ต้องพูดให้ครบ · QUERY เป็นมาตรฐานที่เพิ่งคลอด การรองรับในโลกจริงจึงยังไม่เต็มร้อย
ข้อแรก · ยังไม่มีเบราว์เซอร์ตัวไหนรองรับ QUERY แบบ native หมายความว่า fetch() ในหน้าเว็บยังยิง method นี้ตรงๆ ไม่ได้ทันที การใช้งานช่วงนี้จึงเหมาะกับฝั่ง server-to-server หรือ backend ที่เราคุมทั้งสองฝั่งเองมากกว่า
ข้อสอง · QUERY ไม่ได้อยู่ในรายชื่อ method ที่ CORS อนุญาตโดยอัตโนมัติ ดังนั้นถ้ายิงข้ามโดเมน เบราว์เซอร์จะต้องส่ง preflight OPTIONS ไปถามก่อนทุกครั้ง · เป็นขั้นตอนที่ต้องเตรียมรับมือเวลาวางสถาปัตยกรรม
ข้อสาม · การแคช QUERY ซับซ้อนกว่าการแคช GET พอสมควร เพราะ cache key ของ GET ใช้แค่ URI ก็พอ แต่ของ QUERY ต้องเอา request body ทั้งก้อนมาคิดรวมใน key ด้วย ระบบแคชจึงต้องฉลาดกว่าเดิม · นี่คือเหตุผลที่ header Location มีประโยชน์ เพราะมันเปิดทางให้ย้ายกลับไปแคชแบบ GET ที่ง่ายกว่าได้เมื่อเหมาะสม
เมื่อรวมทุกข้อแล้ว ภาพที่ได้คือ QUERY ไม่ใช่สิ่งที่จะเปลี่ยนทั้งวงการในชั่วข้ามคืน แต่เป็นมาตรฐานส่วนที่เคยขาดหายไปและตอนนี้มีที่ทางชัดเจนแล้ว สำหรับทีมที่ทำ API ฝั่ง server เอง การเริ่มทดลองตั้งแต่ตอนนี้คือการลงทุนล่วงหน้าก่อนที่ ecosystem จะตามมาเต็มตัว
สิ่งที่น่าคิดที่สุดของ QUERY ไม่ใช่ feature ใหม่ที่เพิ่มเข้ามา แต่เป็นการยอมรับว่า "การค้นหา" สมควรมี method ของตัวเองมาตั้งแต่แรก · เราเคยฝืนใช้เครื่องมือผิดงานมาตลอด เพราะไม่มีเครื่องมือที่ใช่ให้เลือก
ที่มา:
- เอกสาร RFC 10008: HTTP QUERY Method จาก RFC Editor
- บทความ QUERY - Expert Guide to HTTP methods จาก http.dev



