ฉันควรส่งคืนสถานะ HTTP 400 (คำขอไม่ถูกต้อง) หากพารามิเตอร์ถูกต้องทางไวยากรณ์ แต่ละเมิดกฎทางธุรกิจหรือไม่


56

บอกว่าฉันมีปลายทาง REST ที่ใช้จำนวนเต็มเป็นพารามิเตอร์:

/makeWaffles?numberOfWaffles=3

ในกรณีนี้ฉันต้องการให้ตัวเลขเป็นบวกเพราะฉันไม่สามารถลบจำนวนวาฟเฟิลได้ (และการขอ 0 วาฟเฟิลเป็นการเสียเวลา) ดังนั้นฉันต้องการปฏิเสธคำขอใด ๆ ที่ไม่มีจำนวนเต็มบวก ฉันต้องการปฏิเสธคำขอที่มีจำนวนเต็มที่เกินจำนวนสูงสุด (สมมติว่าเป็น MAX_INTEGER)

ในกรณีที่มีคนขอวาฟเฟิลในจำนวนที่ไม่เป็นบวกฉันควรส่งคืนสถานะ HTTP 400 (คำขอไม่ถูกต้อง) หรือไม่ ความคิดเริ่มต้นของฉันคือใช่: ไม่ใช่หมายเลขที่ถูกต้องสำหรับฉันที่จะทำตามคำขอ อย่างไรก็ตามRFCไม่ได้กล่าวถึงกฎเกณฑ์ทางธุรกิจว่าเป็นเหตุผลในการ:

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

กฎทางธุรกิจไม่ได้อยู่ภายใต้ตัวอย่างใด ๆ มันถูกต้องทางไวยากรณ์มีการวางกรอบอย่างเหมาะสมและไม่ได้กำหนดเส้นทางคำขอที่หลอกลวง

ดังนั้นฉันควรคืนสถานะ HTTP 400 (คำขอไม่ถูกต้อง) หากพารามิเตอร์ถูกต้องทางไวยากรณ์ แต่ละเมิดกฎทางธุรกิจหรือไม่ หรือมีสถานะที่เหมาะสมกว่าที่จะกลับมา?


1
ที่เกี่ยวข้อง: stackoverflow.com/questions/16133923/…
Kevin Krumwiede

คำตอบ:


38

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

RFC 2616 (มิถุนายน 2542)

10.4.1 400 คำขอไม่ถูกต้อง

เซิร์ฟเวอร์ไม่สามารถเข้าใจคำขอได้เนื่องจากไวยากรณ์ผิดรูปแบบ ลูกค้าไม่ควรทำซ้ำการร้องขอโดยไม่มีการดัดแปลง

ในฐานะของ RFC นี้รหัสสถานะนี้ใช้เฉพาะกับคำขอที่ไม่ถูกต้องทางวากยสัมพันธ์ มีช่องว่างในรหัสสถานะสำหรับการตรวจสอบความหมาย ดังนั้นเมื่อ RFC 4918 มารอบตัวรหัสใหม่ก็เกิดขึ้น

RFC 4918 (มิถุนายน 2550)

11.2 422 เอนทิตีที่ไม่สามารถประมวลผลได้

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

422 เอนทิตีที่ไม่สามารถประมวลผลได้ถูกสร้างขึ้นเพื่อเติมเต็มช่องว่างของการตรวจสอบความหมายในสเปคดั้งเดิมของรหัสสถานะ 4xx อย่างไรก็ตามอีก RFC ที่เกี่ยวข้องมาเกี่ยวกับในปี 2014 ซึ่งทั่วไป 400 ที่จะไม่เป็นที่เฉพาะเจาะจงเพื่อไวยากรณ์

RFC 7231 (มิถุนายน 2014 ล้าสมัยอย่างชัดเจน RFC 2616)

6.5.1 400 คำขอไม่ถูกต้อง

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

โปรดทราบว่าคำอธิบาย 422 บอกว่าสาเหตุที่ 400 ไม่เหมาะสมนั้นเป็นเพราะ 400 (ตั้งแต่ RFC 2616) ควรส่งคืนสำหรับไวยากรณ์คำขอที่ไม่ดีเท่านั้น แต่เป็นของ RFC 7231, นิยามไวยากรณ์ผิดพลาดที่เข้มงวดไม่นำไปใช้กับ 400

