รหัสตอบกลับ HTTP สำหรับ POST เมื่อทรัพยากรมีอยู่แล้ว


842

ฉันกำลังสร้างเซิร์ฟเวอร์ที่อนุญาตให้ลูกค้าจัดเก็บวัตถุ วัตถุเหล่านั้นถูกสร้างอย่างสมบูรณ์ที่ฝั่งไคลเอ็นต์พร้อมด้วย ID วัตถุที่ถาวรตลอดอายุการใช้งานของวัตถุ

ฉันได้กำหนด API เพื่อให้ลูกค้าสามารถสร้างหรือปรับเปลี่ยนวัตถุโดยใช้ PUT:

PUT /objects/{id} HTTP/1.1
...

{json representation of the object}

{id} เป็น ID อ็อบเจ็กต์ดังนั้นจึงเป็นส่วนหนึ่งของ Request-URI

ตอนนี้ฉันกำลังพิจารณาให้ลูกค้าสร้างวัตถุโดยใช้ POST:

POST /objects/ HTTP/1.1
...

{json representation of the object, including ID}

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


5
ข้อมูล ณ วันที่มิถุนายน 2016 FB ตั้งโจ๋งครึ่ม 200 ในการลงทะเบียนเมื่ออีเมลที่มีอยู่
สีเขียว

4
Github API ส่งคืน 422 เมื่อพยายามสร้างทรัพยากร (ทีม / repo) ด้วยชื่อที่มีการใช้งานแล้ว
Ken

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

คำตอบ:


1055

ความรู้สึกของฉันเป็น409 Conflictสิ่งที่เหมาะสมที่สุด แต่ไม่ค่อยเห็นในป่าแน่นอน:

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

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


11
ทำไมไม่ไปขอ 400 Bad สำหรับฉันนี่ดูเหมือนเป็นข้อผิดพลาดในการตรวจสอบความถูกต้อง (คุณให้ข้อมูลที่ไม่ถูกต้องพร้อมรหัสผิดกฎหมาย)
manuel aldana

314
400 => "การร้องขอไม่สามารถเข้าใจได้โดยเซิร์ฟเวอร์เนื่องจากไวยากรณ์ไม่ถูกต้อง" และเซิร์ฟเวอร์เข้าใจอย่างสมบูรณ์แบบ แต่ไม่สามารถปฏิบัติได้เนื่องจากข้อขัดแย้ง ไม่มีอะไรผิดปกติกับคำขอ & ไวยากรณ์เพียงปัญหาข้อมูล 400 คนในทันทีทำให้ฉันเชื่อว่ากลไกทั้งหมดที่ฉันใช้นั้นมีข้อบกพร่องแทนที่จะเป็นเพียงข้อมูล
Wrikken

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

19
@javajavajavajavajava: ยังคงข้อมูลที่ซ้ำกันไม่ได้เป็น 'ข้อผิดพลาดของลูกค้า' ในใจของฉัน แต่ที่อยู่ในสายตาของคนดูแน่นอน
Wrikken

21
ฉันกลับมาHTTP 409พร้อมกับLocationส่วนหัวที่ชี้ไปยังทรัพยากรที่มีอยู่ / ขัดแย้งกัน
Gili

100

ตามRFC 7231เป็น303 ดูอื่น ๆอาจจะใช้หากผลของการประมวลผลการโพสต์จะเทียบเท่ากับการเป็นตัวแทนของทรัพยากรที่มีอยู่


4
ในความคิดของฉันนี่อาจเป็นคำตอบที่ยอมรับได้ แม้ว่า "อาจจะ" แสดงรายการตัวเลือกสมบูรณ์มันเป็นรหัสการตอบสนองเพียงการแนะนำโดยอย่างเป็นทางการRFC 7231เอกสาร
Nando

16
นี่เป็นคำตอบที่สงบที่สุด
เซท

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

11
ขออภัยฉันกำลังลงคะแนนนี้ HTTP 300s เกี่ยวกับการเปลี่ยนเส้นทางและการเปลี่ยนเส้นทางไปยังวัตถุอื่นซึ่งอาจมีคุณสมบัติแตกต่างกันจะทำให้เข้าใจผิดมาก
Michael Scheper

