การตอบสนองรหัสสถานะ HTTP ที่เหมาะสมสำหรับคำขอทั่วไปที่ไม่สำเร็จคืออะไร (ไม่ใช่ข้อผิดพลาด)


109

ฉันกำลังสร้าง RESTful API ที่จะประมวลผลการโต้ตอบของผู้ใช้จำนวนมากรวมถึงการสั่งซื้อโดยใช้บัตรเครดิตที่จัดเก็บไว้

ในกรณีที่คำสั่งซื้อสำเร็จฉันจะส่งคืน 200 OK และในกรณีที่คำขอสั่งซื้อผิดรูปแบบหรือไม่ถูกต้องฉันจะส่งคืน 400 คำขอที่ไม่ถูกต้อง แต่ฉันควรส่งคืนอะไรหากเกิดปัญหาระหว่างการดำเนินการตามคำสั่งซื้อจริง

  1. ลูกค้า POSTS สั่งไปยังเซิร์ฟเวอร์สำหรับทรัพยากรผู้ใช้ หากไม่มีผู้ใช้ 404 Not Found จะถูกส่งกลับ
  2. รูปแบบคำสั่งซื้อและข้อมูลได้รับการตรวจสอบแล้ว หากไม่ถูกต้อง 400 คำขอที่ไม่ถูกต้องจะถูกส่งกลับ
  3. คำสั่งซื้อได้รับการดำเนินการ หากคำสั่งซื้อสำเร็จจะมีการส่งคืน 201 ที่สร้างขึ้นสำหรับคำสั่งซื้อ หากพบข้อผิดพลาดที่ไม่คาดคิดข้อผิดพลาด 500 เซิร์ฟเวอร์จะถูกส่งกลับ

ขั้นตอนสุดท้ายคือปัญหา - ฉันจะคืนอะไรได้บ้างหากคำสั่งซื้อไม่สมบูรณ์ด้วยเหตุผลอื่นใด สถานการณ์ที่เป็นไปได้อาจรวมถึง:

  • สินค้าหมด
  • ถึงขีด จำกัด การสั่งซื้อสูงสุดของผู้ใช้แล้ว
  • การทำธุรกรรมบัตรเครดิตล้มเหลว (เงินไม่เพียงพอ ฯลฯ )

ดูเหมือนว่ามันจะไม่เหมาะสมสำหรับ 400 หรือ 500 หากสิ่งใดที่ฉันเห็นว่าเป็น 400 หากไม่มีรหัสที่ดีกว่าคำขอนั้นไม่ถูกต้องตามกฎทางธุรกิจ ดูเหมือนจะไม่ถูกต้อง

แก้ไข: พบการสนทนาที่มีอยู่ในหัวข้อเดียวกันนี้ คำตอบทั้งหมดดูเหมือนจะชี้ไปที่การใช้รหัสสถานะสำหรับการละเมิดประเภทนี้โดยมีการอภิปรายระหว่างการใช้ส่วนขยาย 400, 409 หรือ 422


8
ฉันชอบ '422 เอนทิตีที่ไม่สามารถประมวลผลได้' สำหรับข้อผิดพลาดในการตรวจสอบความถูกต้อง และจะใช้สำหรับตัวอย่างข้างต้นของคุณรวมข้อความในการตอบกลับที่มีปัญหาทางธุรกิจที่แท้จริง "สินค้าหมดแล้ว" และอาจเพิ่ม 'รหัส' ของคุณเองหากลูกค้าจำเป็นต้องทำการตัดสินใจที่แตกต่างกันโดยใช้โปรแกรมตามคำตอบ
house9

ก่อนที่คุณจะเข้าสู่ 422 ให้พิจารณาว่าคุณรองรับความสามารถของ WebDAV หรือไม่
Mbithy Mbithy

คำตอบ:


90

คุณควรใช้ 400 สำหรับกฎทางธุรกิจ อย่าส่งคืน 2xx หากคำสั่งซื้อไม่ได้รับการยอมรับ HTTP เป็นโปรโตคอลของแอปพลิเคชันอย่าลืมสิ่งนั้น หากคุณส่งคืน 2xx ลูกค้าสามารถถือว่าคำสั่งซื้อนั้นได้รับการยอมรับไม่ว่าคุณจะส่งข้อมูลใดในเนื้อหาก็ตาม


จากตำรา RESTful Web Services :

