รหัสตอบกลับ REST ที่เหมาะสมสำหรับคำขอที่ถูกต้อง แต่เป็นข้อมูลว่างเปล่าคืออะไร


332

ตัวอย่างเช่นคุณเรียกใช้คำขอ GET users/9แต่ไม่มีผู้ใช้ที่มี ID # 9 รหัสตอบกลับที่ดีที่สุดคืออะไร

  • 200 ตกลง
  • 202 ได้รับการยอมรับ
  • 204 ไม่มีเนื้อหา
  • 400 คำขอไม่ถูกต้อง
  • ไม่พบ 404

19
คำแนะนำ: คุณพบผู้ใช้ 9 หรือไม่
Chris Pfohl

42
คำแนะนำ 2: ดังนั้นผู้ใช้ 9 ไม่พบ ?
Tomasz Nurkiewicz

18
@IMB ใครบอกว่า 204 "ไม่มีเนื้อหา" ระบุว่ามีเอนทิตีที่คุณกำลังค้นหาอยู่ แต่ไม่มีการแสดงตน ตัวอย่างเช่นถ้าบล็อกที่มี id 15 ไม่มีความคิดเห็นและคุณไม่ต้องการส่งคืนรายการว่างสำหรับความคิดเห็นของบล็อกหมายเลข 15: "/ blog / 15 / comments" จะส่งคืน NoContent ในทางตรงกันข้ามถ้ามีบล็อก 15 อยู่ '404 Not Found' จะเหมาะสมกว่า
Chris Pfohl

12
@Crisfole ไม่ได้คุณหมายถึง"ในทางตรงกันข้ามถ้าบล็อก 15 ไม่. ไม่อยู่ '404 ไม่พบ' มีความเหมาะสมมากขึ้น"
gdoron สนับสนุน Monica

15
ฉันทำ @gdoron แน่นอนที่สุด! :) ขอบคุณ น่าเศร้าที่ฉันสายไปประมาณสามปีในการแก้ไขและแก้ไข
Chris Pfohl

คำตอบ:


249

TL; DR: ใช้ 404

ดูบล็อกนี้ มันอธิบายได้ดีมาก

สรุปความคิดเห็นของบล็อกใน204:

  1. 204 No Content ไม่มีประโยชน์อย่างยิ่งในฐานะรหัสการตอบสนองสำหรับเบราว์เซอร์ (แม้ว่าเบราว์เซอร์ตามข้อมูลจำเพาะ HTTP จะต้องเข้าใจว่าเป็นรหัสการตอบสนอง 'อย่าเปลี่ยนมุมมอง')
  2. 204 No Content เป็นแต่มีประโยชน์มากสำหรับการให้บริการเว็บ Ajax ซึ่งอาจต้องการที่จะแสดงให้เห็นความสำเร็จโดยไม่ต้องกลับบางสิ่งบางอย่าง (โดยเฉพาะอย่างยิ่งในกรณีเช่นDELETEหรือPOSTที่ไม่ต้องการความคิดเห็น)

ดังนั้นคำตอบสำหรับคำถามของคุณคือใช้404ในกรณีของคุณ เป็นรหัสที่ตอบสนองความที่คุณไม่ควรมักจะกลับมาที่เบราว์เซอร์ในการตอบสนองต่อ204GET

รหัสตอบกลับอื่น ๆ ที่เหมาะสมน้อยกว่า204และ404:

  1. 200ควรกลับมาพร้อมกับเนื้อหาของสิ่งที่คุณเรียกสำเร็จ ไม่เหมาะสมเมื่อไม่มีเอนทิตีที่คุณดึงข้อมูลอยู่
  2. 202ใช้เมื่อเซิร์ฟเวอร์เริ่มทำงานกับวัตถุ แต่วัตถุยังไม่พร้อม ไม่อย่างแน่นอนกรณีที่นี่ คุณยังไม่ได้เริ่มและจะไม่เริ่มสร้างผู้ใช้ 9 เพื่อตอบสนองต่อGETคำขอ ที่ทำลายกฎทุกประเภท
  3. 400ถูกใช้เพื่อตอบสนองต่อคำขอ HTTP ที่จัดรูปแบบไม่ดี (ตัวอย่างเช่นส่วนหัว http ที่มีรูปแบบไม่ถูกต้องส่วนที่สั่งซื้อไม่ถูกต้อง ฯลฯ ) นี่จะเกือบถูกจัดการโดยกรอบสิ่งที่คุณใช้ คุณไม่ควรจัดการกับเรื่องนี้จนกว่าคุณจะเขียนเซิร์ฟเวอร์ของคุณเองตั้งแต่เริ่มต้น แก้ไข : RFC ที่ใหม่กว่าอนุญาตให้ใช้ 400 สำหรับคำขอที่ไม่ถูกต้องในเชิงความหมาย

คำอธิบายของรหัสสถานะ HTTPของ Wikipedia มีประโยชน์อย่างยิ่ง คุณสามารถดูคำจำกัดความในเอกสาร HTTP / 1.1 RFC2616 ได้ที่ www.w3.org


8
หมายเหตุ: รหัสการตอบสนองในยุค 200 บ่งชี้ความสำเร็จ รหัสการตอบสนองในยุค 400 บ่งบอกถึงความล้มเหลว สรุปจุดหนึ่งและสองเกี่ยวกับ204รหัสการตอบกลับ (ไม่มีเนื้อหา)
Chris Pfohl

227
-1 เนื่องจากฉันไม่เห็นด้วยอย่างยิ่งที่จะคัดค้าน 404 เป็นการตอบสนองต่อการโทรที่ประสบความสำเร็จซึ่งไม่มีบันทึกที่จะส่งคืน ในฐานะนักพัฒนาที่จัดการกับ API สำหรับแอปที่ไม่ใช่เว็บฉันเสียเวลาติดต่อกับนักพัฒนาของ API เพื่อติดตามสาเหตุที่ปลายทาง API ที่ฉันโทรหาไม่มีอยู่จริง ๆ แล้วมันก็ไม่มี ข้อมูลที่จะรายงาน สำหรับ 204 ที่ไม่ได้มีประโยชน์เป็นพิเศษกับเบราว์เซอร์นั่นเป็นเหมือนหางที่กระดิกหางสุนัขเนื่องจากการใช้ปลายทาง API ส่วนใหญ่ในอุปกรณ์สมาร์ทโฟนของเรานั้นไม่ใช่เบราว์เซอร์และใช้ AJAX ขออภัยที่จะนำคะแนนไป
Matt Cashatt

38
@MatthewPatrickCashatt คุณมีอิสระที่จะลงคะแนนตามที่คุณต้องการ ในที่สุดตอนนี้ฉันก็เข้าใจแล้วว่าทำไมผู้คนถึงหยาบคายฉัน แต่เหตุผลก็ยังผิด เมื่อได้รับ 404 นั่นไม่ได้หมายความว่าเส้นทางไม่สมเหตุสมผลมันหมายความว่าไม่มีทรัพยากรในตำแหน่งนั้น หยุดเต็ม สิ่งนี้เป็นจริงถ้าคุณร้องขอ/badurlหรือ/user/9เมื่อไม่มีผู้ใช้ดังกล่าว นักพัฒนาสามารถช่วยด้วยการเพิ่มวลีเหตุผลที่ดีกว่า 'ไม่พบ' แต่ไม่จำเป็นต้อง
Chris Pfohl

