สร้างคำขอด้วย POST ซึ่งรหัสตอบกลับ 200 หรือ 201 และเนื้อหา


125

สมมติว่าฉันเขียนบริการ REST ซึ่งมีจุดประสงค์เพื่อเพิ่มรายการข้อมูลใหม่ให้กับระบบ

ฉันวางแผนที่จะโพสต์ถึง

http://myhost/serviceX/someResources

สมมติว่าได้ผลฉันควรใช้รหัสตอบกลับอะไร และฉันจะคืนเนื้อหาอะไร

ฉันกำลังดูคำจำกัดความของรหัสตอบกลับ HTTP และดูความเป็นไปได้เหล่านี้:

200: ส่งคืนเอนทิตีที่อธิบายหรือมีผลลัพธ์ของการกระทำ

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

อันหลังฟังดูสอดคล้องกับข้อมูลจำเพาะ Http มากขึ้น แต่ฉันไม่ชัดเจนว่าอะไร

คำตอบควรรวมถึงเอนทิตีที่มีรายการลักษณะทรัพยากรและตำแหน่งที่ตั้ง

วิธี

ข้อเสนอแนะ? การตีความ?

คำตอบ:


78

แนวคิดก็คือเนื้อหาตอบกลับจะแสดงหน้าเว็บที่เชื่อมโยงคุณไปยังสิ่งนั้น:

201 สร้าง

รหัสสถานะ 201 (สร้างแล้ว) ระบุว่าคำขอได้รับการตอบสนองและส่งผลให้มีการสร้างทรัพยากรใหม่อย่างน้อยหนึ่งรายการ ทรัพยากรหลักที่สร้างขึ้นโดยการร้องขอถูกระบุโดยฟิลด์ส่วนหัวตำแหน่งในการตอบกลับหรือหากไม่ได้รับฟิลด์ตำแหน่งโดย URI คำขอที่มีประสิทธิภาพ

ซึ่งหมายความว่าคุณจะรวมถึงLocationในการตอบสนองส่วนหัวที่ให้ URL ของที่คุณสามารถหาที่สร้างขึ้นใหม่สิ่งที่ :

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597

ร่างกายตอบสนอง

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

โดยทั่วไปส่วนข้อมูลการตอบสนอง 201 จะอธิบายและเชื่อมโยงไปยังทรัพยากรที่สร้างขึ้น

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

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: text/html

Your answer has been saved! 
Click <A href="https://stackoverflow.com/a/36373586/12597">here</A> to view it.

หากหุ่นยนต์ใช้เพจเท่านั้นสิ่งที่ควรตอบคือคอมพิวเตอร์สามารถอ่านได้:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/xml

<createdResources>
   <questionID>1860645</questionID>
   <answerID>36373586</answerID>
   <primary>/a/36373586/12597</primary>
   <additional>
      <resource>http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586</resource>
      <resource>http://stackoverflow.com/a/1962757/12597</resource>
   </additional>
</createdResource>

หรือหากคุณต้องการ:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/json

{ 
   "questionID": 1860645, 
   "answerID": 36373586,
   "primary": "/a/36373586/12597",
   "additional": [
      "http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586",
      "http://stackoverflow.com/a/36373586/12597"
   ]
}

คำตอบขึ้นอยู่กับคุณทั้งหมด เป็นสิ่งที่คุณต้องการโดยพลการ

แคชเป็นมิตร

ในที่สุดก็มีการเพิ่มประสิทธิภาพที่ฉันสามารถแคชทรัพยากรที่สร้างไว้ล่วงหน้าได้ (เนื่องจากฉันมีเนื้อหาอยู่แล้วฉันเพิ่งอัปโหลด) เซิร์ฟเวอร์สามารถส่งคืนวันที่หรือ ETag ซึ่งฉันสามารถจัดเก็บพร้อมกับเนื้อหาที่ฉันเพิ่งอัปโหลด:

ดูหัวข้อ 7.2สำหรับการอภิปรายเกี่ยวกับความหมายและวัตถุประสงค์ของฟิลด์ส่วนหัวของ validator เช่น ETag และ Last-Modified ในคำตอบ 201

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/23704283/12597
Content-Type: text/html
ETag: JF2CA53BOMQGU5LTOQQGC3RAMV4GC3LQNRSS4
Last-Modified: Sat, 02 Apr 2016 12:22:39 GMT 

Your answer has been saved! 
Click <A href="https://stackoverflow.com/a/36373586/12597">here</A> to view it.

และETags เป็นค่าโดยพลการล้วนๆ การทำให้ทรัพยากรแตกต่างกันเมื่อทรัพยากรมีการเปลี่ยนแปลง (และจำเป็นต้องอัปเดตแคช) เป็นเรื่องสำคัญ ETag มักจะเป็นแฮช (เช่น SHA2) แต่อาจเป็นฐานข้อมูลrowversionหรือหมายเลขการแก้ไขที่เพิ่มขึ้น อะไรก็ตามที่จะเปลี่ยนไปเมื่อสิ่งนั้นเปลี่ยนไป


