ข้าม​ไป​ยัง​เนื้อหา

เปิด problemdetails แล้ว​ได้​อะไร และ​ไม่​ได้​อะไร

บท​ที่​แล้ว​จบ​ที่​ปัญหา​สอง​ข้อ · body ไม่​บอก​ว่า​ช่อง​ไหน​ผิด และ​คำขอ​ที่​ผิด​กับ​ระบบ​ที่​พัง​จริง​มี​รูป​เดีย​วกันเป๊ะ

สิ่ง​แรก​ที่​คน​ส่วน​ใหญ่​ทำ​ต่อ​จาก​ตรง​นี้ คือ​เปิด​สวิตช์​ที่ Spring Boot เตรียม​ไว้​ให้

มัน​เปลี่ยน body ข้อ​ผิด​พลาด​ทั้ง​ระบบ โดย​ไม่​ต้อง​แก้ตัว​จัดการ​สัก​ตัว

app/src/main/resources/application.properties
spring.mvc.problemdetails.enabled=true

เปิด​แล้ว​ยิง​คำขอ​ที่​ผิด​สาม​ช่อง​เดิม​เข้าไป​ใหม่

ตอบ​กลับ · 400 · application/problem+json
{"detail":"Invalid request content.","instance":"/bookings","status":400,"title":"Bad Request"}

เทียบ​กับ​ของ​เดิมที​ละ​ช่อง

ก่อน​เปิดหลัง​เปิด
รหัส400400
content-typeapplication/jsonapplication/problem+json
ชื่อ​คีย์error path status timestampdetail instance status title
บอก​ไหม​ว่า​ช่อง​ไหน​ผิดไม่ยัง​ไม่

รูป​ที่​เปลี่ยน​ไป​มีชื่อ และ​มี​เอกสาร​มาตรฐาน​รองรับ

Problem DetailsProblem Details (RFC 9457)รูป​มาตรฐาน​ของ body ที่​บอก​ความ​ผิด​พลาด · มี​คีย์ `type` `title` `status` `detail` `instance` และ​เติม​คีย์​ของ​ตัว​เอง​ได้ · เป็น​รูป ไม่ใช่​เนื้อหา คือ​รูป​ที่ RFC 9457 กำหนด​ไว้​สำหรับ body ที่​บอก​ความ​ผิด​พลาด · มัน​บอก​ว่า​คีย์​ไหน​แปล​ว่า​อะไร และ​เปิด​ให้​เติม​คีย์​ของ​ตัว​เอง​เข้าไป​ได้

content-type ที่​เปลี่ยน​เป็น application/problem+json ไม่ใช่​เรื่อง​เล็ก · มัน​บอก​ตัว​เรียก​ฝั่ง​ผู้​เรียก​ว่า body ก้อน​นี้​อ่าน​ตาม​มาตรฐาน​ได้ ไม่​ต้อง​เดา​รูป​เอง

📄 มาตรฐาน​มี​ห้า​คีย์ แต่​ที่​ออก​มา​มี​สี่

RFC 9457 ระบุ​คีย์ type title status detail instance · ที่​วัด​ได้​มี​สี่​คีย์ เพราะ type มี​ค่า​ตั้ง​ต้น​เป็น about:blank และ Spring ไม่​ส่ง​คีย์ ที่​ยัง​เป็น​ค่า​ตั้ง​ต้น​ออก​มา

สิ่ง​ที่​ไม่​ปรากฏ​ใน body ไม่​ได้​แปล​ว่า​ไม่มี​อยู่​ใน​มาตรฐาน · แต่​ผู้​เรียก​ที่​อ่าน body อย่าง​เดียว​ก็​ไม่มี​ทาง​รู้​ข้อ​นี้ ซึ่ง​เป็น​เหตุผล​ที่ content-type สำคัญ

คีย์ detail มี​ค่า​ว่า Invalid request content. ทุก​ครั้ง ไม่​ว่า​จะ​ผิด​กี่​ช่อง

คำขอ​ของ​เรา​ผิด​สาม​ช่อง​พร้อม​กัน และ​ระบบ​ตรวจ​เจอ​ครบ​ทั้ง​สาม​ช่อง · สิ่ง​ที่​ออก​ไป​คือ​ประโยค​เดียว​ที่​ไม่มี​ชื่อ​ช่อง​อยู่​ใน​นั้น​เลย

ลอง​เปลี่ยน​ให้​ผิด​ช่อง​เดียว​แล้ว​ยิง​ใหม่ · detail ยัง​เป็น​ประโยค​เดิม

สวิตช์​นี้​เปลี่ยน​ซอง​จดหมาย ไม่​ได้​เปลี่ยน​ข้อความ​ข้าง​ใน · ผู้​เรียก​ยัง​ทำ​อะไร​ต่อ​ไม่​ได้ เท่า​เดิม​กับ​ตอน​ก่อน​เปิด

ข้อ​ที่​หนัก​กว่า​นั้น — มัน​ไม่​ได้​ครอบ​ทุก​อย่าง

หัวข้อ​ที่​มีชื่อ​ว่า “ข้อ​ที่​หนัก​กว่า​นั้น — มัน​ไม่​ได้​ครอบ​ทุก​อย่าง”

ยิง​คำขอ​ที่​จอง​ทับ​เวลา​กับ​ใบ​ที่​มี​อยู่​แล้ว แล้ว​ดู​ว่า​อะไร​ออก​มา