19
@Crisfole ฉันมีแนวโน้มที่จะไม่เห็นด้วย ( แต่ไม่ downvote ให้อ่าน) ตามออกของนิยาม W3 404The server has not found anything matching the Request-URIโดยเฉพาะ ในความเป็นจริงเว็บ / แอปพลิเคชันเซิร์ฟเวอร์พบ ACTION ที่ตรงกับ Request-URI แม้ว่าเซิร์ฟเวอร์ db จะไม่ อย่างไรก็ตามมันก็บอกว่าThis status code is commonly used when [...] no other response is applicableดังนั้นฉันคิดว่ามันตรวจสอบการใช้งานบ้าง (แม้ว่าฉันจะไม่เห็นด้วยกับ / ชอบมัน)
Daevin

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

364

ฉันคัดค้าน 404 อย่างเห็นได้ชัด 204 หรือ 200 ด้วยข้อมูลว่างเปล่า หรืออย่างน้อยหนึ่งควรใช้เอนทิตีการตอบสนองกับ 404

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

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

สิ่งนี้อาจถึงแก่ชีวิตได้: ลองจินตนาการถึงบริการบัญชีใน บริษัท ของคุณที่มีรายชื่อพนักงานทุกคนที่ครบกำหนดโบนัสประจำปี โชคไม่ดีที่ครั้งหนึ่งมันถูกเรียกว่ามันจะส่งคืน 404 นั่นหมายความว่าไม่มีใครครบกำหนดโบนัสหรือว่าแอปพลิเคชันหยุดทำงานสำหรับการปรับใช้ใหม่หรือไม่?

-> สำหรับแอปพลิเคชันที่ใส่ใจกับคุณภาพของข้อมูล 404 ที่ไม่มีเอนทิตีการตอบสนอง

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

ข้อได้เปรียบของ 404 มากกว่า 204 คือสามารถส่งคืนเอนทิตีการตอบสนองที่อาจมีข้อมูลบางอย่างเกี่ยวกับสาเหตุที่ไม่พบทรัพยากรที่ร้องขอ แต่ถ้าสิ่งนั้นมีความเกี่ยวข้องจริง ๆ เราอาจพิจารณาใช้การตอบสนอง 200 OK และออกแบบระบบในลักษณะที่ช่วยให้สามารถตอบสนองข้อผิดพลาดในข้อมูลของข้อมูลที่บรรจุได้ อีกวิธีหนึ่งสามารถใช้ payload ของการตอบกลับ 404 เพื่อส่งคืนข้อมูลที่มีโครงสร้างให้กับผู้โทร หากเขาได้รับเช่นหน้า html แทน XML หรือ JSON ที่สามารถแยกวิเคราะห์ได้นั่นเป็นตัวบ่งชี้ที่ดีว่ามีบางอย่างผิดพลาดทางเทคนิคแทนที่จะตอบกลับ "ไม่มีผลลัพธ์" ที่อาจถูกต้องจากมุมมองของผู้โทร หรืออาจใช้ส่วนหัวการตอบสนอง HTTP สำหรับสิ่งนั้น

ยังฉันต้องการ 204 หรือ 200 กับการตอบสนองที่ว่างเปล่าว่า วิธีนั้นสถานะของการดำเนินการทางเทคนิคของคำขอจะถูกแยกออกจากผลลัพธ์ตรรกะของคำขอ 2xx หมายถึง "การดำเนินการทางเทคนิคตกลงนี่คือผลลัพธ์จัดการกับมัน"

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

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


30
เหตุผลทางเทคนิคสำหรับ 'ไม่พบ' หรือที่เรียกว่าข้อผิดพลาดของเซิร์ฟเวอร์ สิ่งเหล่านั้นควรจะเป็นในยุค 500 โดยเฉพาะ "การบริการไม่สามารถพบ" 503 Service Unavailableคือ
Chris Pfohl

43
ผู้ถามยังถามเกี่ยวกับทรัพยากรเฉพาะ: ผู้ใช้คนเดียว (ไม่ใช่/usersเส้นทาง แต่/users/9คือ "ผู้ใช้ที่รู้จักกันในชื่อ # 9") ดังนั้นการเปรียบเทียบ 'ชุดผลลัพธ์ที่ว่างเปล่า' ของคุณจึงไม่สมเหตุสมผล 404 หมายความว่าวัตถุนั้นไม่มีอยู่จริง
Chris Pfohl

29
404 เพียงระบุว่าทรัพยากรที่ร้องขอ (ในกรณีนี้หมายเลขผู้ใช้ 9) ไม่พบ มันไม่มีส่วนเกี่ยวข้องกับรหัสแอพพลิเคชั่นที่ถูกไล่ออกหรือไม่มันไม่เกี่ยวข้องกับแอพพลิเคชั่นด้านหลังหรือไม่ เว็บเซิร์ฟเวอร์เป็นคำถามที่เกี่ยวกับไม่มีการพูดถึงการย้อนกลับของพร็อกซี่ในคำถาม
Chris Pfohl

29
การให้เหตุผลในคำตอบนี้ผิดอย่างมหันต์
เคิร์ตสปินเลอร์

20
404: ไคลเอ็นต์สามารถสื่อสารกับเซิร์ฟเวอร์ที่กำหนดได้ แต่เซิร์ฟเวอร์ไม่พบสิ่งที่ร้องขอ แท้จริงแล้ว: คำขอที่ได้รับมันเป็นรูปแบบที่ถูกต้องและเหมาะสม (คำขอไม่ถูกต้อง 400) เป็นของแท้หรือของสาธารณะ (ไม่ได้รับอนุญาต 401 / ต้องห้าม 403) ไม่จำเป็นต้องชำระเงิน (จำเป็นต้องชำระ 402) วิธีการร้องขอนั้นใช้ได้ดี ) คำขอยอมรับสามารถพอใจ (ไม่ได้รับการยอมรับ 406) ควรใช้ 200 Ok เมื่อผู้ใช้ได้รับทรัพยากร ว่างเปล่าไม่ใช่ทรัพยากร 400 ช่วงสำหรับข้อผิดพลาดของลูกค้า 500 ช่วงสำหรับข้อผิดพลาดของเซิร์ฟเวอร์ในระยะสั้น: เหตุผลของคุณปิด
Derk-Jan

62

ตอนแรกฉันคิดว่า 204 จะเข้าท่า แต่หลังจากการอภิปรายฉันเชื่อว่า 404 เป็นคำตอบที่ถูกต้องเท่านั้น พิจารณาข้อมูลต่อไปนี้:

ผู้ใช้: John, Peter