ข้อผิดพลาดทั่วไปอย่างหนึ่งที่บริการบนเว็บบางบริการทำคือการส่งคืนรหัสสถานะที่แสดงถึงความสำเร็จ (รหัสสถานะตั้งแต่ 200 ถึง 206 และจาก 300 ถึง 307) แต่รวมเนื้อหาข้อความที่อธิบายถึงเงื่อนไขข้อผิดพลาด การทำเช่นนี้จะป้องกันไม่ให้ซอฟต์แวร์ที่รับรู้ HTTP ตรวจพบข้อผิดพลาด ตัวอย่างเช่นแคชจะจัดเก็บไว้เป็นการตอบสนองที่ประสบความสำเร็จและให้บริการแก่ลูกค้ารายต่อ ๆ ไปแม้ว่าลูกค้าจะสามารถร้องขอได้สำเร็จก็ตาม

ฉันจะปล่อยให้คุณตัดสินใจระหว่าง 4xx ถึง 5xx แต่คุณควรใช้รหัสสถานะข้อผิดพลาด


1
คุณมีตัวอย่างหรือข้อมูลอ้างอิงสำหรับแนวทางนี้เทียบกับวิธีอื่น ๆ หรือไม่? ทั้งคำตอบของคุณและ Widor นั้นสมเหตุสมผลคำตอบหนึ่งจากมุมมองของ HTTP ในฐานะโปรโตคอลของแอปพลิเคชันและอีกคำตอบหนึ่งเนื่องจากเป็นไปตามวัตถุประสงค์ของการถ่ายโอนอย่างเคร่งครัด ข้อมูลจำเพาะกำหนดให้เป็น "โปรโตคอลระดับแอปพลิเคชัน" ซึ่งคลุมเครือเล็กน้อย ฉันยังได้เห็นทั้งมุมมองและตัวอย่างในเว็บเมื่อค้นคว้าเรื่องนี้
Raelshark

นี่เป็นเรื่องจริง
Young Hyun Yoo

2
คุณหมายถึง 'คุณควรใช้ 4xx สำหรับกฎทางธุรกิจ'?
Yawar

28

คุณควรใช้ 4xx สำหรับข้อผิดพลาดของไคลเอ็นต์หากไคลเอ็นต์สามารถแก้ไขคำขอเพื่อหลีกเลี่ยงข้อผิดพลาดได้ ใช้ 5xx สำหรับข้อผิดพลาดของเซิร์ฟเวอร์ที่ไคลเอนต์ไม่สามารถแก้ไขได้จริงๆ

สินค้าหมดอาจเป็นข้อผิดพลาดของเซิร์ฟเวอร์ ไคลเอนต์ไม่สามารถแก้ไขคำขอในบางกรณีเพื่อหลีกเลี่ยงข้อผิดพลาด คุณสามารถเปลี่ยนไปใช้ผลิตภัณฑ์อื่นได้ แต่นั่นไม่ใช่คำขอใหม่ใช่หรือไม่

ถึงขีด จำกัด คำสั่งซื้อสูงสุดของผู้ใช้แล้วยังเป็นข้อผิดพลาดของเซิร์ฟเวอร์ ไม่มีสิ่งใดที่ไคลเอ็นต์สามารถทำได้เพื่อแก้ไขข้อผิดพลาดนั้น

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


6
หากถึงขีด จำกัด การสั่งซื้อแล้วลูกค้าไม่ควรแจ้งเตือนผู้ใช้และให้พวกเขาเปลี่ยนคำขอให้เหมาะสมหรือไม่? ดูเหมือนว่าจะมีข้อผิดพลาด 4xx เช่นเดียวกันกับสินค้าที่ขายหมด ข้อผิดพลาด 5xx มีไว้สำหรับข้อผิดพลาดที่เกิดจากระบบหมดสภาพไม่ทางใดก็ทางหนึ่งไม่ใช่สำหรับการดำเนินการที่ไม่อนุญาตโดยกฎทางธุรกิจ
carlin.scott

7
ฉันเห็นด้วยกับความคิดเห็นด้านบน ข้อผิดพลาด 5xx เกิดขึ้นเมื่อเซิร์ฟเวอร์มีปัญหา ข้อผิดพลาด 4xx สำหรับกฎทางธุรกิจ
Merc

21

ประเภทข้อผิดพลาด:

4×× Client Error

รหัสข้อผิดพลาด:

422 Unprocessable Entity

เซิร์ฟเวอร์เข้าใจประเภทเนื้อหาของเอนทิตีคำขอ (ดังนั้นรหัสสถานะประเภทสื่อที่ไม่รองรับ 415 จึงไม่เหมาะสม) และไวยากรณ์ของเอนทิตีคำขอถูกต้อง (ดังนั้นรหัสสถานะคำขอไม่ถูกต้อง 400 รายการจึงไม่เหมาะสม) แต่ไม่สามารถประมวลผลที่มีอยู่ได้ คำแนะนำ

