วิธีการเวอร์ชัน REST URI


111

วิธีใดเป็นวิธีที่ดีที่สุดในการสร้าง URI REST ขณะนี้เรามีเวอร์ชัน # ใน URI เองเช่น

http://example.com/users/v4/1234/

สำหรับเวอร์ชัน 4 ของการเป็นตัวแทนนี้

เวอร์ชันอยู่ใน queryString หรือไม่ กล่าวคือ

http://example.com/users/1234?version=4

หรือการกำหนดเวอร์ชันทำได้ดีที่สุดด้วยวิธีอื่น?


คำตอบ:


34

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


11
คำถามคือทรัพยากรที่แตกต่างกันที่เรากำลังพูดถึงหรือไม่? หรือเป็นตัวแทนที่แตกต่างกันของทรัพยากรนั้น? REST สร้างความแตกต่างระหว่างการเป็นตัวแทนและทรัพยากรหรือไม่
Cheeso

1
@Cheeso - OP ระบุว่าเป็นการแสดงที่แตกต่างกันแทนที่จะเป็นทรัพยากรอื่นดังนั้นคำตอบของฉัน
Greg Beech

สิ่งนี้ได้รับคำตอบโดยละเอียดก่อนที่นี่stackoverflow.com/q/389169/104261
Taras Alenin

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

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

191

อย่าเวอร์ชัน URL เนื่องจาก ...

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

สมมติว่าทรัพยากรของคุณส่งคืนตัวแปร application / vnd.yourcompany.user + xml สิ่งที่คุณต้องทำคือสร้างการสนับสนุนสำหรับแอปพลิเคชันใหม่ / ประเภทสื่อ vnd.yourcompany.userV2 + xml และผ่านความมหัศจรรย์ของการเจรจาเนื้อหา v1 ของคุณและ ไคลเอนต์ v2 สามารถอยู่ร่วมกันได้อย่างสงบสุข

ในอินเทอร์เฟซ RESTful สิ่งที่ใกล้เคียงที่สุดที่คุณต้องทำสัญญาคือคำจำกัดความของประเภทสื่อที่แลกเปลี่ยนระหว่างไคลเอนต์และเซิร์ฟเวอร์

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

หากคุณต้องการเปลี่ยนแปลงประเภทสื่อของคุณที่จะทำลายลูกค้าปัจจุบันของคุณให้สร้างใหม่และปล่อยให้ URL ของคุณอยู่คนเดียว!

และสำหรับผู้อ่านเหล่านั้นในปัจจุบันกล่าวว่าสิ่งนี้ไม่สมเหตุสมผลหากฉันใช้ application / xml และ application / json เป็นสื่อประเภท เราควรจะทำเวอร์ชันเหล่านั้นอย่างไร? คุณไม่. ประเภทสื่อเหล่านี้ค่อนข้างไร้ประโยชน์สำหรับอินเทอร์เฟซ RESTful เว้นแต่คุณจะแยกวิเคราะห์โดยใช้การดาวน์โหลดโค้ดซึ่งการกำหนดเวอร์ชันเป็นจุดที่สงสัย


66
เพื่อจัดการกับสัญลักษณ์แสดงหัวข้อย่อย 1. คุณไม่ทำลายลิงก์ Perma เนื่องจากลิงก์ถาวรเชื่อมโยงไปยังเวอร์ชันเฉพาะ 2. หากทุกอย่างเป็นเวอร์ชันที่ไม่ใช่ปัญหา URL เก่ายังสามารถใช้งานได้ ตามหลักการแล้วคุณไม่ต้องการให้ URL เวอร์ชัน 4 ส่งคืนการเชื่อมโยงกับทรัพยากรเวอร์ชัน 3 3. บางที
Mike Pone

10
ลองนึกภาพว่าเมื่อคุณอัปเกรดเป็นเว็บเบราว์เซอร์เวอร์ชันใหม่รายการโปรดที่บุ๊กมาร์กทั้งหมดของคุณพัง! โปรดจำไว้ว่าตามแนวคิดแล้วผู้ใช้กำลังบันทึกลิงก์ไปยังทรัพยากรไม่ใช่เวอร์ชันของการเป็นตัวแทนของทรัพยากร
Darrel Miller

11
@Gili เพื่อให้เป็นไปตามข้อกำหนดสำหรับ REST api ที่จะอธิบายตัวเองได้จำเป็นที่ส่วนหัวประเภทเนื้อหาจะต้องให้คำอธิบายความหมายที่สมบูรณ์ของข้อความ กล่าวอีกนัยหนึ่งประเภทสื่อของคุณคือสัญญาข้อมูลของคุณ หากคุณส่ง application / xml หรือ application / json คุณกำลังบอกลูกค้าเกี่ยวกับสิ่งที่อยู่ใน XML / Json นั้น ทันทีที่แอปพลิเคชันไคลเอนต์เข้าถึงในการดึงออก / ลูกค้า / ชื่อคุณกำลังสร้างการมีเพศสัมพันธ์ที่อิงตามข้อมูลที่ไม่อยู่ในข้อความ การขจัดข้อต่อนอกแบนด์มีความสำคัญต่อการบรรลุความสงบ
Darrel Miller