METHOD  URL                      STATUS  RESPONSE
GET     /users                   200     [John, Peter]
GET     /users/john              200     John
GET     /users/kyle              404     Not found
GET     /users?name=kyle`        200     []
DELETE  /users/john              204     No Content

พื้นหลังบางส่วน:

  1. การค้นหาส่งคืนอาร์เรย์ แต่ไม่มีการจับคู่ใด ๆ แต่มีเนื้อหานั่นคืออาร์เรย์ว่าง

  2. 404 เป็นที่รู้จักกันดีที่สุดสำหรับ url ที่ไม่ได้รับการสนับสนุนจากเซิร์ฟเวอร์ที่ร้องขอ แต่แหล่งข้อมูลที่ขาดหายไปนั้นเหมือนกัน
    แม้ว่า/users/:nameจะจับคู่กับusers/kyleผู้ใช้ Kyle ผู้ใช้ไม่สามารถใช้ทรัพยากรดังนั้น 404 ยังคงใช้ มันไม่ใช่ข้อความค้นหา แต่เป็นการอ้างอิงโดยตรงจาก URL แบบไดนามิกดังนั้นจึงเป็น 404

อย่างไรก็ตามสองเซ็นต์ของฉัน :)


9
ทิ้งน้ำหนักของฉันไว้เบื้องหลังสไตล์นี้เพื่อใช้ REST API ลูกค้าไม่ควรขอ / users / kyle เว้นแต่จะมีการบอกว่าทรัพยากรจะมีอยู่ผ่านการโทรไปยัง / users หรือ / users? name = kyle
Gary Barker

@GaryBarker แต่เนื่องจากนั่นคือ "การป้อนข้อมูลผู้ใช้" ในบางประเภท API ยังคงต้องจัดการอย่างถูกต้อง ในขณะที่คุณควรป้องกัน 404 ในไคลเอนต์ของคุณคุณไม่สามารถรับประกันได้ว่ามันถูกตรวจสอบในสถานที่แรก การออกแบบ API ควรทำโดยไม่คำนึงถึงการใช้งานที่แน่นอนของลูกค้าของคุณโดยเฉพาะอย่างยิ่งในแง่ของการป้อนข้อมูลผู้ใช้
RicoBrassers

นี่คือคำตอบที่ฉันเห็นด้วยมากที่สุด ตัวอย่างที่สมบูรณ์แบบของวิธีที่ฉันต้องการให้ API ทำงาน @ ข้อคิดเห็นของ GaryBarker ก็สมบูรณ์แบบเช่นกัน มันเป็นข้อผิดพลาดเมื่อคุณค้นหาบางอย่างด้วย ID และไม่มีอยู่จริง คุณควรรู้ว่ามี ID อยู่ก่อนการโทร ส่วนใหญ่เป็นเพราะการได้รับการตอบสนองที่ว่างเปล่า 'ประสบความสำเร็จ' เพียงแค่เตะข้อผิดพลาดไปตามถนนอาจถึงบางคน 'ไม่สามารถอ่านชื่อคุณสมบัติของไม่ได้กำหนด' เมื่อทำ user.name หรือบางสิ่งบางอย่าง
Jamie Twells

สิ่งที่เกี่ยวกับการรวมกันของทั้งสอง สมมติว่าผู้ใช้มีเพื่อน / ผู้ใช้ / ไคล์ / เพื่อน? name = เฟร็ด Kyle ไม่มีตัวตนดังนั้นคำตอบนี้จะเป็น 404 หรือไม่? หรือจะเป็น 200 เพราะเราไม่สนใจไคล์อย่างแท้จริงเราแค่แคร์ค้นหาเพื่อนที่มีชื่อเฟร็ดเท่านั้น
JSextonn

IMO ที่จะให้ 404 เนื่องจากเป็นคำขอที่ไม่ถูกต้อง: Kyle ไม่มีอยู่ดังนั้นการค้นหาเพื่อนของเขาจึงเป็นไปไม่ได้
Justus Romijn

23

หากคาดว่ามีทรัพยากรอยู่ แต่อาจว่างเปล่าฉันจะโต้แย้งว่ามันอาจจะง่ายกว่าที่จะได้ 200 OK ด้วยการเป็นตัวแทนที่บ่งบอกว่าสิ่งนั้นว่างเปล่า

ดังนั้นฉันจึงอยากได้ / สิ่งต่าง ๆ คืนค่า 200 OK ด้วย {"รายการ": []} มากกว่า 204 ที่ไม่มีอะไรเลยเพราะด้วยวิธีนี้คอลเลคชันที่มี 0 รายการสามารถถือว่าเหมือนกับคอลเลกชันที่มีหนึ่งหรือ รายการเพิ่มเติมในนั้น

ฉันเพิ่งปล่อย 204 ไม่มีเนื้อหาสำหรับ PUTs และ DELETEs ซึ่งอาจเป็นกรณีที่ไม่มีการนำเสนอที่เป็นประโยชน์จริง ๆ

ในกรณีที่ไม่มีสิ่ง / / 9 จริงๆ 404 นั้นเหมาะสม


1
ดูเหมือนว่าคุณต้องการตั้งโปรแกรมกับ API โดยใช้รูปแบบที่เป็นนามธรรมมากกว่าที่เรียกว่า RPC แทนที่จะเข้าถึงทรัพยากรโดยทำตามคำกริยาอย่างใกล้ชิดและ URL ที่ยึดตามทรัพยากรเช่นcustomers/1/addressbookวิธี RPC คือการเรียกจุดสิ้นสุดเช่นGetCustomerAddressBookและรับข้อมูลหรือเป็นโมฆะเป็นหลักและไม่ต้องกังวลเกี่ยวกับความซับซ้อนของ HTTP มีทั้งข้อดีและข้อเสีย
มัฟฟินแมน

2
@ The Muffin Man ฉันไม่แน่ใจว่าคุณจะหลอกว่ารู้ว่าฉันชอบ REST หรือ RPC หรือไม่และทำไมมันถึงเกี่ยวข้องกับการอภิปรายเกี่ยวกับรหัสสถานะที่จะกลับไปที่คำขอ HTTP GET
j0057

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

22

ในโครงการก่อนหน้านี้ฉันใช้ 404 หากไม่มีผู้ใช้ 9 แสดงว่าไม่พบวัตถุ ดังนั้น 404 ไม่พบมีความเหมาะสม

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


14

ตามที่w3โพสต์

200 ตกลง

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

202 ได้รับการยอมรับ

คำขอได้รับการยอมรับสำหรับการประมวลผล แต่การประมวลผลยังไม่เสร็จสมบูรณ์

204 ไม่มีเนื้อหา

เซิร์ฟเวอร์ดำเนินการตามคำขอ แต่ไม่จำเป็นต้องส่งคืนเอนทิตีและอาจต้องการส่งคืนข้อมูลปรับปรุงที่อัปเดต

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

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

401 ไม่ได้รับอนุญาต

การร้องขอต้องมีการรับรองความถูกต้องของผู้ใช้ การตอบสนองต้องมีฟิลด์ส่วนหัว WWW-Authenticate

ไม่พบ 404

เซิร์ฟเวอร์ไม่พบสิ่งใดที่ตรงกับ Request-URI ไม่มีการบ่งชี้ว่าเงื่อนไขเป็นแบบชั่วคราวหรือถาวร


โพสต์ w3 เป็นเรื่องเกี่ยวกับรหัสสถานะ HTTP HTTP ไม่เหมือนกับ REST REST ส่วนใหญ่ แต่ไม่จำเป็นต้องใช้ HTTP เป็นโปรโตคอลการส่งผ่าน 404 เป็นรหัสข้อผิดพลาดการขนส่ง HTTP หาก REST จะเหมือนกับ HTTP จะไม่เรียกว่า HTTP หรือไม่
anneb

1
@anneb อย่างที่คุณบอกว่า REST ใช้ HTTP ดังนั้นคำตอบนี้จึงสมเหตุสมผล REST ไม่ใช่ HTTP แต่ REST ไม่ใช่โปรโตคอลอยู่ดี REST ไม่จำเป็นต้องเหมือนกัน (หรือเหมือนกับ HTTP) สำหรับคำตอบนี้ไม่สมเหตุสมผล
Koray Tugay

@Koray Tugay: การค้นหาของ Google ใช้ http ดังนั้นตามคำตอบนี้การค้นหาของ Google ควรตอบสนองสถานะ HTTP 404 หากไม่มีสิ่งใดที่ตรงกับการค้นหาหรือไม่
anneb

@anneb Google Search คุณพูดถึงแอปพลิเคชั่น RESTful หรือไม่? ฉันไม่คิดอย่างนั้น .. ดังนั้นคำตอบจะไม่ ย้อนกลับไปที่คำถามเดิมและคำตอบนี้แทนที่จะตกอยู่ในโพรงกระต่ายหาก Google Search หนึ่งวันสร้าง RESTful API (หรืออาจจะมีอยู่แล้วฉันไม่รู้) อาจกลับมา204 No Contentเมื่อไม่มีผลลัพธ์ ไม่ได้404ก็มีผลสำหรับคุณ แต่มันไม่มีเนื้อหา ..
Koray Tugay

13

เพื่อสรุปหรือทำให้ง่ายขึ้น

2xx: ข้อมูลเพิ่มเติม: รูปแบบที่ดี URI: เกณฑ์ไม่ได้เป็นส่วนหนึ่งของ URI: หากเกณฑ์เป็นตัวเลือกที่สามารถระบุได้ใน @RequestBody และ @RequestParam ควรนำไปสู่ ​​2xx ตัวอย่าง: กรองตามชื่อ / สถานะ

4xx: ข้อมูลที่คาดหวัง: รูปแบบที่ไม่ดี URI: เกณฑ์เป็นส่วนหนึ่งของ URI: หากเกณฑ์เป็นข้อบังคับที่สามารถระบุได้เฉพาะใน @PathVariable เท่านั้นจึงควรนำไปสู่ ​​4xx ตัวอย่าง: ค้นหาด้วย id เฉพาะ

ดังนั้นสำหรับสถานการณ์ที่ถาม: "users / 9" จะเป็น 4xx (อาจเป็น 404) แต่สำหรับ "users? name = superman" ควรเป็น 2xx (อาจเป็น 204)


12

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

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

ตัวอย่างที่ให้มาถามเกี่ยวกับวัตถุเฉพาะผู้ใช้ /users/9ตัวอย่างที่ให้ไว้แทนถามเกี่ยวกับวัตถุที่เฉพาะเจาะจงที่ผู้ใช้หากไม่พบผู้ใช้ # 9 จะไม่มีการส่งคืนวัตถุผู้ใช้ คุณขอทรัพยากรเฉพาะ (วัตถุผู้ใช้) และไม่ได้รับเพราะไม่พบดังนั้น 404 จึงเหมาะสม

ฉันคิดว่าวิธีการแก้ไขปัญหานี้คือถ้าคุณสามารถใช้การตอบสนองในแบบที่คุณคาดหวังได้โดยไม่ต้องเพิ่มคำสั่งแบบมีเงื่อนไขใด ๆ จากนั้นใช้ 204 หรือใช้ 404

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

แน่นอนคุณสามารถส่งคืนวัตถุโดยใช้รูปแบบวัตถุ null หากที่เหมาะสมกับความต้องการของคุณ แต่นั่นคือการสนทนาสำหรับหัวข้ออื่น


9

หลังจากดูคำถามคุณไม่ควรใช้404ทำไม

ขึ้นอยู่กับRFC 7231รหัสสถานะที่ถูกต้องคือ204

ในแอปพลิเคชันด้านบนฉันสังเกตเห็นความเข้าใจผิดเล็กน้อย 1 ข้อ

1.- ทรัพยากรคือ: /users

2.- /users/8ไม่ใช่ทรัพยากรนี่คือ: ทรัพยากรที่/usersมีพารามิเตอร์เส้นทาง8ผู้บริโภคอาจไม่สามารถสังเกตเห็นได้และไม่ทราบความแตกต่าง แต่ผู้เผยแพร่ทำและต้องรู้สิ่งนี้! ... ดังนั้นเขาจะต้องตอบสนองผู้บริโภคอย่างแม่นยำ ระยะเวลา

ดังนั้น:

จาก RFC: 404 ไม่ถูกต้องเนื่องจาก/usersพบทรัพยากรแต่ลอจิกที่ดำเนินการโดยใช้พารามิเตอร์8ไม่พบสิ่งใดที่contentจะส่งกลับเป็นการตอบสนองดังนั้นคำตอบที่ถูกต้องคือ:204

ประเด็นหลักที่นี่คือ: 404ไม่พบว่ามีทรัพยากรในการประมวลผลตรรกะภายใน

204คือ: ฉันพบทรัพยากรตรรกะถูกดำเนินการ แต่ฉันไม่พบข้อมูลใด ๆ โดยใช้เกณฑ์ของคุณที่ระบุไว้ในพารามิเตอร์เส้นทางดังนั้นฉันไม่สามารถคืนสิ่งใดให้คุณ ขออภัยตรวจสอบเกณฑ์ของคุณและโทรหาฉันอีกครั้ง

200: ตกลงฉันพบทรัพยากรตรรกะถูกดำเนินการ (แม้เมื่อฉันไม่ได้บังคับให้คืนสิ่งใด) ใช้สิ่งนี้และใช้ตามความประสงค์ของคุณ

205: (ตัวเลือกที่ดีที่สุดของการตอบกลับ GET) ฉันพบทรัพยากรตรรกะถูกดำเนินการฉันมีเนื้อหาบางส่วนสำหรับคุณใช้งานได้ดีด้วยวิธีที่คุณจะแบ่งปันสิ่งนี้ในมุมมองโปรดรีเฟรชมุมมองเพื่อ แสดงมัน

หวังว่ามันจะช่วย


8

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

  • ในกรณีของพารามิเตอร์พา ธ พารามิเตอร์เป็นส่วนหนึ่งของพา ธ ของทรัพยากร ในกรณีของ/users/9การตอบสนองควรเป็น404เพราะไม่พบทรัพยากรนั้น /users/9เป็นทรัพยากรและผลลัพธ์นั้นเป็นข้อผิดพลาดหรือไม่มีข้อผิดพลาด นี่ไม่ใช่ Monad
  • ในกรณีที่พารามิเตอร์การค้นหาพารามิเตอร์ไม่ได้เป็นส่วนหนึ่งของเส้นทางทรัพยากร ในกรณีของ/users?id=9การตอบสนองควรเป็น204เพราะ/usersพบทรัพยากรแต่ไม่สามารถส่งคืนข้อมูลใด ๆ มีทรัพยากร/usersอยู่และผลลัพธ์เป็นค่าที่ไม่ถูกต้องแม้ว่าจะว่างเปล่าก็ตาม ถ้าidเป็นเอกลักษณ์นี่คือ monad

ว่าจะใช้พารามิเตอร์พา ธ หรือพารามิเตอร์เคียวรีขึ้นอยู่กับกรณีการใช้งาน ฉันชอบพารามิเตอร์พา ธ สำหรับคำสั่งบังคับ, กฎเกณฑ์, หรือการระบุอาร์กิวเมนต์และพารามิเตอร์การสืบค้นสำหรับอาร์กิวเมนต์ที่เป็นทางเลือก, ไม่เป็นบรรทัดฐาน, หรือการอ้างเหตุผล (เช่นเพจจิ้ง, การเรียงหน้าภาษา ใน REST API ผมจะใช้/users/9ไม่ได้/users?id=9โดยเฉพาะอย่างยิ่งเพราะการทำรังที่เป็นไปได้ที่จะได้รับ "บันทึกเด็ก" ชอบ/users/9/ssh-keys/0ที่จะได้รับคีย์สาธารณะ SSH ครั้งแรกหรือครั้ง/users/9/address/2ที่จะได้รับที่อยู่ทางไปรษณีย์สาม

ฉันชอบใช้ 404 นี่คือเหตุผล:

  • การเรียกเมธอด unary (1 ผลลัพธ์) และ n-ary (ผลลัพธ์ n) ไม่ควรเปลี่ยนแปลงด้วยเหตุผลที่ไม่ดี ฉันชอบที่จะมีรหัสตอบกลับเหมือนกันถ้าเป็นไปได้ จำนวนผลลัพธ์ที่คาดหวังนั้นแตกต่างกันแน่นอนว่าคุณคาดว่าร่างกายจะเป็นวัตถุ (เอกนารี) หรืออาเรย์ของวัตถุ (n-ary)
  • สำหรับ n-ary ฉันจะส่งคืนอาร์เรย์และในกรณีที่ไม่มีผลลัพธ์ฉันจะไม่ส่งคืนไม่มีชุด (ไม่มีเอกสาร) ฉันจะส่งคืนชุดว่าง (เอกสารว่างเช่นอาร์เรย์ว่างใน JSON หรือองค์ประกอบว่างใน XML ) นั่นคือมันยังคง 200 แต่มีศูนย์บันทึก ไม่มีเหตุผลที่จะนำข้อมูลนี้ไปวางไว้บนลวดนอกเหนือจากในร่างกาย
  • 204เป็นเหมือนvoidวิธีการ ฉันจะไม่ใช้มันGETเพียงเพื่อPOST, และPUT DELETEฉันสร้างข้อยกเว้นในกรณีGETที่ตัวระบุเป็นพารามิเตอร์การสืบค้นไม่ใช่พารามิเตอร์พา ธ
  • การไม่พบระเบียนนั้นเป็นเช่นNoSuchElementExceptionนั้นArrayIndexOutOfBoundsExceptionหรือสิ่งที่เกิดขึ้นจากลูกค้าโดยใช้รหัสที่ไม่มีอยู่ดังนั้นจึงเป็นข้อผิดพลาดของไคลเอ็นต์
  • จากมุมมองของรหัสการรับ204หมายถึงสาขาเพิ่มเติมในรหัสที่สามารถหลีกเลี่ยงได้ มันซับซ้อนรหัสลูกค้าและในบางกรณีก็มีความซับซ้อนรหัสเซิร์ฟเวอร์ (ขึ้นอยู่กับว่าคุณใช้เอนทิตี้ / แบบจำลอง monads หรือเอนทิตี / รุ่นธรรมดาและฉันขอแนะนำให้อยู่ห่างจากเอนทิตี้ / แบบจำลอง monads มันอาจนำไปสู่ ของ monad ที่คุณคิดว่าการผ่าตัดประสบความสำเร็จและคืน 200 หรือ 204 เมื่อคุณควรส่งคืนอย่างอื่น)
  • รหัสลูกค้านั้นง่ายต่อการเขียนและเข้าใจหาก 2xx หมายถึงเซิร์ฟเวอร์ทำตามที่ลูกค้าร้องขอและ 4xx หมายถึงเซิร์ฟเวอร์ไม่ได้ทำตามที่ลูกค้าร้องขอและเป็นความผิดของลูกค้า การไม่ให้ลูกค้าบันทึกว่าไคลเอนต์ที่ขอโดย id เป็นความผิดของลูกค้าเพราะลูกค้าร้องขอรหัสที่ไม่มีอยู่

สุดท้าย แต่ไม่ท้ายสุด: ความสอดคล้อง

  • GET /users/9
  • PUT /users/9 และ DELETE /users/9

PUT /users/9และDELETE /users/9ต้องกลับมา204ในกรณีที่การอัปเดตหรือลบสำเร็จ ดังนั้นสิ่งที่พวกเขาควรกลับมาในกรณีที่ผู้ใช้ 9 ไม่มีอยู่? มันไม่มีเหตุผลที่จะมีสถานการณ์เดียวกับที่แสดงเป็นรหัสสถานะที่แตกต่างกันขึ้นอยู่กับวิธีการใช้ HTTP

นอกจากนี้ไม่ใช่กฎเกณฑ์ แต่เป็นเหตุผลทางวัฒนธรรม: หาก204ใช้เพื่อGET /users/9สิ่งต่อไปที่จะเกิดขึ้นในโครงการคือมีใครบางคนคิดว่าการกลับมา204เป็นสิ่งที่ดีสำหรับวิธีการแบบดั้งเดิม และนั่นทำให้รหัสลูกค้าซับซ้อนเพราะแทนที่จะตรวจสอบ2xxแล้วถอดรหัสร่างกายลูกค้าต้องทำการตรวจสอบโดยเฉพาะ204และในกรณีนั้นข้ามการถอดรหัสเนื้อหา แตกหน่อลูกค้าทำอะไรแทน สร้างอาร์เรย์ว่างหรือไม่ ทำไมไม่มีเส้นลวดล่ะ? หากลูกค้าสร้างอาร์เรย์ที่ว่างเปล่า 204 เป็นรูปแบบของการบีบอัดโง่ หากไคลเอนต์ใช้nullแทนจะสามารถเปิดเวิร์มต่าง ๆ ได้


5

Twitter ใช้ 404 พร้อมข้อความแสดงข้อผิดพลาดที่กำหนดเองเช่น "ไม่พบข้อมูล"

Ref: https://developer.twitter.com/en/docs/basics/response-codes.html


2
Microsoft Azure ใช้ 404 เช่นกัน แต่ไม่สามารถเกิดข้อผิดพลาดที่กำหนดเองเมื่อตอบกลับคำขอ HEAD docs.microsoft.com/en-us/rest/api/resources/resources/…
Mike

3

204 เหมาะสมกว่า โดยเฉพาะอย่างยิ่งเมื่อคุณมีระบบการแจ้งเตือนเพื่อให้แน่ใจว่าเว็บไซต์ของคุณปลอดภัย 404 ในกรณีนี้จะทำให้เกิดความสับสนเพราะคุณไม่รู้ว่าการแจ้งเตือน 404 นั้นเป็นข้อผิดพลาดแบ็กเอนด์หรือคำขอปกติ แต่ไม่มีการตอบสนอง


คุณไม่ควรส่งคืน 404 หากคุณมีข้อผิดพลาดของแบ็กเอนด์
appalling22

3

ฉันจะบอกว่าไม่เหมาะสมจริงๆ ดังที่ได้กล่าวไว้ - โดย @anneb ฉันก็คิดว่าปัญหาส่วนหนึ่งเกิดจากการใช้รหัสตอบกลับ HTTP เพื่อส่งสถานะที่เกี่ยวข้องกับบริการ RESTful สิ่งใดที่บริการ REST ต้องกล่าวเกี่ยวกับการดำเนินการของตนเองควรได้รับการขนส่งโดยใช้รหัสเฉพาะของ REST

1

ฉันขอยืนยันว่าหากเซิร์ฟเวอร์ HTTP พบบริการใด ๆ ที่พร้อมที่จะตอบคำขอที่ถูกส่งไปมันไม่ควรตอบกลับด้วย HTTP 404 - ในที่สุดเซิร์ฟเวอร์จะพบบางสิ่ง - เว้นแต่จะมีการบอกอย่างชัดเจนจาก บริการที่ประมวลผลคำขอ

สมมติว่าสำหรับช่วงเวลาที่ URL http://example.com/service/return/testต่อไปนี้:

  • กรณี A คือเซิร์ฟเวอร์นั้น“ แค่หาไฟล์บนระบบไฟล์” หากไม่มีอยู่404ถูกต้อง เช่นเดียวกันถ้ามันขอให้บริการบางอย่างส่งไฟล์นี้อย่างแน่นอนและบริการนั้นบอกว่าไม่มีชื่อนั้นอยู่
  • ในกรณี B เซิร์ฟเวอร์ไม่ทำงานกับไฟล์“ ของจริง” แต่จริง ๆ แล้วคำขอจะได้รับการประมวลผลโดยบริการอื่น ๆ - เช่นระบบ templating บางประเภท ที่นี่เซิร์ฟเวอร์ไม่สามารถอ้างสิทธิ์ใด ๆ เกี่ยวกับการมีอยู่ของทรัพยากรได้เนื่องจากไม่ได้รู้อะไรเกี่ยวกับมัน (เว้นแต่จะได้รับแจ้งจากบริการที่จัดการ)

หากไม่มีการตอบสนองใด ๆ จากบริการที่ต้องการพฤติกรรมที่แตกต่างอย่างชัดเจนเซิร์ฟเวอร์ HTTP สามารถพูดได้ 3 สิ่งเท่านั้น:

  • 503 ถ้าบริการที่ควรจะจัดการกับคำขอไม่ได้ทำงานหรือตอบสนอง;
  • 200 มิฉะนั้นเป็นเซิร์ฟเวอร์ HTTP สามารถตอบสนองคำขอได้จริง - ไม่ว่าบริการจะพูดอะไรในภายหลัง
  • 400หรือ404เพื่อระบุว่าไม่มีบริการดังกล่าว (ตรงข้ามกับ "มีอยู่ แต่ออฟไลน์") และไม่พบสิ่งใด

2

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

  • REST:EMPTYเช่นถ้าถูกขอให้ค้นหา sth และงานวิจัยนั้นกลับว่างเปล่า
  • REST:NOT FOUNDถ้ามันถูกถามโดยเฉพาะสำหรับฏ. “ เหมือน ID” - เป็นชื่อไฟล์หรือทรัพยากรตาม ID หรือรายการหมายเลข 24 เป็นต้น - และไม่พบทรัพยากรที่ระบุ (โดยปกติจะมีการขอทรัพยากรเฉพาะหนึ่งรายการและไม่พบ)
  • REST:INVALID หากส่วนใดส่วนหนึ่งของคำขอที่ส่งไปนั้นไม่ได้รับการยอมรับจากบริการ

(โปรดทราบว่าฉันนำหน้าสิ่งเหล่านี้ด้วย“ REST:” โดยมีวัตถุประสงค์เพื่อทำเครื่องหมายข้อเท็จจริงว่าแม้ว่าสิ่งเหล่านี้อาจมีค่าหรือถ้อยคำเดียวกันกับรหัสการตอบกลับ HTTP แต่พวกเขาแตกต่างกันโดยสิ้นเชิง)

3

กลับไปที่ URL ข้างต้นแล้วตรวจสอบกรณี B ที่ให้บริการบ่งชี้ไปยังเซิร์ฟเวอร์ HTTP ที่มันไม่ได้จัดการกับคำขอนี้เอง SERVICEแต่ผ่านมันไป HTTP เพียงทำหน้าที่ออกว่ามันจะกลับมามือโดยSERVICEก็ไม่ได้รู้อะไรเกี่ยวกับreturn/testส่วนที่เป็นที่ handeled SERVICEโดย หากบริการนั้นกำลังทำงานอยู่ HTTP ควรกลับมา200เหมือนเดิมเมื่อพบบางสิ่งเพื่อจัดการกับคำขอ

สถานะที่ส่งคืนโดยSERVICE(และซึ่งตามที่กล่าวไว้ข้างต้นต้องการเห็นในส่วนหัวที่แยกต่างหาก) ขึ้นอยู่กับการกระทำที่คาดหวังจริง:

  • หากreturn/testถามถึงทรัพยากรที่เฉพาะเจาะจง: ถ้ามีอยู่ให้ส่งคืนด้วยสถานะของREST:FOUND; ถ้าทรัพยากรที่ไม่อยู่กลับREST:NOT FOUND; สิ่งนี้สามารถขยายออกเพื่อส่งคืนREST:GONEถ้าเรารู้ว่ามีอยู่ครั้งเดียวและจะไม่กลับมาและREST:MOVEDถ้าเรารู้ว่ามันหายไปจากฮอลลีวู้ด
  • หากreturn/testพิจารณาว่าเป็นการดำเนินการค้นหาหรือคล้ายตัวกรอง: หากชุดผลลัพธ์ว่างเปล่าให้ส่งคืนชุดว่างในประเภทที่ร้องขอและสถานะเป็นREST:EMPTY; ชุดผลลัพธ์ในประเภทที่ร้องขอและสถานะเป็นREST:SUCCESS
  • ถ้าreturn/testไม่ใช่การปฏิบัติการที่คำนวณโดยSERVICE : return REST:ERRORถ้ามันผิดทั้งหมด (เช่น typo like retrun/test) หรือREST:NOT IMPLEMENTEDในกรณีที่มีการวางแผนในภายหลัง

4

ความแตกต่างนี้สะอาดกว่าการผสมสองอย่างเข้าด้วยกัน นอกจากนี้ยังจะทำให้การดีบักง่ายขึ้นและประมวลผลเพียงเล็กน้อยที่ซับซ้อนมากขึ้นถ้าทั้งหมด

  • ถ้า HTTP 404 ถูกส่งคืนเซิร์ฟเวอร์จะบอกฉันว่า "ฉันไม่รู้ว่าคุณกำลังพูดถึงอะไร" ในขณะที่ส่วนที่เหลือของคำขอของฉันอาจไม่เป็นไรฉันกำลังมองหา par'Mach ในสถานที่ที่ผิดทั้งหมด
  • ในทางกลับกัน HTTP 200 และ REST: ERR บอกฉันว่าฉันได้รับบริการ แต่ทำสิ่งผิดปกติในคำขอของฉันที่จะรับบริการ
  • จาก HTTP 200 และ REST: ว่างเปล่าฉันรู้ว่าฉันไม่ได้ทำอะไรผิด - เซิร์ฟเวอร์ที่ถูกต้องเซิร์ฟเวอร์พบบริการร้องขอการบริการที่ถูกต้อง แต่ผลลัพธ์การค้นหาว่างเปล่า

สรุป

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

สถานะของคำร้องขอที่ประมวลผลโดยเซอร์วิสและไม่ใช่เซิร์ฟเวอร์ HTTP ควรได้รับจริงๆ (RFC 6919) โดยรหัสตอบกลับ HTTP รหัส HTTP SHOULD (RFC 2119) มีเฉพาะข้อมูลที่เซิร์ฟเวอร์ HTTP สามารถให้จากขอบเขตของตัวเอง: กล่าวคือไม่ว่าจะพบบริการที่จะดำเนินการตามคำขอหรือไม่

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


2

ตาม RFC7231 - page59 ( https://tools.ietf.org/html/rfc7231#page-59 ) คำจำกัดความของการตอบสนองรหัสสถานะ 404 คือ:

6.5.4 404 ไม่พบรหัสสถานะ 404 (ไม่พบ) ระบุว่าเซิร์ฟเวอร์ต้นทางไม่พบการแสดงปัจจุบันสำหรับทรัพยากรเป้าหมายหรือไม่เต็มใจที่จะเปิดเผยว่ามีอยู่ รหัสสถานะ 404 ไม่ได้ระบุว่าการขาดการเป็นตัวแทนนี้เป็นการชั่วคราวหรือถาวร รหัสสถานะ 410 (หายไป) เป็นที่ต้องการมากกว่า 404 ถ้าเซิร์ฟเวอร์ต้นทางรู้ว่าน่าจะเป็นวิธีที่สามารถกำหนดค่าได้ซึ่งน่าจะเป็นเงื่อนไขที่ถาวร การตอบกลับ 404 สามารถแคชได้โดยค่าเริ่มต้น เช่นเว้นแต่ระบุไว้เป็นอย่างอื่นโดยคำนิยามวิธีการหรือการควบคุมแคชอย่างชัดเจน (ดูหัวข้อ 4.2.2 ของ [RFC7234])

และสิ่งสำคัญที่ทำให้เกิดความสงสัยคือนิยามของทรัพยากรในบริบทข้างต้น ตาม RFC เดียวกัน (7231) คำจำกัดความของทรัพยากรคือ:

ทรัพยากร: เป้าหมายของคำขอ HTTP เรียกว่า "ทรัพยากร" HTTP ไม่ได้ จำกัด ลักษณะของทรัพยากร เพียงกำหนดอินเทอร์เฟซที่อาจใช้เพื่อโต้ตอบกับทรัพยากร แต่ละทรัพยากรถูกระบุโดย Uniform Resource Identifier (URI) ตามที่อธิบายไว้ในส่วนที่ 2.7 ของ [RFC7230] เมื่อลูกค้าสร้างข้อความร้องขอ HTTP / 1.1 ลูกค้าจะส่ง URI เป้าหมายในรูปแบบต่าง ๆ ตามที่กำหนดไว้ใน (ส่วน 5.3 ของ [RFC7230] เมื่อได้รับคำขอเซิร์ฟเวอร์จะสร้าง URI คำขอที่มีประสิทธิภาพใหม่สำหรับทรัพยากรเป้าหมาย (มาตรา 5.5 ของ [RFC7230]) เป้าหมายการออกแบบหนึ่งของ HTTP คือการแยกการระบุทรัพยากรจากซีแมนทิกส์คำขอซึ่งทำไปได้โดยการมอบซีเมนต์คำขอในวิธีการร้องขอ (ส่วนที่ 4) และฟิลด์ส่วนหัวที่ปรับเปลี่ยนการร้องขอไม่กี่ (ส่วนที่ 5)

ดังนั้นในรหัสสถานะ 404 ของฉันไม่ควรใช้กับคำขอ GET ที่ประสบความสำเร็จกับผลลัพธ์ที่ว่างเปล่า (ตัวอย่าง: รายการที่ไม่มีผลลัพธ์สำหรับตัวกรองเฉพาะ)


2

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

  • คำขอ: ฉันขอข้อมูลบางส่วนได้ไหม
  • ทรัพยากร (จุดสิ้นสุด API): ฉันจะรับคำขอนั้นจากคุณที่นี่ [ส่งการตอบกลับของข้อมูลที่เป็นไปได้]

ไม่พบจุดสิ้นสุดและพบตารางและคอลัมน์เพื่อให้ DB สอบถามและข้อมูลถูกส่งคืน "สำเร็จ"!

ตอนนี้ - ไม่ว่า "การตอบสนองที่ประสบความสำเร็จ" มีข้อมูลหรือไม่ไม่สำคัญคุณขอการตอบสนองของข้อมูล "ที่มีศักยภาพ" และการตอบสนองที่มีข้อมูล "ที่อาจเกิดขึ้น" นั้น ว่างเปล่า ฯลฯ เป็นข้อมูลที่ถูกต้อง

200 หมายถึงการร้องขออะไรก็ตามที่เราประสบความสำเร็จ ฉันขอข้อมูลไม่มีข้อผิดพลาดกับ HTTP / REST และเนื่องจากข้อมูล (แม้ว่าจะว่างเปล่า) ก็ถูกส่งคืน "คำขอข้อมูล" ของฉันสำเร็จ

ส่งคืน 200 และปล่อยให้ผู้ร้องขอจัดการข้อมูลที่ว่างเปล่าเนื่องจากแต่ละสถานการณ์สมมติรับประกัน!

ลองพิจารณาตัวอย่างนี้:

  • คำขอ: ตาราง "infractions" ข้อความค้นหาที่มี ID ผู้ใช้ 1234
  • ทรัพยากร (จุดสิ้นสุด API): ส่งคืนการตอบกลับ แต่ข้อมูลว่างเปล่า

ข้อมูลนี้ว่างเปล่าถูกต้องทั้งหมด หมายความว่าผู้ใช้ไม่มีการละเมิด นี่คือ 200 เนื่องจากใช้ได้ทั้งหมดแล้วฉันสามารถทำ:

คุณไม่มีการละเมิดมีมัฟฟินบลูเบอร์รี่!

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


[โน้ตหน้าด้าน .. ]

ในชื่อของคุณคุณยอมรับโดยไม่รู้ตัวว่า 200 เป็นการตอบสนองที่ถูกต้อง:

รหัสตอบกลับ REST ที่เหมาะสมสำหรับคำขอที่ถูกต้องแต่เป็นข้อมูลว่างเปล่าคืออะไร


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

  1. ความมั่นคง หากคุณใช้ 404 สำหรับ "ไม่มีข้อมูล" ให้ใช้ทุกครั้งที่การตอบกลับไม่มีข้อมูล
  2. อย่าใช้สถานะเดียวกันสำหรับมากกว่าหนึ่งความหมาย หากคุณส่งคืน 404 เมื่อไม่พบทรัพยากร (เช่นจุดสิ้นสุด API ไม่มีอยู่ ฯลฯ ) จากนั้นอย่าใช้เพื่อไม่ให้ส่งคืนข้อมูล มันแค่จัดการกับการตอบสนองที่เจ็บปวด
  3. พิจารณาบริบทอย่างระมัดระวัง "คำขอ" คืออะไร? คุณกำลังพูดว่าคุณพยายามจะทำอะไรให้สำเร็จ

1

เข้ารหัสเนื้อหาการตอบกลับด้วย enum ทั่วไปที่อนุญาตให้ไคลเอ็นต์เปิดใช้งานและแยกลอจิกตามลำดับ ฉันไม่แน่ใจว่าลูกค้าของคุณจะแยกความแตกต่างระหว่าง "data not found" 404 และ "ไม่พบทรัพยากรเว็บ" 404 ได้อย่างไร คุณไม่ต้องการให้ใครบางคนเรียกดูผู้ใช้Z / 9 และให้ลูกค้าสงสัยว่าคำขอนั้นถูกต้อง แต่ไม่มีข้อมูลที่ส่งคืน


1

ทำไมไม่ใช้ 410? มันแนะนำทรัพยากรที่ร้องขอไม่มีอยู่อีกต่อไปและลูกค้าคาดว่าจะไม่ทำการร้องขอทรัพยากรนั้นในกรณีของคุณusers/9มันแสดงให้เห็นทรัพยากรที่ร้องขอไม่มีอยู่แล้วและลูกค้าที่คาดว่าจะไม่ทำตามคำขอสำหรับทรัพยากรนั้นในกรณีของคุณ

คุณสามารถค้นหารายละเอียดเพิ่มเติมเกี่ยวกับ 410 ได้ที่นี่: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html


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

สิ่งที่ฮอลลี่พูด ในการเพิ่มไปยังจุดของเธอ: แม้ในกรณีที่ผู้ใช้มีอยู่และถูกลบ 410 ผิดเพราะถ้าผู้ใช้ถูกยกเลิกการลบ? (กรณีใดเป็นกรณีพิเศษที่ถูกสร้างขึ้นในภายหลัง)
Christian Hujer

เพราะ 410 ควรเป็นสถานการณ์ถาวร restapitutorial.com/httpstatuscodes.html
Akostha

1

มันเป็นเรื่องน่าเศร้าที่บางสิ่งที่เรียบง่ายและมีความหมายได้กลายมาเป็น "ฐานความคิดเห็น" ในหัวข้อนี้

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

แต่ละเอนทิตีดังกล่าวคาดว่าจะสามารถระบุได้โดย URL ที่ไม่ซ้ำกันเช่น

  • / user / 9 - เอนทิตีเดียว: USER ID = 9
  • / users - เอนทิตีเดียว: รายการของผู้ใช้ทั้งหมด
  • /media/x.mp3 - เอนทิตีเดียว: ไฟล์สื่อชื่อ x.mp3
  • / search - เอนทิตีเดียว: เนื้อหาแบบไดนามิกขึ้นอยู่กับ params แบบสอบถาม

หากเซิร์ฟเวอร์ค้นหาทรัพยากรด้วย URL ที่กำหนดมันไม่สำคัญว่าเนื้อหาของมันคืออะไร - 2G ของข้อมูล, null, {}, [] - ตราบใดที่มีอยู่มันจะเป็น 200 แต่ถ้าเอนทิตีดังกล่าวเป็น ไม่รู้จักเซิร์ฟเวอร์เป็น EXPECTED ที่จะส่งคืน 404 "ไม่พบ"

ความสับสนหนึ่งดูเหมือนว่ามาจากนักพัฒนาที่คิดว่าหากแอปพลิเคชันมีตัวจัดการสำหรับรูปร่างเส้นทางที่แน่นอนมันไม่ควรเป็นข้อผิดพลาด ในสายตาของโปรโตคอล HTTP มันไม่สำคัญว่าเกิดอะไรขึ้นใน internals ของเซิร์ฟเวอร์ (เช่นไม่ว่าจะเป็นเราเตอร์เริ่มต้นตอบสนองหรือจัดการสำหรับรูปร่างเส้นทางที่เฉพาะเจาะจง) ตราบใดที่ไม่มีเอนทิตีที่ตรงกันบนเซิร์ฟเวอร์ไปยัง URL ที่ร้องขอ (ที่ร้องขอไฟล์ MP3 หน้าเว็บวัตถุผู้ใช้ ฯลฯ ) ซึ่งจะส่งคืนเนื้อหาที่ถูกต้อง (ว่างเปล่าหรืออย่างอื่น) จะต้องเป็น 404 (หรือ 410 เป็นต้น)

อีกประเด็นที่น่าสับสนก็คือ "ไม่มีข้อมูล" และ "ไม่มีเอนทิตี" อดีตคือเนื้อหาของเอนทิตีและสิ่งหลังเกี่ยวกับการมีอยู่ของมัน

ตัวอย่างที่ 1:

  • ไม่มีข้อมูล: / ผู้ใช้คืนค่า 200 OK, เนื้อหา: [] เพราะยังไม่มีใครลงทะเบียน
  • ไม่มีเอนทิตี: / users ส่งคืน 404 เนื่องจากไม่มี path / users

ตัวอย่างที่ 2:

  • ไม่มีข้อมูล: / user / 9 คืนค่า 200 OK, body: {}, เนื่องจาก ID ผู้ใช้ = 9 ไม่เคยป้อนข้อมูลส่วนตัวของเขา / เธอ
  • ไม่มีเอนทิตี: / user / 9 ส่งคืน 404 เนื่องจากไม่มี ID ผู้ใช้ = 9

ตัวอย่างที่ 3:

  • ไม่มีข้อมูล: / search? name = Joe คืนค่า 200 OK [] เนื่องจากไม่มี Joe ในฐานข้อมูล
  • ไม่มีเอนทิตี: / search? name = Joe ส่งคืน 404 เนื่องจากไม่มีเส้นทาง / ค้นหา

0

404 จะสร้างความสับสนให้กับลูกค้าหากคุณกลับมาเพราะไม่มีข้อมูลในการตอบสนอง

สำหรับฉันรหัสตอบสนอง 200 ที่มีร่างกายว่างเปล่าเพียงพอที่จะเข้าใจว่าทุกอย่างสมบูรณ์แบบ แต่ไม่มีข้อมูลที่ตรงกับข้อกำหนด


0

ตามที่ Microsoft: ตัวควบคุมชนิดส่งคืนการกระทำใน ASP.NET Core API เว็บเลื่อนลงไปด้านล่างเกือบคุณพบ blurb ต่อไปนี้เกี่ยวกับ 404 ที่เกี่ยวข้องกับวัตถุที่ไม่พบในฐานข้อมูล ที่นี่พวกเขาแนะนำว่า 404 เหมาะสำหรับข้อมูลที่ว่างเปล่า

ป้อนคำอธิบายรูปภาพที่นี่


0

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

คาดว่าสถานะ 200 จะมีข้อมูลทรัพยากร - ดังนั้นจึงไม่ใช่ตัวเลือกที่เหมาะสม สถานะ 204 หมายถึงอย่างอื่นทั้งหมดและไม่ควรใช้เป็นการตอบกลับคำขอ GET

สถานะที่มีอยู่อื่นทั้งหมดไม่สามารถใช้ได้ด้วยเหตุผลใดเหตุผลหนึ่งหรืออย่างอื่น

ฉันได้เห็นหัวข้อนี้ถูกกล่าวถึงครั้งแล้วครั้งเล่าในหลายสถานที่ สำหรับฉันมันชัดเจนว่าการกำจัดความสับสนในหัวข้อนั้นจำเป็นต้องมีสถานะความสำเร็จเฉพาะ บางอย่างเช่น " 209 - ไม่มีทรัพยากรที่จะแสดง"

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

คำถามเดียวก็คือ: ฉันจะให้ RFC ยอมรับว่าเป็นมาตรฐานได้อย่างไร

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