ตัวอย่างเช่นเงื่อนไขข้อผิดพลาดนี้อาจเกิดขึ้นหากเนื้อหาคำขอ XML มีรูปแบบที่ถูกต้อง (กล่าวคือถูกต้องตามรูปแบบไวยากรณ์) แต่คำแนะนำ XML ที่ผิดพลาดทางความหมาย

https://httpstatuses.com/422


16

ฉันรู้ว่าคำถามนี้เก่า แต่วันนี้ฉันมาพร้อมกับคำถามเดิม ๆ หากผู้ใช้ของฉันเครดิตหมด REST API ของฉันควรส่งคืนรหัสสถานะใด

ฉันมักจะเอนเอียงไปที่402 Payment Required:

อ้างอิงจากWikipedia :

สงวนไว้สำหรับใช้ในอนาคต ความตั้งใจเดิมคืออาจใช้รหัสนี้เป็นส่วนหนึ่งของรูปแบบเงินสดดิจิทัลหรือรูปแบบการชำระเงินขนาดเล็ก แต่ก็ยังไม่เกิดขึ้นและโดยปกติจะไม่ใช้รหัสนี้ Google Developers API จะใช้สถานะนี้หากนักพัฒนาบางรายส่งคำขอเกินขีด จำกัด รายวัน

และแน่นอนพวกเขาทำ :

PAYMENT_REQUIRED (402)

  • ถึงขีด จำกัด งบประมาณรายวันที่กำหนดโดยนักพัฒนาแล้ว
  • การดำเนินการที่ร้องขอต้องใช้ทรัพยากรมากกว่าที่โควต้าอนุญาต ต้องชำระเงินเพื่อดำเนินการให้เสร็จสิ้น
  • การดำเนินการที่ร้องขอต้องการการชำระเงินบางประเภทจากผู้ใช้ที่ตรวจสอบสิทธิ์

นี่เป็นคำตอบที่คิดได้ดีและมีเหตุผลที่สุด
GTodorov

5

แล้วไง424 Failed Dependency? ข้อมูลจำเพาะอธิบายว่า:

ไม่สามารถดำเนินการเมธอดบนทรัพยากรได้เนื่องจากการดำเนินการที่ร้องขอขึ้นอยู่กับการดำเนินการอื่นและการดำเนินการนั้นล้มเหลว

แต่ยังมีคำจำกัดความนี้ :

รหัสสถานะ 424 ถูกกำหนดไว้ในมาตรฐาน WebDAV และมีไว้สำหรับกรณีที่ลูกค้าต้องการเปลี่ยนแปลงสิ่งที่กำลังทำอยู่ - เซิร์ฟเวอร์ไม่พบปัญหาใด ๆ ที่นี่

คุณสามารถบอกลูกค้า (หรือแสร้งทำเป็น) ว่าคุณมีการดำเนินการภายในซึ่งควรจะสร้างคำสั่งซื้อและหักยอดคงเหลือและการดำเนินการอย่างใดอย่างหนึ่งนั้นล้มเหลวแม้ว่าจะมีเหตุผลที่ถูกต้องสมบูรณ์ก็ตามและนั่นคือสาเหตุที่คำขอล้มเหลว

เท่าที่ฉันเห็น "การกระทำ" เป็นคำที่ค่อนข้างกว้างและสามารถใช้ได้ในหลายสถานการณ์รวมถึงสต็อกไม่เพียงพอเครดิตไม่เพียงพอหรืองานปาร์ตี้ในโกดัง


อาจเป็นอีกทางเลือกหนึ่ง 422 Unprocessable Entity :

เซิร์ฟเวอร์เข้าใจประเภทเนื้อหาของเอนทิตีคำขอ (ดังนั้นรหัสสถานะประเภทสื่อที่ไม่รองรับ 415 จึงไม่เหมาะสม) และไวยากรณ์ของเอนทิตีคำขอถูกต้อง (ดังนั้นรหัสสถานะคำขอไม่ถูกต้อง 400 รายการจึงไม่เหมาะสม) แต่ไม่สามารถประมวลผลที่มีอยู่ได้ คำแนะนำ

ตัวอย่างเช่นเงื่อนไขข้อผิดพลาดนี้อาจเกิดขึ้นหากเนื้อหาคำขอ XML มีรูปแบบที่ถูกต้อง (กล่าวคือถูกต้องตามรูปแบบไวยากรณ์) แต่คำแนะนำ XML ที่ผิดพลาดทางความหมาย