กลับไปที่คำถามในมือ: ในขณะที่ 422 มีเทคนิคเฉพาะเจาะจงมากขึ้นตามบริบทนี้ฉันสามารถเห็นทั้ง 400 หรือ 422 ถูกใช้สำหรับการตรวจสอบความหมายของพารามิเตอร์ API ฉันลังเลที่จะใช้ 422 ใน API ของตัวเองเพราะคำจำกัดความของ 422 นั้นล้าสมัยทางเทคนิค ณ จุดนี้ (แม้ว่าฉันจะไม่รู้ว่ามันได้รับการยอมรับอย่างเป็นทางการหรือไม่ก็ตาม) บทความที่อ้างถึงในคำตอบของ Fran ที่ส่งเสริมการใช้งาน 422 นั้นถูกเขียนขึ้นในปี 2012 สองปีก่อน RFC 7231 ได้ชี้แจง HTTP 400 เพียงแค่ให้แน่ใจว่าได้สร้างมาตรฐานให้กับหนึ่งหรืออื่น ๆ


42

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

จาก IETF

422 เอนทิตีที่ไม่สามารถประมวลผลได้ (WebDAV; RFC 4918) คำขอนั้นมีรูปแบบที่ดี แต่ไม่สามารถติดตามได้เนื่องจากข้อผิดพลาดทางความหมาย

ดูเหมือนว่าจะเป็นการตอบสนองที่เหมาะสมกว่าเนื่องจากคำขอของคุณมีรูปแบบที่ดี แต่ไม่ผ่านกฎการตรวจสอบของคุณ


5
ฉันเคยได้ยินมันอธิบายว่า "400 หมายถึงไวยากรณ์ไม่ดี 422 หมายถึงความหมายที่ไม่ดี"
cbojar

33
รหัส x00 ทั้งหมดเป็นรหัส "จับทั้งหมด" 400 ไม่ได้เป็นที่ไม่เหมาะสมเพียงน้อยที่เฉพาะเจาะจง
แจ็ค

1
คำตอบที่ดี แต่ansewer ที่ @GoFreeมอบให้ฉัน
Ewerton

2
มีกรณีที่แข็งแกร่งมากสำหรับการส่งคืนรหัสที่ทุกคนรู้ ทุกคนจะต้องค้นหาอย่างแน่นอน 422 และฉันจะเดิมพันที่ส่วนใหญ่ยังไม่ทราบว่าจะทำอย่างไร
sylvanaar

8

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

ข้อยกเว้นสำหรับเรื่องนี้คือถ้ากฎธุรกิจเกี่ยวข้องกับความปลอดภัย ( 401 Unauthorizedหรือมากกว่านั้น403 Forbiddenก็จะดีกว่า) อีกทางเลือกหนึ่งถ้าส่ง 400 จะรั่วข้อมูลเกี่ยวกับสิ่งที่มีอยู่แล้ว a 404 Not Foundอาจเหมาะสมกว่า


8

ไม่คุณไม่ควร รหัส HTTP มีไว้สำหรับเลเยอร์ HTTP ของแอปพลิเคชันของคุณ กฎทางธุรกิจเป็นเลเยอร์ที่แตกต่างกันอย่างสิ้นเชิงและเป็นแอปพลิเคชันที่เฉพาะเจาะจงดังนั้นคุณต้องมี "โปรโตคอล" ของคุณเอง

ลองจินตนาการถึงวิบัติที่เกิดขึ้นและคุณจะต้องเปลี่ยนจากโปรโตคอล HTTP เป็น Pigeons นกพิราบไม่มีรหัสส่งคืนดังนั้นคุณจะต้องเปลี่ยนชั้นธุรกิจของคุณเพื่อรองรับ แต่ธุรกิจของคุณไม่ได้เปลี่ยนไปในทางใดทางหนึ่งดังนั้นคุณไม่จำเป็นต้องเปลี่ยนเลเยอร์ธุรกิจ มันแสดงให้เห็นถึงการมีเพศสัมพันธ์ที่แน่นหนาระหว่างสองชั้น (การขนส่งและธุรกิจ)

กลับไปที่คำถาม: สิ่งที่คุณควรทำคือส่งคืน "200 OK" โดยมีเนื้อหาอธิบายสิ่งที่เกิดขึ้นกับคำขอ สเปคบอกอย่างชัดเจนว่า:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1

200 ตกลง

คำขอสำเร็จแล้ว ข้อมูลกลับมาพร้อมกับการตอบสนองจะขึ้นอยู่กับวิธีการที่ใช้ในคำขอเช่น

โพสต์เอนทิตีที่อธิบายหรือบรรจุผลลัพธ์ของการกระทำ