6
คุณไม่ต้องเสียใจ อย่างไรก็ตามหากการแสดงนั้นเทียบเท่ากับทรัพยากรที่มีอยู่แล้วจะมีคุณสมบัติที่แตกต่างได้อย่างไร และแม้ว่ามันจะมีการเปลี่ยนเส้นทางจะทำให้เข้าใจผิดได้อย่างไร? OP กล่าวว่า: ฉันไม่แน่ใจว่าต้องทำอย่างไรในกรณีที่วัตถุมีอยู่แล้ว อันที่จริงมันเป็นวัตถุ 'เดียวกัน' ทำไมการเปลี่ยนเส้นทางจะทำให้เข้าใจผิด? คุณกำลังพูดถึงวัตถุอื่นซึ่งอยู่ในใจของ OP ไม่ชัดเจน
Nullius

86

422 Unprocessable Entityส่วนตัวผมไปกับส่วนขยายของ WebDAV

อ้างอิงจาก RFC 4918

422 Unprocessable Entityรหัสสถานะหมายความว่าเซิร์ฟเวอร์เข้าใจชนิดเนื้อหาของการร้องขอกิจการ (เพราะฉะนั้น415 Unsupported Media Typeรหัสสถานะที่ไม่เหมาะสม) และไวยากรณ์ของคำขอกิจการที่ถูกต้อง (ดังนั้นจึงเป็น400 Bad Requestรหัสสถานะที่ไม่เหมาะสม) แต่ก็ไม่สามารถที่จะดำเนินการคำแนะนำที่มีอยู่


19
นี่เป็นความคิดที่น่าสนใจและกระตุ้นให้ฉันอ่าน WebDAV RFC ในที่สุด อย่างไรก็ตามฉันคิดว่าความหมายของ 422 คือคำร้องขอและเอนทิตีที่รวมไว้นั้นถูกต้องตามหลักไวยากรณ์ แต่ความหมายไม่สมเหตุสมผล
vmj

4
ในรูปแบบ JSON ไม่ได้เป็นนิติบุคคลที่ถูกต้อง syntactically ดังนั้น422นัดฉันเป็นเลขคี่ ...
awendt

7
ฉันจะไม่ไปกับสิ่งนี้ จาก URL เดียวกันที่อ้างอิงในคำตอบ: "ตัวอย่างเช่นเงื่อนไขข้อผิดพลาดนี้อาจเกิดขึ้นหากเนื้อหาคำขอ XML มีรูปแบบที่ถูกต้อง (เช่นถูกต้องทางไวยากรณ์) แต่คำแนะนำ XML ผิดพลาด" นี่คือความหมายที่แท้จริงของเอนทิตีที่ไม่สามารถประมวลผลได้ซึ่งแตกต่างจากกรณีที่คุณส่งเอนทิตีที่ถูกต้องสมบูรณ์ด้วยไวยากรณ์และซีแมนทิกส์ที่ถูกต้อง แต่ปัญหาเดียวคือมันขัดแย้งกับเอนทิตีที่มีอยู่ ที่จริงแล้วหากซีแมนทิกส์ของเอนทิตีที่ร้องขอไม่ถูกต้องก็ไม่ควรมีเอนทิตีที่มีอยู่เหมือนกันเลย
Tamer Shlash

1
การเพิ่มความคิดเห็น Tamer ถ้าคำขอที่สองมาก่อนมันจะสำเร็จซึ่งจะเป็นไปไม่ได้ถ้าสิ่งนั้นถูกต้องทางอรรถศาสตร์ ดังนั้นในความหมายที่ถูกต้องจะไม่ใช้ที่นี่
Harish

4
@Tamer ทำไมเหรอ? คำสั่ง "Please create object xy" ถูกต้องตามหลักไวยากรณ์ มันถูกต้องเชิงความหมายเฉพาะในกรณีที่เป็นไปได้ในการสร้างวัตถุ xy หาก object xy มีอยู่แล้วจะไม่สามารถสร้างได้อีกต่อไปดังนั้นนี่เป็นข้อผิดพลาดทางความหมาย
Hagen von Eitzen

48

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


หากเซิร์ฟเวอร์เพิ่งทำซ้ำจุดให้ดูที่ 4xx:

  • 400 คำขอไม่ถูกต้อง - เมื่อเซิร์ฟเวอร์จะไม่ประมวลผลคำขอเนื่องจากเป็นความผิดของลูกค้าที่ชัดเจน
  • 409 Conflict - ถ้าเซิร์ฟเวอร์จะไม่ประมวลผลการร้องขอ แต่เหตุผลนั้นไม่ใช่ความผิดของลูกค้า
  • ...