การพยายามขอสินค้าที่หมดสต็อกหรือเมื่อคุณมีเครดิตไม่เพียงพออาจถือเป็นความผิดพลาดในระดับความหมาย

MozDev กล่าวว่าสิ่งนี้บ่งบอกถึงความผิดพลาดในฝั่งไคลเอ็นต์โดยเฉพาะ:ไคลเอนต์ไม่ควรทำซ้ำคำขอนี้โดยไม่มีการแก้ไข

Loopback 4 ใช้ 422 เมื่อการตรวจสอบอินพุตล้มเหลว


อาจถือว่าสต็อกไม่เพียงพอหรืองานปาร์ตี้ในโกดังอาจเป็นสถานะชั่วคราวได้ดังนั้นจึงสามารถลองขอใหม่อีกครั้งในภายหลัง สถานการณ์นั้นสามารถระบุได้โดย503 Service Unavailable

ขณะนี้เซิร์ฟเวอร์ไม่สามารถจัดการกับคำขอได้เนื่องจากมีการโอเวอร์โหลดชั่วคราวหรือการบำรุงรักษาตามกำหนดเวลาซึ่งอาจจะบรรเทาลงหลังจากเกิดความล่าช้า

เซิร์ฟเวอร์อาจส่งฟิลด์ส่วนหัว Retry-After เพื่อแนะนำระยะเวลาที่เหมาะสมให้ไคลเอ็นต์รอก่อนที่จะลองคำขออีกครั้ง


ไม่มีสิ่งใดที่เกี่ยวข้องกับการชำระเงิน ฉันจะใช้ 402 จากคำตอบก่อนหน้านี้!
GTodorov

2

ฉันไม่คิดว่า 400 สามารถใช้ได้กับทุกสถานการณ์ทางธุรกิจ สามารถใช้สำหรับการตรวจสอบอินพุตข้อมูลพื้นฐาน นอกเหนือจากนั้นเราอาจยากที่จะปรับตรรกะทางธุรกิจอื่น ๆ ในรหัสข้อผิดพลาดนี้ ข้อผิดพลาดที่จัดการโดยส่วนใหญ่เป็นข้อผิดพลาดเวลาออกแบบซึ่งนักพัฒนาอาจพบในระหว่างการเข้ารหัสไคลเอ็นต์

สมมติว่าพารามิเตอร์ทั้งหมดถูกต้องและสมมติว่าเรากำลังส่งหมายเลขบัญชีผู้ใช้ไปยังคำขอ

ดังนั้นตอนนี้คำขอจึงไม่ใช่คำขอที่ไม่ถูกต้องอีกต่อไปเซิร์ฟเวอร์สามารถยอมรับคำขอได้ แต่ตอนนี้ปฏิเสธที่จะดำเนินการตามคำขอโดยอิงจากข้อมูลใหม่ที่มีอยู่ซึ่งก็คือ - บัญชีมียอดเงินไม่เพียงพอ

ฉันขอแนะนำให้เราใช้ 403 กับข้อความแสดงข้อผิดพลาดที่เหมาะสมในสถานการณ์เหล่านั้น

รหัสข้อผิดพลาดอื่น ๆ ที่เป็นไปได้อาจเป็นข้อขัดแย้ง 409 แต่จะใช้ในสถานการณ์ที่ทรัพยากรอยู่ในสถานะที่สอดคล้องกัน


0

ฉันไปกับ Not Acceptable406

นี่คือรายการ 4xx:

const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
const HTTP_MISDIRECTED_REQUEST = 421;                                         // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
const HTTP_LOCKED = 423;                                                      // RFC4918
const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585

8
แม้ว่าชื่อของรหัสสถานะ 406 อาจฟังดูถูกต้อง แต่คุณต้องทราบว่ารหัสสถานะแต่ละรหัสมีคำอธิบายที่เป็นข้อความที่เชื่อถือได้ คำอธิบายสำหรับรหัสสถานะ 406 ไม่เหมาะสำหรับกรณีที่อยู่ในมือ ดูhttpstatuses.com/406เช่น
Zero3

1
@ Zero3 ถูกต้องรหัสนี้หมายความว่าประเภทการตอบกลับไม่สามารถยอมรับได้เนื่องจากมีความไม่ตรงกันระหว่างส่วนหัวที่ยอมรับที่ส่งจากไคลเอนต์และ MediaType ที่ส่งโดยปลายทางเช่น application / json กับ text / plain
Gregor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.