คำขอ HTTP ของคุณสำเร็จหรือไม่ ใช่มีเว็บเซิร์ฟเวอร์รู้ว่าจะทำอย่างไรกับคำขอนั้น (เช่นส่งต่อไปยังส่วนเซิร์ฟเวอร์ของแอปพลิเคชันของคุณ) จากนั้นเว็บเซิร์ฟเวอร์จะส่งคำขอนี้ไปยังส่วนเซิร์ฟเวอร์ของแอปพลิเคชันของคุณซึ่งใช้ข้อมูล POSTed ประมวลผล (ตรวจสอบความถูกต้องในกรณีของคุณ) และส่งคืนคำตอบปกติ (ในส่วนของการตอบกลับ HTTP) ไปยังส่วนลูกค้าของแอปพลิเคชัน . คำตอบจากส่วนเซิร์ฟเวอร์ของแอปพลิเคชันอาจเป็น "ยอดเยี่ยมข้อมูลที่คุณส่งมาให้ฉันนั้นถูกต้อง" หรือ "ฉันขอโทษข้อมูลที่คุณส่งไม่ถูกต้อง" และขึ้นอยู่กับส่วนของลูกค้าของคุณที่จะเข้าใจความหมายของคำตอบ

PS: "400 คำขอไม่ถูกต้อง" หมายความว่าเว็บเซิร์ฟเวอร์ไม่เข้าใจสิ่งที่คุณต้องการ หมายความว่าส่วนเซิร์ฟเวอร์ของแอปพลิเคชันของคุณไม่ได้รับการร้องขอ หรืออย่างน้อยนั่นคือความหมาย :-)

แก้ไข : ฉันเพิ่งรู้ว่าคุณกำลังรับคำขอไม่ใช่ POST นี่เป็นความคิดที่ไม่ดีเพราะ GET ไม่ควรเปลี่ยนสถานะของแอปพลิเคชัน GET ควรจะดึงข้อมูลจากเซิร์ฟเวอร์ แต่ในคำขอของคุณคุณกำลังเปลี่ยนสถานะของแอปพลิเคชันจริง ๆ ดังนั้นคุณควรใช้ POST


1
ใช่คืน 404 ในกรณีนั้นเป็นเรื่องปกติ ฉันไม่ได้บอกว่าเซิร์ฟเวอร์ควรส่ง 200 OK พร้อมคำอธิบายในเนื้อหาเสมอ
GoFree

คำอธิบายที่ดีกว่าที่ฉันเคยเห็น ฉันมีคำถามเดียวกันนี้และดูเหมือนว่าทุกคำคิดแตกต่างจากฉันและคุณ @GoFree
Ewerton

@GoFree นี่เป็นคำตอบที่ดีมากสำหรับการคิดใหม่เกี่ยวกับการออกแบบ API แต่มันไม่ใช่กรณีที่เราใช้ HTTP และรหัสการตอบสนองของมันเป็นส่วนสำคัญของเลเยอร์กฎทางธุรกิจเมื่อเราใช้ REST API
Thomas Lauria

1
@Thomas Lauria ฉันยังไม่เห็นการใช้งาน RESTFUL API ที่เหมาะสม อย่างไรก็ตาม REST API เป็นคำศัพท์ในปัจจุบันดังนั้นทุก บริษัท ต้องใช้มัน (คำว่าไม่ใช่เทคโนโลยี) โดยไม่เข้าใจแนวคิดที่อยู่เบื้องหลัง ดังนั้นใช่มันถูกใช้ในทางที่ผิดทุกที่ สิ่งที่โปรแกรมเมอร์สร้างมักจะไม่ใช่ REST API แต่เป็น HTTP API หรือ API OVER HTTP จริงหนึ่งในไม่กี่คนการใช้งานที่พักผ่อนที่ดีคือ HTTP เอง :)
GoFree

1
การใช้ 200-OK นั้นมีเหตุผลเป็นพิเศษหากแอปพลิเคชันมีฟิลด์ "ข้อผิดพลาด" ในเนื้อความการตอบสนองเพื่ออธิบายข้อผิดพลาดระดับธุรกิจเช่นค่าอินพุตสูงเกินไปหรือต่ำเกินไปหรือขาดหายไปสินค้าหมด ฯลฯ
Roland

-3

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


5
409 หมายถึง "สถานะที่คุณพยายามใส่นี้ขัดแย้งกับสถานะที่ไคลเอ็นต์อื่นพยายามใส่ไว้ในนี้" เป็นการบล็อกการเขียนพร้อมกัน (โดยใช้ ETags เป็นต้น)
แจ็ค
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.