REST endpoint เพื่อแสดงตัวอย่างก่อน POSTing


17

ฉันออกแบบเว็บแอปพลิเคชั่นใหม่ซึ่งขับเคลื่อนโดยแบ็กเอนด์ REST และส่วนหน้า HTML + JS

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

POST /api/config BODY {config: ....}

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

สิ่งแรกที่ฉันคิดเกี่ยวกับการทำให้จุดสิ้นสุดGETสำหรับการแสดงตัวอย่างส่งเนื้อความของสถานะใหม่ของเอนทิตี ทางนี้:

GET /api/preview/items BODY {config: ....}

อาจแสดงสถานะใหม่สำหรับรายการที่มีการกำหนดค่าใหม่

GET /api/preview/sales BODY {config: ....}

อาจแสดงสถานะใหม่สำหรับการขายด้วยการกำหนดค่าใหม่

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

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

POST /api/preview/config BODY {config: ....}

GET /api/preview/items?idPreviewConfig=1

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

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

แต่การเปลี่ยนแปลงหมายถึงอะไร มันเปลี่ยนชุดเอนทิตีที่ส่งคืนหรือไม่ มันเปลี่ยนโครงสร้างที่ส่งคืนหรือไม่
Andy

จริงๆแล้วมันเปลี่ยนค่าสำหรับitemsและsales(ไม่ใช่โครงสร้าง) ขึ้นอยู่กับการตั้งค่าที่คุณโพสต์
Xtreme Biker คืนสถานะโมนิก้า

และการกำหนดค่ามีขนาดเท่าใด สามารถปลูกได้หลายร้อยกิโลไบท์หรือมากกว่านี้?
Andy

คำตอบ:


27

นี่เป็นโดเมนเฉพาะเกินไปที่จะมีการสนับสนุนดั้งเดิมใน HTTP

คุณสามารถทำสิ่งใดสิ่งหนึ่งต่อไปนี้แทน

  1. POST /api/config/previewมี ที่ฝั่งเซิร์ฟเวอร์แอปพลิเคชันจะรู้ว่าไม่ควรแก้ไขการกำหนดค่าจริง แต่รวมสิ่งที่เกิดขึ้นจริงกับที่คุณโพสต์และส่งกลับผลลัพธ์ที่ระบุว่ามีการเปลี่ยนแปลงอย่างไร

    ในภายหลังหากผู้ใช้พอใจกับผลลัพธ์เธอจะดำเนินการPOST /api/configกับส่วนของข้อมูลเดียวกันกับในคำขอก่อนหน้า สิ่งนี้จะเขียนทับการกำหนดค่าอย่างมีประสิทธิภาพ

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

    ข้อเสียคือเมื่อร่างกายมีขนาดใหญ่ก็หมายความว่ามันจะต้องส่งไปยังเซิร์ฟเวอร์สองครั้ง หากเป็นกรณีของคุณคุณอาจใช้วิธีการถัดไป

  2. มีสิ่งPOST /api/config/prepareที่จำสิ่งที่ถูกส่งไปในบันทึกชั่วคราวและส่งกลับสองสิ่ง: ID ของบันทึกชั่วคราว (เช่น12345) และตัวอย่างของการเปลี่ยนแปลง

    หากผู้ใช้พอใจกับผลลัพธ์เธอจะดำเนินการPOST /api/config/commit/12345เพื่อเก็บการเปลี่ยนแปลงอย่างชัดเจน หากไม่ได้บันทึกชั่วคราวอาจถูกเก็บไว้เป็นระยะเวลาหนึ่งแล้วจึงยกเลิกงาน cron

    ประโยชน์คือว่าที่นี่อีกครั้งคุณอาจจะPOST /api/configยังคงเหมือนเดิมและลูกค้าที่ไม่ต้องการตัวอย่างจะไม่แตก

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

  3. ย้ายตรรกะการแสดงตัวอย่างทางฝั่งไคลเอ็นต์


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

1
@marstato: โดยส่วนตัวแล้วฉันไม่ชอบ HTTP header สำหรับการใช้งานนี้เป็นพิเศษ แม้ว่ามันอาจสมเหตุสมผลสำหรับคนอื่น แต่ฉันก็สบายดีถ้าคุณแก้ไขคำตอบของฉัน โปรดทราบว่าคุณสามารถโพสต์คำตอบของคุณเองซึ่งจะอนุญาตให้ผู้อื่นอัปโหลดได้ (และจะได้รับคะแนนชื่อเสียง)
Arseni Mourzenko

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

1
@PedroWerneck คุณสามารถขยายได้ไหม? สำหรับฉันแล้วดูเหมือนว่าตัวเลือก 2 จะกำหนดเอนทิตีอื่น (ร่างแบบร่าง) และให้วิธีการที่จะโต้ตอบกับพวกเขา
แอนดรูพูดว่า Reinstate Monica

1
@PedroWerneck มันเป็นสถานะในลักษณะเดียวกับการจัดเก็บการกำหนดค่าบนเซิร์ฟเวอร์เป็นสถานะ ดังนั้นแอปพลิเคชั่นจึงมีมุมมองของคุณอยู่แล้วและมีตัวเลือกทั้งหมดเพื่อเพิ่มฟีเจอร์นี้
jpmc26

10

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

การใช้ GET ในกรณีนี้ดูเหมือนจะขัดแย้งกับทั้งสองอย่าง