จนถึงตอนนี้คำตอบของคุณดูเหมือนจะสมเหตุสมผลที่สุด ฉันกังวลเล็กน้อยเกี่ยวกับภววิทยาของการตอบสนอง แต่นอกเหนือจากนั้นดูเหมือนว่าเป็นการตีความข้อมูลจำเพาะที่เป็นผู้ใหญ่ที่สุด ฉันอยากรู้ว่ามีวิธี "ตอบสนอง" ที่มีน้ำหนักเบาในการจัดการกับเอาต์พุตของมนุษย์ / เครื่องจักร แต่ส่วนใหญ่ฉันรู้สึกทึ่งกับคำแนะนำ "แคชข้อมูลที่คุณป้อนเอง" เว็บแอปส่วนใหญ่ที่ฉันรู้จักจะไม่สร้างทรัพยากรในเวอร์ชัน 1: 1 แม้ว่าจะเป็นเรื่องเล็กน้อยเช่นการทำให้สตริงเป็นตัวพิมพ์ใหญ่ ไม่ใช่เรื่องยากที่จะปฏิบัติต่อเวอร์ชันที่คุณส่งมาเป็นเวอร์ชันที่ etag ถูกสร้างขึ้นหรือไม่?
Anthony

1
@ Anthony การแคช: อาจเป็นแอปพลิเคชั่นจัดเก็บไฟล์ประเภท 1: 1 เปรียบเทียบเช่น WebDAV PUT & POST ไฟล์ขนาดใหญ่ที่ต้องจัดการ
kxr

@ แอนโธนี่ขึ้นอยู่กับคุณว่าคุณต้องการส่งคืน ETag กลับไปยังลูกค้า หากเนื้อหาที่ไคลเอนต์เพิ่งอัปโหลดไม่ใช่สิ่งที่คุณบันทึกไว้อย่าส่งคืน ETag เป็นความยืดหยุ่นและทางเลือกของคุณ
Ian Boyd

เหตุใดคำตอบของคุณจึงไม่มีความยาวของเนื้อหา
Vinnie Falco

1
@VinnieFalco นี่คือคำตอบเกี่ยวกับรหัสตอบกลับ 201 ความยาวของเนื้อหาถูกขจัดออกไปเพื่อวัตถุประสงค์ในการเปิดเผยข้อมูล
Ian Boyd

91

ฉันคิดว่าatompub REST APIเป็นตัวอย่างที่ดีของบริการพักผ่อน ดูตัวอย่างด้านล่างจากข้อมูลจำเพาะ atompub:

POST /edit/ HTTP/1.1
Host: example.org
User-Agent: Thingio/1.0
Authorization: Basic ZGFmZnk6c2VjZXJldA==
Content-Type: application/atom+xml;type=entry
Content-Length: nnn
Slug: First Post

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <title>Atom-Powered Robots Run Amok</title>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2003-12-13T18:30:02Z</updated>
  <author><name>John Doe</name></author>
  <content>Some text.</content>
</entry>

เซิร์ฟเวอร์ส่งสัญญาณการสร้างที่สำเร็จด้วยรหัสสถานะ 201 การตอบสนองรวมถึงส่วนหัวตำแหน่งที่ระบุ URI รายการสมาชิกของรายการ Atom และการแสดงรายการนั้นในเนื้อหาของการตอบสนอง

HTTP/1.1 201 Created
Date: Fri, 7 Oct 2005 17:17:11 GMT
Content-Length: nnn
Content-Type: application/atom+xml;type=entry;charset="utf-8"
Location: http://example.org/edit/first-post.atom
ETag: "c180de84f991g8"  

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <title>Atom-Powered Robots Run Amok</title>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2003-12-13T18:30:02Z</updated>
  <author><name>John Doe</name></author>
  <content>Some text.</content>
  <link rel="edit"
      href="http://example.org/edit/first-post.atom"/>
</entry>

รายการที่สร้างและส่งคืนโดยคอลเลกชันอาจไม่ตรงกับรายการที่โพสต์โดยไคลเอนต์ เซิร์ฟเวอร์อาจเปลี่ยนค่าขององค์ประกอบต่างๆใน Entry เช่น atom: id, atom: updated และ atom: author values ​​และอาจเลือกที่จะลบหรือเพิ่มองค์ประกอบและแอตทริบิวต์อื่น ๆ หรือเปลี่ยนเนื้อหาองค์ประกอบและค่าแอตทริบิวต์


9
การส่งคืนทรัพยากรที่สร้างขึ้นอาจจะมากไปหน่อยหากทรัพยากรอยู่ในขนาดกิกะไบต์ ...
Tor Valamo

10
ตกลงกัน! นั่นคือการเพิ่มประสิทธิภาพตามความจำเป็น - แต่คุณไม่ต้องการทำก่อนเวลาอันควร สิ่งสำคัญคือต้องออกแบบในวิญญาณที่สงบสุขและให้ข้อยกเว้นเฉพาะเมื่อจำเป็นเท่านั้น
Chandra Patni

3
@ChandraPatni, Atom ตาย ต้องการตัวอย่างที่ดีกว่า
Pacerier

