มีปัญหากับการใช้วิธี HTTP แบบกำหนดเองหรือไม่?


34

เรามี URL ในรูปแบบดังต่อไปนี้

/ อินสแตนซ์ / {instanceType} / {} InstanceID

คุณสามารถเรียกมันได้ด้วยวิธี HTTP มาตรฐาน: POST, GET, DELETE, PUT อย่างไรก็ตามมีการกระทำอีกสองสามอย่างที่เราดำเนินการเช่น "บันทึกเป็นแบบร่าง" หรือ "Curate"

เราคิดว่าเราสามารถใช้วิธี HTTP แบบกำหนดเองเช่น: DRAFT, VALIDATE, CURATE

ฉันคิดว่านี่เป็นสิ่งที่ยอมรับได้เพราะมาตรฐานบอกว่า

"ชุดวิธีการทั่วไปสำหรับ HTTP / 1.1 ถูกกำหนดไว้ด้านล่างแม้ว่าชุดนี้สามารถขยายได้ แต่วิธีการเพิ่มเติมไม่สามารถสันนิษฐานได้ว่าจะใช้ความหมายเดียวกันสำหรับไคลเอนต์และเซิร์ฟเวอร์แยกกัน"

และเครื่องมือเช่น WebDav สร้างส่วนขยายของตัวเอง

มีปัญหาที่บางคนใช้กับวิธีการที่กำหนดเองหรือไม่? ฉันกำลังคิดถึงพร็อกซีเซิร์ฟเวอร์และไฟร์วอลล์ แต่ยินดีต้อนรับประเด็นอื่น ๆ ฉันควรอยู่อย่างปลอดภัยและมีพารามิเตอร์ URL เช่น action = validate | curate | ฉบับร่างหรือไม่


6
ดังที่ฉันอ้างจากRFC 1925อีกครั้ง - "ในการออกแบบโพรโทคอลความสมบูรณ์แบบไม่ได้มาถึงเมื่อไม่มีอะไรเหลือให้เพิ่ม - หากใช้งานได้ไม่มีเหตุผลที่จะเพิ่มใน http

4
ไม่มีอะไรผิดปกติตราบใดที่คุณรู้ว่าตอนนี้คุณกำลังใช้โปรโตคอลที่กำหนดเองไม่ใช่ HTTP
user16764

10
@ user16764 "ชุดวิธีการทั่วไปสำหรับ HTTP / 1.1 ถูกกำหนดไว้ด้านล่างแม้ว่าชุดนี้สามารถขยายได้ แต่ไม่สามารถสันนิษฐานได้ว่าจะใช้วิธีการเพิ่มเติมร่วมกันในความหมายเดียวกันสำหรับไคลเอนต์และเซิร์ฟเวอร์แยกกัน" w3.org/Protocols/rfc2616/rfc2616-sec9.htmlดังนั้นจึงได้รับอนุญาตและยังเป็น HTTP
Juan Mendes

imho ไม่มีอะไรที่จะเพิ่ม / ลบออกจาก HTTP เนื่องจากคำจำกัดความของวิธีการระบุว่าการใช้วิธีการที่กำหนดเองเป็นที่ยอมรับแล้วภายในขอบเขต HTTP / 1.1 แต่คาดว่าจะไม่สามารถแบ่งปันความหมายเดียวกันได้ดังนั้นฉันเดาว่าคะแนนจาก @MichaelT และ Juan Mendes ค่อนข้างสงบ
Prof83

คำตอบ:


42

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

อินเตอร์เฟซที่เหมือนกัน:

  • ง่ายกว่า
  • decouples การใช้งานจากบริการที่พวกเขาให้
  • อนุญาตให้ใช้สถาปัตยกรรมแบบเลเยอร์รวมถึงสิ่งต่างๆเช่น HTTP load balancer (nginx) และแคช (วานิช)

ในทางกลับกันส่วนต่อประสานที่เหมือนกัน:

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

ข้อตกลงนี้ได้รับการ "ออกแบบมาสำหรับกรณีทั่วไปของเว็บ" และได้อนุญาตให้สร้างระบบนิเวศขนาดใหญ่ซึ่งจะช่วยแก้ปัญหาที่พบบ่อยในสถาปัตยกรรมเว็บ การยึดอินเทอร์เฟซที่เหมือนกันจะทำให้ระบบของคุณได้รับประโยชน์จากระบบนิเวศนี้ในขณะที่การแตกมันจะทำให้มันยาก คุณอาจต้องการใช้ load balancer เช่น nginx แต่ตอนนี้คุณสามารถใช้ load balancer ที่เข้าใจ DRAFT และ CURATE เท่านั้น คุณอาจต้องการใช้เลเยอร์แคช HTTP เช่น Varnish แต่ตอนนี้คุณสามารถใช้เลเยอร์แคช HTTP ที่เข้าใจ DRAFT และ CURATE เท่านั้น คุณอาจต้องการขอความช่วยเหลือจากใครบางคนในการแก้ไขปัญหาความล้มเหลวของเซิร์ฟเวอร์ แต่ไม่มีใครรู้ถึงความหมายของคำขอ CURATE อาจเป็นการยากที่จะเปลี่ยนไคลเอนต์หรือไลบรารีเซิร์ฟเวอร์ที่คุณต้องการเพื่อทำความเข้าใจและใช้วิธีการใหม่อย่างถูกต้อง และอื่น ๆ