สำหรับการจัดการรายการซ้ำโดยนัยให้ดูที่ 2XX:

  • 200 ตกลง
  • 201 สร้างแล้ว
  • ...

หากเซิร์ฟเวอร์คาดว่าจะส่งคืนบางสิ่งให้ดูที่ 3XX:

  • 302 พบ
  • 303 ดูอื่น ๆ
  • ...

เมื่อเซิร์ฟเวอร์สามารถชี้ทรัพยากรที่มีอยู่มันหมายถึงการเปลี่ยนเส้นทาง


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


2
การร้องขอไม่ได้ทำซ้ำทรัพยากรมันกำลังผนวกข้อมูลเข้ากับหนึ่ง ในความคิดของฉันคุณเป็นคำตอบที่ดีที่สุด
Suncat2000

28

ช้าไปหน่อยอาจจะเป็นเกม แต่ฉันสะดุดปัญหาความหมายในขณะที่พยายามทำ REST API

ในการขยายคำตอบของ Wrikken เล็กน้อยฉันคิดว่าคุณสามารถใช้อย่างใดอย่างหนึ่ง409 Conflictหรือ403 Forbiddenขึ้นอยู่กับสถานการณ์ - ในระยะสั้นใช้ข้อผิดพลาด 403 เมื่อผู้ใช้ไม่สามารถทำอะไรเพื่อแก้ไขข้อขัดแย้งและทำตามคำขอ (เช่นพวกเขาไม่สามารถส่งDELETEขอให้ลบทรัพยากรออกอย่างชัดเจน) หรือใช้ 409 หากมีสิ่งใดที่สามารถทำได้

10.4.4 403 สิ่งต้องห้าม

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

ทุกวันนี้มีคนบอกว่า "403" และปัญหาการอนุญาตหรือการรับรองความถูกต้องอยู่ในใจ แต่สเป็คบอกว่าโดยทั่วไปแล้วเซิร์ฟเวอร์บอกลูกค้าว่ามันจะไม่ทำไม่ต้องถามอีกแล้วนี่คือเหตุผลที่ลูกค้าไม่ควรทำ 'T

สำหรับPUTvs. POST... POSTควรใช้เพื่อสร้างอินสแตนซ์ใหม่ของทรัพยากรเมื่อผู้ใช้ไม่มีวิธีการหรือไม่ควรสร้างตัวระบุสำหรับทรัพยากร PUTจะใช้เมื่อมีการระบุตัวตนของทรัพยากร

9.6 PUT

...

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

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


7
ฉันคิดว่า403 ต้องห้ามหมายความว่าแม้ว่าผู้ใช้จะได้รับการรับรองความถูกต้องแล้วก็ตามเขาไม่ได้รับอนุญาตให้ดำเนินการตามที่ขอ ฉันจะไม่ใช้มันสำหรับข้อผิดพลาดในการตรวจสอบ ตัวอย่าง : ไม่ได้ลงชื่อเข้าใช้ฉันพยายามลบบางสิ่ง เซิร์ฟเวอร์ส่ง401 Unauthorized (ซึ่งเป็นชื่อที่ไม่ดีควรเป็น401 Unauthenticated ) ฉันเข้าสู่ระบบและลองอีกครั้ง ขณะนี้เซิร์ฟเวอร์ตรวจสอบสิทธิ์ของฉันเห็นฉันไม่ได้รับอนุญาตและผลตอบแทนที่403 พระราชวังต้องห้าม ดูคำถามนี้ด้วย
Stijn de Witt

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

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