A. ลูกค้าต้องรวมเนื้อหากับ GET หรือไม่? ไม่คาดฝัน

B. เซิร์ฟเวอร์คืนการตอบสนองที่แตกต่างกันไปขึ้นอยู่กับเนื้อความ แบ่งข้อมูลจำเพาะและกลไกการแคช

หากคุณกำลังดิ้นรนกับคำถามสงบเงียบกฎของฉันคือถามตัวเอง

"วิธีนี้ดีกว่าการใช้ POST สำหรับทุกสิ่ง"

หากไม่มีประโยชน์ทันทีและชัดเจนให้ใช้กลยุทธ์ Just Use POST Stupid (JUPS)


ฮ่าฮ่าฮ่าจับได้ดี
Xtreme Biker คืนสถานะโมนิก้า

@Ewan ... ไม่ว่ามันจะเป็นวิธีปฏิบัติหรือไม่ก็ตาม ... หากคุณใช้ POST สำหรับทุกสิ่งคุณควรสังเกตว่ามันไม่ได้สงบจริง ๆ
Allen

1
ดีเว้นแต่ POST เป็นตัวเลือกที่เหมาะสมสำหรับวิธีการทั้งหมดของคุณ และมันก็ไม่เหมือนว่ามีกฎเกณฑ์ที่คุณสามารถนำไปใช้ได้เราจะเถียงว่าการตีความเชิงอัตวิสัยของเรามีอะไรมากกว่าแนวปฏิบัติเล็กน้อย
Ewan

6

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

POST /api/config HTTP/1.1
Host: api.mysite.com
Content-Type: application/json
Persistence-Options: simulate

{
   "config": {
      "key": "value"
   }
}

ซึ่งเซิร์ฟเวอร์สามารถตอบสนอง:

HTTP/1.1 200 OK
Persistence-Options: simulated
Content-Type: application/json

-- preview --

โปรดทราบว่าหากคุณใช้หน่วยงานตาม O / RM และ / หรือธุรกรรมตามคำขอกับฐานข้อมูลของคุณคุณสามารถใช้ฟังก์ชั่นนี้ได้อย่างง่ายดายสำหรับปลายทางทั้งหมดของคุณโดยไม่ต้องทำงานบนปลายทางเฉพาะใด ๆ : หากคำขอมาพร้อมกับตัวเลือกนั้น ย้อนกลับธุรกรรม / หน่วยของการทำงานแทนการยอมรับ



@PeterRader จุดดีเอาออกX-
marstato

ยินดีต้อนรับ. คุณจะบอกได้หรือไม่ว่าเอนทิตีภายใต้การจำลองควรถูกแสดงเป็น "ภายใต้การจำลอง"
Peter Rader

ไม่มี นั่นคือจุดของการจำลองใช่มั้ย ค่าส่วนหัวอาจเป็นได้noneแต่สำหรับรสนิยมของฉัน - ขัดแย้งกับลักษณะของPOSTวิธีการมากเกินไป
marstato

2

ฉันขอแนะนำให้ปฏิบัติเช่นนี้กับคุณในการค้นหา ฉันจะตั้งค่าจุดสิ้นสุด POST ที่/api/config/previewสร้างตัวอย่างใหม่ จากนั้นฉันจะตั้งค่าจุดปลาย PUT หรือ PATCH ที่api/configขึ้นอยู่กับว่าคุณต้องการแก้ไขการกำหนดค่าปัจจุบันหรือเพียงแค่แทนที่การตั้งค่าทั้งหมด (สมมุติว่าในกรณีก่อนหน้านี้คุณจะส่งภาพตัวอย่างที่คุณเพิ่งสร้างขึ้น)


0

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

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


0

RFC6648เลิกสร้างใหม่X-ดังนั้นฉันต้องลงคะแนนให้กับแนวคิดเพื่อส่งฟิลด์ส่วนหัวใหม่ REST เป็นสไตล์สถาปัตยกรรมสิ่งที่เราพูดถึงคือ RESTful - แต่ให้เพิกเฉยต่อสิ่งนั้นในขณะนี้

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

GET  /api/emulation - 200 OK {first:1, last:123}
POST /api/emulation/124 - 200 OK
GET  /api/emulation/124/config - 200 OK {config:{tax:8}}
PUT  /api/emulation/124/config {config:{tax:16}} - 200 OK {config:{tax:16}}
GET  /api/emulation/124/items - 200 OK [first:1, last: 3000]
GET  /api/emulation/124/items/1 - 200 OK {price:1.79, name:'Cup'}
--- show emulation ---
--- commit emulation ---
PUT /api/config {config:{tax:16}}
DELETE /api/emulation/124 - 200 OK

มีวิธีอื่น .... คุณอาจสังเกตเห็นว่ามีคำขอจำนวนมากจาก HTML / JavaScript-client อาจสร้างคำขอมากเกินไปสิ่งที่ถึงขีด จำกัด ของคำขอประมาณ 17 ในเวลาเดียวกัน (ดูที่หน้านี้ ) คุณสามารถสลับการใช้งาน REST และแทนการส่งมอบออบเจ็กต์สถานะ lame ที่คุณสามารถส่งมอบเพจรัฐเฉพาะที่หลากหลาย ตัวอย่าง:

GET /user/123/config - 200 OK {user:'Tim', date:3298347239847, currentItem:123, 
                  roles:['Admin','Customer'], config:{tax:16}, unsavedChanges:true, ...}

ขอแสดงความนับถือ

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