6
@Gili ไคลเอนต์ไม่ควรมีความรู้มาก่อนเกี่ยวกับ URL ของ API นอกเหนือจากรูท URL คุณไม่ควรผูกรูปแบบการนำเสนอกับ URL ที่เจาะจง ในการเลือกประเภทสื่อคุณต้องเลือกระหว่างรูปแบบเฉพาะเช่น application / vnd.mycompany.myformat + xml หรือรูปแบบมาตรฐานเช่น XHtml Atom RDF เป็นต้น
Darrel Miller

4
มันสมเหตุสมผลหรือไม่ที่จะกำหนดให้เวอร์ชัน API เป็นฟิลด์ส่วนหัวแยกต่างหาก ดังนี้: ยอมรับ: application / com.example.myapp + json; version = 1.0
Erik

21

อาฉันสวมหมวกใบเก่าที่ไม่พอใจอีกครั้ง

จากมุมมองของ ReST มันไม่สำคัญเลย ไม่ใช่ไส้กรอก.

ไคลเอนต์ได้รับ URI ที่ต้องการติดตามและถือว่าเป็นสตริงทึบแสง ใส่อะไรก็ได้ที่คุณต้องการลูกค้าไม่มีความรู้เกี่ยวกับสิ่งนั้นเป็นตัวระบุเวอร์ชัน

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

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

ฉันเองจะโหวตให้http: // localhost / 3f3405d5-5984-4683-bf26-aca186d21c04

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


จะเกิดอะไรขึ้นหากการแสดงจำเป็นต้องเปลี่ยนแปลงอย่างมีนัยสำคัญและจะไม่สามารถใช้งานร่วมกันได้แบบย้อนกลับ?
Mike Pone

1
ด้วยการออกแบบประเภทสื่อของคุณในรูปแบบที่ขยายได้เช่นโดยใช้เนมสเปซและ xsd ที่ขยายได้หรือรูปแบบ xml ike ที่มีอยู่สิ่งนี้ควรป้องกันได้ หากคุณต้องการจริงๆสื่อประเภทอื่นคือหนทางที่จะไป
SerialSeb

1
ฉันชอบคำตอบที่ถูกต้องทั้งหมดนี้ แต่ฉันคิดว่า URI ที่เสนอนั้นแสดงให้เห็นถึงประเด็นมากกว่าสถานการณ์จริงที่คุณต้องการ URI ที่ 'แฮ็กได้'
Dave Van den Eynde

10

คุณไม่ควรใส่เวอร์ชันใน URL คุณควรใส่เวอร์ชันในส่วนหัวยอมรับของคำขอ - ดูโพสต์ของฉันในหัวข้อนี้:

แนวทางปฏิบัติที่ดีที่สุดสำหรับการกำหนดเวอร์ชัน API?

หากคุณเริ่มติดเวอร์ชันใน URL คุณจะพบ URL โง่ ๆ เช่นนี้: http://company.com/api/v3.0/customer/123/v2.0/orders/4321/

และยังมีปัญหาอื่น ๆ อีกมากมายที่กำลังคืบคลานเข้ามาเช่นกัน - ดูบล็อกของฉัน: http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html


11
ขออภัยฉันไม่คิดว่าคุณจะลงเอยด้วย URL โง่ ๆ แบบนี้ คุณกำลังผูกหมายเลขเวอร์ชันกับทรัพยากรเฉพาะหรือ (แย่กว่านั้น) กับการแสดงเฉพาะ นั่นจะเป็นเรื่องโง่ IMO แต่คุณกำลังกำหนดเวอร์ชัน API ดังนั้นคุณจะไม่มีมากกว่าหนึ่งเวอร์ชันใน URI
fool4jesus

5

คำถาม SO (เฉพาะน้อยกว่า) เหล่านี้เกี่ยวกับการกำหนดเวอร์ชัน REST API อาจเป็นประโยชน์:


3