1
ฉันจะไม่อนุมานว่าข้อผิดพลาด 409 ไม่สามารถส่งคืนได้โดยPOSTแท้จริงแล้วฉันจะอนุมานตรงกันข้ามเพราะ "ความขัดแย้งมีแนวโน้มที่จะเกิดขึ้นในการตอบสนองต่อคำขอ PUT" ดูเหมือนว่าจะระบุว่าวิธีการร้องขออื่น ๆ สามารถใช้รหัสนี้ได้ นอกจากนี้ "เนื้อหาการตอบสนองควรมีข้อมูลเพียงพอสำหรับผู้ใช้ในการรับรู้แหล่งที่มาของความขัดแย้งโดยหลักแล้วเอนทิตีการตอบสนองจะมีข้อมูลที่เพียงพอสำหรับผู้ใช้หรือตัวแทนผู้ใช้เพื่อแก้ไขปัญหาอย่างไรก็ตามอาจไม่สามารถทำได้ไม่ต้องการ " ( webdav.org/specs/rfc2616.html#status.409 )
JWAspin

14

"302 Found" ฟังดูสมเหตุสมผลสำหรับฉัน และRFC 2616บอกว่ามันสามารถตอบได้สำหรับคำขออื่นนอกเหนือจาก GET และ HEAD (และแน่นอนรวมถึง POST)

แต่ยังคงช่วยให้ผู้เข้าชมไปที่ URL นี้เพื่อรับทรัพยากร "พบ" นี้โดย RFC หากต้องการให้ตรงไปที่ URL "พบ" ของจริงคุณควรใช้ "303 ดูอื่น ๆ " ซึ่งเหมาะสม แต่บังคับให้มีการโทรอีกครั้งเพื่อรับ URL ต่อไปนี้ ในแง่ดี GET นี้สามารถแคชได้

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

UPDATE:อีกครั้งหลังจากอ่าน RFC ผมยังคิดว่าinexistent "4XX + 303 พบ" รหัสที่ควรจะเป็นที่ถูกต้อง อย่างไรก็ตาม"409 Conflict" เป็นรหัสคำตอบที่ดีที่สุดที่มีอยู่ (ตามที่ @Wrikken ชี้) ซึ่งอาจรวมถึงส่วนหัว Location ที่ชี้ไปยังทรัพยากรที่มีอยู่


88
สถานะ 3xx นั้นมีไว้สำหรับการเปลี่ยนเส้นทาง
Aviram Netanel

1
"ทรัพยากรที่ร้องขออยู่ชั่วคราวภายใต้ URI อื่น" จากw3.org/Protocols/rfc2616/rfc2616-sec10.html
statueofmike

1
IMHO "การเปลี่ยนเส้นทางชั่วคราว 307" เป็นการเปลี่ยนเส้นทางชั่วคราวจริง "302" ไม่ชัดเจน แต่ "FOUND !!" เป็นข้อความที่ต้องการจริงๆที่นี่ การประนีประนอมที่ดีที่สุดคือ "303 See Other" บนซีแมนทิกส์ HTTP ฉันจะไปกับ "303 See Other"
alanjds

@DavidVartanian Hum ... ฉันไม่เห็นข้อผิดพลาดที่นี่ ลูกค้าส่งคำขอที่ถูกต้อง แต่จะพูดว่า "ขออภัย แต่สิ่งที่คุณพยายามสร้างที่นี่มีอยู่แล้วที่นั่น"? ดูเหมือนว่างานสำหรับ 3xx บางอย่าง ไม่ใช่ 4xx สำหรับฉันเนื่องจากไม่มีข้อผิดพลาดของไคลเอ็นต์
alanjds

1
@DavidVartanian ขอบคุณสำหรับการอภิปราย ปรับปรุงคำตอบต่อ 409 ลูกค้าผิดที่ขอสิ่งที่เป็นไปไม่ได้แม้ว่าจะไม่รู้ว่าเป็นไปไม่ได้ก็ตาม
alanjds

11

ฉันไม่คิดว่าคุณควรทำเช่นนี้

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

ใช้มันเพื่อเพิ่มรายการโดยไม่มีรหัส มันเป็นวิธีปฏิบัติที่ดีที่สุด

หากคุณต้องการจับภาพข้อ จำกัด UNIQUE (ไม่ใช่ id) คุณสามารถตอบกลับ 409 ได้เหมือนที่คุณทำได้ในคำขอ PUT แต่ไม่ใช่รหัส


สิ่งที่เกี่ยวกับวัตถุที่มีความสัมพันธ์ตารางเข้าร่วม? สมมติว่าเรามีบัญชีผลิตภัณฑ์และ account_product เป็นตารางฐานข้อมูล ฉันต้องการเพิ่มผลิตภัณฑ์ลงในบัญชีดังนั้นฉันจึงต้องการโพสต์ไปยัง / account / {id} / ผลิตภัณฑ์ด้วย product_id หากได้รับอนุญาตความสัมพันธ์ผลิตภัณฑ์บัญชีเดียวเท่านั้นฉันควรส่งคืนอะไร
partkyle

2
ลืมตารางฐานข้อมูล สมมติว่าผลิตภัณฑ์สามารถเกี่ยวข้องกับบัญชีได้เท่านั้น ... จากนั้นเป็นความสัมพันธ์แบบหนึ่งต่อหลาย ดังนั้น POST / product / {id} ด้วย {'บัญชี': account_id} หากคุณตั้งค่าความสำคัญสูงสุดให้เป็น '1' (ความสัมพันธ์แบบหนึ่งต่อหนึ่ง) .... ทำไมพวกเขาจึงแยกวัตถุส่วนที่เหลือออก? ข้อผิดพลาดของ cardinality จะเป็นเพียง 400 err ง่าย ๆ เข้าไว้. ฉันหวังว่าฉันเข้าใจคำถามของคุณ
Alfonso Tienda

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

@partkyle หยุดใช้ PKs เป็นรหัสสาธารณะ !!
Sinaesthetic

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

9

ฉันจะไปกับ422 Unprocessable Entityซึ่งจะใช้เมื่อคำขอไม่ถูกต้อง แต่ปัญหาไม่ได้อยู่ในไวยากรณ์หรือการตรวจสอบ

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

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

สำหรับเร็กคอร์ด 422 ยังเป็นรหัสสถานะที่ GitHub ใช้เมื่อคุณพยายามสร้างที่เก็บด้วยชื่อที่ใช้งานแล้ว


422 เป็นข้อมูลจำเพาะของ webdav ดังนั้นฉันจะไม่แนะนำให้ใช้สิ่งนี้สำหรับ REST API
rwenz3l

7

ฉันคิดว่าสำหรับ REST คุณเพียงแค่ต้องตัดสินใจเกี่ยวกับพฤติกรรมของระบบนั้นในกรณีนี้ฉันคิดว่าคำตอบที่ "ถูกต้อง" จะเป็นหนึ่งในสองคำตอบที่ได้รับจากที่นี่ หากคุณต้องการให้คำขอหยุดและทำงานราวกับว่าลูกค้าทำผิดพลาดที่ต้องแก้ไขก่อนดำเนินการต่อให้ใช้ 409 ถ้าความขัดแย้งนั้นไม่สำคัญจริง ๆ และต้องการให้คำขอดำเนินต่อไปให้ตอบกลับด้วยการเปลี่ยนเส้นทาง ลูกค้าไปยังเอนทิตีที่พบ ฉันคิดว่า REST APIs ที่เหมาะสมควรเปลี่ยนเส้นทาง (หรืออย่างน้อยก็ให้ส่วนหัวของตำแหน่ง) ไปยัง GET endpoint สำหรับทรัพยากรนั้นตาม POST ต่อไปดังนั้นพฤติกรรมนี้จะให้ประสบการณ์ที่สอดคล้องกัน

แก้ไข: นอกจากนี้ยังเป็นที่น่าสังเกตว่าคุณควรพิจารณา PUT เนื่องจากคุณระบุ ID พฤติกรรมนั้นเรียบง่าย: "ฉันไม่สนใจสิ่งที่อยู่ในตอนนี้ ความหมายหากไม่มีสิ่งใดอยู่ในนั้นมันจะถูกสร้างขึ้น หากมีสิ่งนั้นจะถูกแทนที่ ฉันคิดว่า POST เหมาะสมกว่าเมื่อเซิร์ฟเวอร์จัดการ ID นั้น การแยกแนวคิดทั้งสองโดยทั่วไปจะบอกวิธีจัดการกับมัน (เช่น PUT คือ idempotent ดังนั้นควรทำงานตราบใดที่ payload ตรวจสอบแล้ว POST จะสร้างเสมอดังนั้นหากมีการชนกันของรหัส 409 จะอธิบายความขัดแย้งนั้น) .


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

IMO ที่เป็นปัญหา หากคุณโพสต์ถึง / ผู้ใช้ทรัพยากรคือชุดสะสมแทนบันทึกส่วนตัว / ผู้ใช้ / {id}
Sinaesthetic

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

ฉันทำเช่นเดียวกับข้อเสนอแนะของคุณเพื่อใช้PUTแม้ว่า
Grant Gryczan

4

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

PATCH จะแก้ปัญหาโดยอนุญาตให้คุณอัปเดตรายการที่มีอยู่แล้ว ดู: RFC 5789: PATCH


2
Patch เหมือน PUT แต่ไม่ใช่การทดแทนที่สมบูรณ์ มันถูกใช้เพื่อแก้ไขชิ้นส่วนของทรัพยากรเช่นการเพิ่มการลบหรือการแก้ไของค์ประกอบเดียวของทรัพยากรแทนการแทนที่โดยรวม
Sinaesthetic

4

ทำไมไม่ได้เป็น202 ได้รับการยอมรับ ? มันเป็นคำขอตกลง (200s) ไม่มีข้อผิดพลาดของลูกค้า (400s) ต่อ se

จาก10 นิยามรหัสสถานะ :

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

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

ฉันกำลังโน้มน้าวการขว้าง 202 และส่งคืนเนื้อหาที่คล้ายกันกับสิ่งที่ GET /{resource}/{id}จะได้รับคืน


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

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

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

ไม่มีความรู้สึกในการพูดกับลูกค้าว่าคำขอได้รับการยอมรับเพราะคุณรู้อยู่แล้วว่ามันไม่ได้เป็น!
lucastamoios

1
@ เอเดรียและ lucastamoios ฉันคิดว่าคุณทั้งคู่สมมติว่าเซิร์ฟเวอร์อ่านจากฐานข้อมูลพร้อมกันก่อนที่จะตอบสนอง นี่ไม่ใช่กรณีเสมอดังนั้นคำตอบนี้ไม่ "ผิด" เนื่องจากเซิร์ฟเวอร์ไม่ "รู้" เกี่ยวกับระเบียนที่มีอยู่เสมอ นี่เป็นกรณีที่เกิดขึ้นอย่างมากในระบบอะซิงโครนัสซึ่งชั้น api เพียงแค่บันทึกคำขอสำหรับการประมวลผลโดยผู้ทำงานเบื้องหลัง
gsaslis

2

สะดุดกับคำถามนี้ในขณะที่ตรวจสอบรหัสที่ถูกต้องสำหรับการบันทึกที่ซ้ำกัน

ให้อภัยความไม่รู้ของฉัน แต่ฉันไม่เข้าใจว่าทำไมทุกคนละเว้นรหัส "300" ซึ่งระบุว่า "ตัวเลือกหลายตัว" หรือ "คลุมเครือ" อย่างชัดเจน

ในความคิดของฉันนี้จะเป็นรหัสที่สมบูรณ์แบบสำหรับการสร้างที่ไม่ได้มาตรฐานหรือระบบเฉพาะสำหรับการใช้งานของคุณเอง ฉันอาจผิดเช่นกัน!

https://tools.ietf.org/html/rfc7231#section-6.4.1


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

ลูกค้ากำลังพูดว่า "สร้างสิ่งนี้" และเซิร์ฟเวอร์กำลังตอบกลับโดยพูดว่า "ไปที่นี่แทน" บทสนทนาไม่สมเหตุสมผล เกือบราวกับว่าเซิร์ฟเวอร์กำลังบอกให้ลูกค้า "โพสต์ไปยังตำแหน่งนี้แทน" 300s เป็นคำตอบที่เหมาะสมยิ่งขึ้นต่อคำขอ GET หรือ POST ในกรณีที่เซิร์ฟเวอร์ตอบกลับด้วย "ตกลงฉันสร้างขึ้นมาแล้วและอยู่ที่นี่" ..
Sinaesthetic

2

มีโอกาสมากขึ้นก็คือ 400 Bad Request

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


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

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


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

1

แล้วประมาณ 208 - http://httpstatusdogs.com/208-already-reportedล่ะ นั่นคือตัวเลือกหรือไม่?

ในความคิดของฉันถ้าสิ่งเดียวคือทรัพยากรซ้ำไม่ควรมีข้อผิดพลาด ท้ายที่สุดไม่มีข้อผิดพลาดทั้งในฝั่งไคลเอ็นต์หรือเซิร์ฟเวอร์


ไม่มีตัวเลือกเนื่องจากคุณต้องการผนวกรายการที่ ID นั้นมีอยู่แล้ว ดังนั้นคุณพยายามที่จะเพิ่มอะไรบางอย่าง แต่นี่มีอยู่แล้ว ตกลงจะใช้เฉพาะเมื่อชุดข้อมูลนั้นโตขึ้น ผนวก Something -> ตกลงฉันไม่มีการต่อท้ายอะไร ไม่พอดีฉันเดา
Martin Kersten

อย่างที่ฉันพูดฉันไม่ได้คิดว่านี่เป็นข้อผิดพลาด แต่ฉันเห็นจุดของ @martin
Fernando Ferreira

หากไม่สามารถสร้างทรัพยากรได้สำเร็จแสดงว่ามีข้อผิดพลาดเกิดขึ้น
Grant Gryczan

POST ยังใช้สำหรับการต่อท้ายข้อมูล นี่คือโดยความหมาย , ไม่ใช่ข้อผิดพลาด
Suncat2000

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