คอร์ส​ก่อน​พิสูจน์​ไว้​แล้ว​ว่า​ฐาน​ข้อมูล​กัน​จอง​ซ้อน​ได้​จริง · ยิง​ใบ​แรก​ผ่าน แล้ว​ยิง​ใบ​ที่​สอง ที่​เวลา​ทับ​กัน

ตอบ​กลับ​ของ​ใบ​ที่​สอง · 500 · application/json
{"error":"Internal Server Error","path":"/bookings","status":500,"timestamp":"..."}

สี่​คีย์​แบบ​เดิม · application/json แบบ​เดิม · เหมือน​กับ​ตอน​ที่​ยัง​ไม่​ได้​เปิด​สวิตช์​เลย

เหตุผล​อยู่​ที่​ขอบเขต​ของ​สวิตช์​เอง · มัน​เปลี่ยน​รูป​ให้​เฉพาะ exception ที่ Spring MVC รู้จัก​และ​จัดการ​เอง​อยู่​แล้ว เช่น​ตัว​ที่​เกิด​จาก @Valid

ความ​ล้ม​เหลว​ใบ​ที่​สอง​ไม่ใช่​ตัว​นั้น · มัน​มา​จาก​ฐาน​ข้อมูล และ​ตก​ไป​ที่​ตัว​จัดการ​ค่า​ตั้ง​ต้น ซึ่ง​ไม่รู้​จัก​รูป​ใหม่

⚠️ ระบบ​เดียว​ที่​ตอบ​สอง​รูป​แบบ อ่าน​ยาก​กว่า​ระบบ​ที่​ตอบ​รูป​เดียว

หลัง​เปิด​สวิตช์ ระบบ​ของ​เรา​ตอบ application/problem+json บ้าง application/json บ้าง ขึ้น​อยู่​กับ​ว่า​อะไร​พัง

ผู้​เรียก​ที่​เขียน​ตัว​อ่าน​ตาม​รูป​ใหม่​จะ​เจอ body ที่​ไม่มี​คีย์​ที่​มัน​รอ​อยู่ · การ​แก้​ครึ่ง​เดียว สร้าง​ขอบ​ที่​คาด​เดา​ยาก​กว่า​เดิม และ​นี่​คือ​เหตุผล​ที่​บท​ที่ 3 กับ 4 ต้อง​มี

สาม​ข้อ · หนึ่ง​ข้อดี​ขึ้น หนึ่ง​ข้อ​เท่า​เดิม หนึ่ง​ข้อ​ไม่​ถูก​แตะ​เลย

  • content-type เปลี่ยน​จริง เป็น application/problem+json และ​ชื่อ​คีย์​เปลี่ยน​ทั้ง​ชุด
  • ข้อความ​ยัง​ไม่​บอก​ว่า​ช่อง​ไหน​ผิด detail เป็น​ประโยค​เดียวกัน​ทุก​ครั้ง
  • ความ​ขัด​แย้ง​ของ​ข้อมูล​ยัง​เป็น 500 พร้อม​สี่​คีย์​แบบ​เดิม เพราะ​อยู่​นอก​ขอบเขต​ของ​สวิตช์

ProblemDetailProblemDetailชนิด​ใน Spring ที่​แทน​รูป​ข้าง​บน · คืน​มัน​จาก​ตัว​จัดการ​แล้ว Spring ตั้ง​รหัส​ตอบ​กลับ​ตาม `status` ของ​มัน และ​ตั้ง content-type เป็น `application/problem+json` ให้​เอง คือ​ชนิด​ที่​เรา​จะ​ใช้​เขียน​คำ​ตอบ​เอง​ใน​บท​ถัด​ไป · สวิตช์​เปิด​รูป​ให้​แล้ว แต่​เนื้อหา​ต้อง​มี​คน​ใส่

บท​ที่ 3 จะ​เขียน​ตัว​จัดการ​ตัว​แรก แล้ว​เจอ​เรื่อง​ที่​ไม่มี​ใคร​เตือน​เลย

🔬 ตัวเลข​ทุก​ตัว​ใน​บท​นี้​มา​จาก​ไหน
  • ทรง​เดียว​กับ​บท​ที่ 1 ทุก​อย่าง ต่าง​กัน​ที่​บรรทัด​เดียว​ใน application.properties · ทรง​ที่​ใช้​วัด​เป็น​ส่วน​หนึ่ง​ของ​ข้อ​อ้าง เปลี่ยน​อย่าง​อื่น​ด้วย​แล้ว​เทียบ​กัน​ไม่​ได้
  • Spring Boot 4.1.1 · Kotlin 2.4.10 · JDK 25 · PostgreSQL 18
  • รัน​ซ้ำ​เอง​ได้​ด้วย npm run verify:clinic-http
  • RFC 9457 — Problem Details for HTTP APIs (เข้า​ถึง 2026-09-02) — ชื่อ​คีย์​ทั้ง​ห้า​และ​ค่า​ตั้ง​ต้น​ของ type
  • Spring Framework — Error Responses (เข้า​ถึง 2026-09-02) — ขอบเขต​ของ spring.mvc.problemdetails.enabled

เช็กความเข้าใจ — บทที่ 2

ข้อ 1 / 3

เปิด spring.mvc.problemdetails.enabled แล้ว อะไรเปลี่ยนจริง