มี 4 วิธีที่แตกต่างกันในการกำหนดเวอร์ชัน API:

  • การเพิ่มเวอร์ชันในเส้นทาง URI:

    http://example.com/api/v1/foo
    
    http://example.com/api/v2/foo
    

    เมื่อคุณทำลายการเปลี่ยนแปลงคุณต้องเพิ่มเวอร์ชันเช่น: v1, v2, v3 ...

    คุณสามารถติดตั้งคอนโทรลเลอร์ในโค้ดของคุณได้ดังนี้:

    @RestController
    public class FooVersioningController {
    
    @GetMapping("v1/foo")
    public FooV1 fooV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping("v2/foo")
    public FooV2 fooV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • ขอการกำหนดเวอร์ชันพารามิเตอร์:

    http://example.com/api/v2/foo/param?version=1
    http://example.com/api/v2/foo/param?version=2
    

    พารามิเตอร์เวอร์ชันอาจเป็นทางเลือกหรือจำเป็นขึ้นอยู่กับว่าคุณต้องการใช้ API อย่างไร

    การใช้งานอาจคล้ายกับสิ่งนี้:

    @GetMapping(value = "/foo/param", params = "version=1")
    public FooV1 paramV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping(value = "/foo/param", params = "version=2")
    public FooV2 paramV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • การส่งผ่านส่วนหัวที่กำหนดเอง:

    http://localhost:8080/foo/produces
    

    ด้วยส่วนหัว:

    headers[Accept=application/vnd.company.app-v1+json]
    

    หรือ:

    headers[Accept=application/vnd.company.app-v2+json]
    

    ข้อได้เปรียบที่ใหญ่ที่สุดของรูปแบบนี้ส่วนใหญ่เป็นความหมาย: คุณไม่ได้ทำให้ URI ยุ่งเหยิงกับสิ่งที่เกี่ยวข้องกับการกำหนดเวอร์ชัน

    การใช้งานที่เป็นไปได้:

    @GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v1+json")
    public FooV1 producesV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v2+json")
    public FooV2 producesV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • การเปลี่ยนชื่อโฮสต์หรือใช้เกตเวย์ API:

    โดยพื้นฐานแล้วคุณกำลังย้าย API จากชื่อโฮสต์หนึ่งไปยังอีกชื่อหนึ่ง คุณอาจเรียกสิ่งนี้ว่าการสร้าง API ใหม่กับทรัพยากรเดียวกัน

    นอกจากนี้คุณสามารถทำได้โดยใช้ API เกตเวย์


2

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

ขออภัยโซลูชันนี้ใช้ได้กับ API ที่ใช้การตรวจสอบสิทธิ์เท่านั้น อย่างไรก็ตามจะไม่เก็บเวอร์ชันต่างๆจาก URI


2

ฉันต้องการสร้าง API ที่กำหนดเวอร์ชันและพบว่าบทความนี้มีประโยชน์มาก:

http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http

มีส่วนเล็ก ๆ ใน "ฉันต้องการให้ API ของฉันเป็นเวอร์ชัน" ฉันพบว่ามันเรียบง่ายและเข้าใจง่าย ประเด็นสำคัญคือการใช้ช่องยอมรับในส่วนหัวเพื่อส่งผ่านข้อมูลเวอร์ชัน


1

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


1

หากคุณใช้ URI ในการกำหนดเวอร์ชันหมายเลขเวอร์ชันควรอยู่ใน URI ของรูท API ดังนั้นตัวระบุทรัพยากรทุกตัวสามารถรวมไว้ได้

ในทางเทคนิค REST API ไม่ทำลายโดยการเปลี่ยนแปลง URL (ผลลัพธ์ของข้อ จำกัด ของอินเตอร์เฟสที่เหมือนกัน) จะแตกก็ต่อเมื่อความหมายที่เกี่ยวข้อง (เช่นคำศัพท์ RDF เฉพาะของ API) เปลี่ยนไปในลักษณะที่เข้ากันไม่ได้ย้อนหลัง (หายาก) ปัจจุบัน ppl จำนวนมากไม่ใช้ลิงก์สำหรับการนำทาง (ข้อ จำกัด ของ HATEOAS) และคำศัพท์เพื่อใส่คำอธิบายประกอบการตอบกลับ REST (ข้อ จำกัด ของข้อความอธิบายตัวเอง) นั่นคือสาเหตุที่ลูกค้าของพวกเขาหยุดทำงาน

ประเภท MIME ที่กำหนดเองและการกำหนดเวอร์ชันประเภท MIME ไม่สามารถช่วยได้เนื่องจากการใส่ข้อมูลเมตาที่เกี่ยวข้องและโครงสร้างของการแสดงลงในสตริงสั้น ๆ ไม่ได้ผล Ofc ข้อมูลเมตาและโครงสร้างมักจะเปลี่ยนแปลงดังนั้นหมายเลขเวอร์ชันก็เช่นกัน ...

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


0

ฉันโหวตให้ทำสิ่งนี้ในประเภท mime แต่ไม่ใช่ใน URL แต่เหตุผลไม่เหมือนกับผู้ชายคนอื่น ๆ

ฉันคิดว่า URL ควรไม่ซ้ำกัน (ยกเว้นการเปลี่ยนเส้นทางเหล่านั้น) สำหรับการค้นหาทรัพยากรที่ไม่ซ้ำกัน ดังนั้นถ้าคุณยอมรับ/v2.0ใน URL ที่ว่าทำไมมันไม่ได้/ver2.0หรือ/v2/หรือ/v2.0.0? หรือแม้แต่-alphaและ-beta? (จากนั้นมันก็กลายเป็นแนวคิดของsemver โดยสิ้นเชิง )

ดังนั้นเวอร์ชันในประเภท mime จึงเป็นที่ยอมรับได้มากกว่า URL

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