วิธี* ที่ถูกต้องในการนำเสนอนี้เป็นการแปลงสถานะบนทรัพยากร (หรือทรัพยากรที่เกี่ยวข้อง) คุณไม่ร่างโพสต์คุณเปลี่ยนdraftสถานะเป็นtrueหรือคุณสร้างdraftทรัพยากรที่มีการเปลี่ยนแปลงและลิงค์ไปยังเวอร์ชันฉบับร่างก่อนหน้า คุณไม่ได้เลิกโพสต์คุณเปลี่ยนcuratedสถานะเป็นtrueหรือสร้างcurationทรัพยากรที่เชื่อมโยงโพสต์กับผู้ใช้ที่ดูแลไว้

* แก้ไขให้ถูกต้องที่สุดตามหลักการสถาปัตยกรรม REST


ขอบคุณสำหรับความคิดเห็นเกี่ยวกับการทำโหลดบาลานซ์ฉันจะดูมันอย่างแน่นอน คุณรู้ของทรัพยากรที่ระบุว่าวิธีการที่กำหนดเองเป็นที่ยอมรับหรือไม่?
Juan Mendes

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

5
ฉันเห็นข้อดีในการออกแบบวิธีที่คุณต้องการให้บริการ HTTP ของคุณทำงานด้วยตัวเอง อย่างไรก็ตาม "วิธีการเพิ่มเติมไม่สามารถสันนิษฐานได้ว่ามีความหมายเหมือนกัน" - ยุติธรรมเพียงพอ แต่มันก็ยังคงเป็นส่วนหนึ่งของขอบเขต HTTP / 1.1 ดังนั้นไฟร์วอลล์พร็อกซีพร็อกซีโหลดบาลานเซอร์และสิ่งอื่น ๆ แล้วพวกเขาจะใช้ HTTP / 1.1 ไม่ถูกต้องหรือไม่?
Prof83

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

7

ฉันต้องการออกแบบเหล่านี้เป็นแหล่งข้อมูลย่อยซึ่งคุณดำเนินการตามคำขอ POST

พิจารณาคุณมีทรัพยากรที่/instance/type/1ผมจะต้องเป็นตัวแทนของทรัพยากรที่ถ่ายทอดคู่ของการเชื่อมโยงที่จะ 'การกระทำ' ที่สามารถดำเนินการบนทรัพยากรเช่นและ/instance/type/1/draft /instance/type/1/curateใน JSON สิ่งนี้อาจง่ายเหมือน:

{
    "some property":"the usual value",
    "state": "we can still inform the client about the current state",
    "draft": "http://server/instance/type/1/draft",
    "curate": "http://server/instance/type/1/curate"
}

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

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

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


คำตอบที่ดี. ความสามารถในการให้ข้อโต้แย้งกับการเปลี่ยนสถานะและการมีเซิร์ฟเวอร์แค็ปซูลและจัดการสิ่งเหล่านี้เป็นวิธีที่ดีที่สุด
โทมัส W

บริษัท ที่ฉันอยู่ในขณะนี้ (VMware) ทำสิ่งนี้ GET บน/vms/some-idจะส่งคืนลิงก์ไปยังการกระทำที่ต้องการPOST /vms/some-id/restartและเราใช้เพื่อพิจารณาว่าควรเปิดใช้งานหรือปิดใช้งานการกระทำหรือไม่ ผมมีความสัมพันธ์ความรัก / ความเกลียดชังกับHATEOAS :)
ฆ Mendes

มันจะมีเหตุผลมากกว่านี้ถ้าการกระทำที่ทำนั้นเป็นคำกริยาของคำขอเมื่อเทียบกับพารามิเตอร์คิวรีสุ่มบางส่วนเซ็กเมนต์พา ธ ของทรัพยากรหรือคุณสมบัติของร่างกาย
Matthew Whited

คุณไม่สามารถเชื่อมโยงคำกริยา
Dave Van den Eynde

6

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

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

นอกจากนี้ @Rein Henrichs "คุณไม่ได้โพสต์ร่างคุณเปลี่ยนสถานะร่างเป็นจริงหรือคุณสร้างทรัพยากรร่าง" ดูเหมือนว่าเท็จสำหรับฉัน draftsทรัพย์สินจะถูกนำมาใช้เพื่อการประหยัดถาวรของรัฐที่ไม่ได้สำหรับการเปลี่ยนแปลง การกระทำไม่จำเป็นต้องส่งผลให้ 'รัฐ' หรือถูกบันทึกไว้ในทรัพย์สิน การสร้างเอนทิตีแยกสำหรับแต่ละรัฐ / การแปลงดูเหมือนจะคลุมเครือมากขึ้น .. พยายามที่จะรักษาการอ้างอิงเดียวกัน (URI) เพื่อ enity


1
นี่เป็นประเด็นที่ยุติธรรมแม้ว่าจะไม่เห็นด้วยอย่างกว้างขวางฉันสามารถเห็นเหตุผลที่อยู่เบื้องหลังและฉันไม่เห็นด้วยกับ downvote (โดยเฉพาะอย่างยิ่งเมื่อไม่มีความเห็นจากผู้ลงคะแนน) ลองใช้การจัดการข้อยกเว้น PHP เป็นตัวอย่าง "แนวปฏิบัติที่ดีที่สุด" ดูเหมือนจะพึ่งพาการใช้ประเภทข้อยกเว้นเฉพาะเพื่อแนะนำประเภทของข้อยกเว้นแม้จะละเว้นข้อความจริงเช่น RuntimeException vs BadMethodCallException เหตุใดจึงมีการโต้แย้งกันอย่างกว้างขวางในการใช้ DRAFT หากใช้วิธีการแบบกำหนดเองถือว่าเป็นส่วนหนึ่งของขอบเขต HTTP / 1.1 แล้วหรือไม่ และโหลดบาลานเซอร์และพร็อกซี่ควรยอมรับความเป็นไปได้นี้เช่นกัน
Prof83
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.