16
Atom อาจตายไปแล้ว แต่จิตวิญญาณของตัวอย่างยังคงอยู่
Ashimema

2
การตีความเดิมของฉันเกี่ยวกับการตอบกลับ 201 เป็นแบบ "เดี๋ยวก่อนคุณต้องการสร้างทรัพยากร แต่คุณไม่ได้สนใจผลลัพธ์สุดท้ายหรือมีสิทธิ์เขียน แต่ไม่มีสิทธิ์อ่านทรัพยากรนี้ในทั้งสองอย่าง สิ่งที่คุณต้องมีก่อนกลับไปที่คอลเล็กชันหลักคือ URL ของทรัพยากรที่สร้างขึ้นเพื่อเป็นหลักฐานว่าถูกสร้างขึ้น " สิ่งที่เกินกว่านั้นดูเหมือนจะเป็นการตอบสนอง 200 ครั้ง เว้นแต่ RFC จะมีอย่างอื่นอยู่ในใจ
Anthony

50

พูดไม่กี่คำ:

  • 200เมื่อวัตถุถูกสร้างและส่งคืน
  • 201เมื่อออบเจ็กต์ถูกสร้างขึ้น แต่จะส่งคืนเฉพาะการอ้างอิงเท่านั้น (เช่น ID หรือลิงค์)

ที่มานี้?
sudo soul

3
นี่คือสิ่งที่ฉันเข้าใจจากw3.org/Protocols/rfc2616/rfc2616-sec10.htmlและhttpstatuses.com/201
Stéphane Bruckert

3
หลังจากอ่านtools.ietf.org/html/rfc7231#section-6.3.1ฉันเห็นด้วยกับความเข้าใจนี้ - ฉันคิดว่าฉันกำลังถามเพิ่มเติมว่าคุณมาถึงมันได้อย่างไร แต่ตอนนี้ในความเข้าใจของฉัน ... 200 = ทรัพยากรที่สร้างและส่งคืน | 201 = ทรัพยากรที่สร้างและส่งคืนการอ้างอิง | 204 = ทรัพยากรที่สร้างขึ้นและไม่มีการส่งคืนข้อมูล
sudo soul

34

ตรวจสอบhttp: วิธีนิยาม: โพสต์

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

ถ้าทรัพยากรถูกสร้างขึ้นบนเซิร์ฟเวอร์ต้นทางการตอบสนองควรเป็น 201 (สร้าง) และมีเอนทิตีที่อธิบายสถานะของคำขอและอ้างถึงทรัพยากรใหม่และส่วนหัวตำแหน่ง (ดูหัวข้อ 14.30)


18

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19

เป็นเพียงคีย์ - ค่าที่คั่นด้วยเครื่องหมายโคลอน

ETag: "xyzzy"

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

ETag: "{ id: 1234, uri: 'http://domain.com/comments/1234', type: 'comment' }"

ในตัวอย่างนี้ตัวระบุ uri และประเภทของรายการที่สร้างคือ "ลักษณะทรัพยากรและตำแหน่ง"


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

"รายการลักษณะทรัพยากรและตำแหน่งที่ตั้ง" จะเป็นเนื้อหาของโครงสร้างข้อมูลที่มีให้ การใช้งานที่เข้มงวดมากขึ้นคือโครงสร้าง JSON รวมทรัพยากร uri และอาจเป็นประเภทของทรัพยากรที่สร้างขึ้น ฉันจะปรับคำตอบตามนี้
ชั่วคราว

7
ระบุประเด็นเพื่อให้ผู้คนได้เรียนรู้ มิฉะนั้นความคิดเห็นเป็นเพียงการโบกมือ
ชั่วคราว

@SimonGibbs ประเด็นอะไร?
MEMark

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

1

ผลลัพธ์ขึ้นอยู่กับชนิดเนื้อหาที่ร้องขอ อย่างไรก็ตามอย่างน้อยที่สุดคุณควรใส่ทรัพยากรที่สร้างขึ้นใน Location เช่นเดียวกับรูปแบบ Post-Redirect-Get

ในกรณีของฉันฉันปล่อยว่างไว้จนกว่าจะมีการร้องขอเป็นอย่างอื่น เนื่องจากนั่นคือลักษณะการทำงานของ JAX-RS เมื่อใช้ Response.created ()

อย่างไรก็ตามโปรดทราบว่าเบราว์เซอร์และเฟรมเวิร์กเช่น Angular ไม่เป็นไปตาม 201 โดยอัตโนมัติ ฉันได้สังเกตพฤติกรรมในhttp://www.trajano.net/2013/05/201-created-with-angular-resource/


-2

คำตอบอื่นที่ฉันต้องการสำหรับสิ่งนี้คือใช้แนวทางปฏิบัติและรักษาสัญญา REST APIของคุณให้เรียบง่าย ในกรณีของฉันฉันได้ปรับโครงสร้าง REST API ของฉันใหม่เพื่อให้สามารถทดสอบสิ่งต่าง ๆ ได้มากขึ้นโดยไม่ต้องใช้ JavaScript หรือ XHR เพียงแค่รูปแบบ HTML ธรรมดาและลิงก์

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

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

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