Cách tạo phiên bản URI REST


111

Cách tốt nhất để phiên bản các URI REST là gì? Hiện tại, chúng tôi có một phiên bản # trong chính URI.

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

cho phiên bản 4 của đại diện này.

Phiên bản có thuộc queryString không? I E.

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

Hay việc tạo phiên bản được thực hiện tốt nhất theo cách khác?


Câu trả lời:


34

Tôi muốn nói rằng biến nó thành một phần của chính URI (tùy chọn 1) là tốt nhất vì v4 xác định một tài nguyên khác với v3. Các tham số truy vấn như trong tùy chọn thứ hai của bạn có thể được sử dụng tốt nhất để chuyển vào thông tin bổ sung (truy vấn) liên quan đến yêu cầu , thay vì tài nguyên .


11
Câu hỏi đặt ra là nó có phải là NGUỒN LỰC khác mà chúng ta đang thảo luận không? Hoặc một đại diện khác của tài nguyên đó? REST có phân biệt giữa biểu diễn và tài nguyên không?
Cheeso

1
@Cheeso - OP chỉ ra rằng nó là một đại diện khác chứ không phải là một tài nguyên khác, do đó tôi trả lời.
Greg Beech

Điều này đã được trả lời chi tiết hơn trước đây stackoverflow.com/q/389169/104261
Taras Alenin

+1 cho "Tham số truy vấn như trong tùy chọn thứ hai của bạn có thể được sử dụng tốt nhất để chuyển thông tin bổ sung (truy vấn) liên quan đến yêu cầu, thay vì tài nguyên"
andy

Đối với các đại diện khác nhau, tôi nghĩ bạn nên sử dụng các tiêu đề như "Chấp nhận", sau đó máy khách có thể chỉ định cho máy chủ "Tôi chỉ chấp nhận phiên bản 4" và máy chủ có thể trả lời với đại diện đó. Nếu không chấp nhận được gửi thì phiên bản cuối cùng được cung cấp.
Carlos Verdes

190

Không phiên bản URL, vì ...

  • bạn phá vỡ liên kết cố định
  • Các thay đổi url sẽ lây lan như một căn bệnh qua giao diện của bạn. Bạn làm gì với các biểu diễn không thay đổi nhưng trỏ đến biểu diễn đã có? Nếu bạn thay đổi url, bạn sẽ phá vỡ các khách hàng cũ. Nếu bạn rời khỏi url, khách hàng mới của bạn có thể không hoạt động.
  • Tạo phiên bản các loại phương tiện là một giải pháp linh hoạt hơn nhiều.

Giả sử rằng tài nguyên của bạn đang trả về một số biến thể của application / vnd.yourcompany.user + xml, tất cả những gì bạn cần làm là tạo hỗ trợ cho một ứng dụng mới / vnd.yourcompany.userV2 + loại phương tiện xml và thông qua phép thuật thương lượng nội dung v1 của bạn và khách hàng v2 có thể cùng tồn tại một cách hòa bình.

Trong giao diện RESTful, điều gần nhất mà bạn có trong hợp đồng là định nghĩa về các loại phương tiện được trao đổi giữa máy khách và máy chủ.

Các URL mà máy khách sử dụng để tương tác với máy chủ phải được cung cấp bởi máy chủ được nhúng trong các đại diện đã truy xuất trước đó. URL duy nhất mà khách hàng cần biết là URL gốc của giao diện. Việc thêm số phiên bản vào url chỉ có giá trị nếu bạn tạo url trên máy khách, điều này bạn không cho là làm với giao diện RESTful.

Nếu bạn cần thực hiện một thay đổi đối với các loại phương tiện sẽ phá vỡ các khách hàng hiện tại của bạn, hãy tạo một cái mới và để yên các url của bạn!

Và đối với những độc giả hiện đang nói rằng điều này không có ý nghĩa gì nếu tôi đang sử dụng ứng dụng / xml và ứng dụng / json làm các loại phương tiện. Làm thế nào chúng ta phải phiên bản chúng? Bạn không phải. Những loại phương tiện đó khá vô dụng đối với giao diện RESTful trừ khi bạn phân tích cú pháp chúng bằng cách sử dụng tải xuống mã, tại thời điểm này, việc lập phiên bản là một điểm tranh luận.


66
Để giải quyết các gạch đầu dòng. 1. bạn không phá vỡ liên kết perma, bởi vì liên kết cố định liên kết đến một phiên bản cụ thể 2. Nếu mọi thứ đều được tạo phiên bản thì đây không phải là vấn đề. Các url cũ vẫn có thể hoạt động. Tốt nhất, bạn sẽ không muốn URL phiên bản 4 trả về một liên kết đến tài nguyên phiên bản 3. 3. Có lẽ
Mike Pone.

10
Hãy tưởng tượng nếu khi bạn nâng cấp lên phiên bản mới của trình duyệt web, tất cả các mục yêu thích được đánh dấu trang của bạn sẽ bị hỏng! Hãy nhớ rằng về mặt khái niệm, người dùng đang lưu một liên kết tới một tài nguyên, chứ không phải vào một phiên bản biểu diễn của một tài nguyên.
Darrel Miller

11
@Gili Để đáp ứng yêu cầu cho một api REST là tự mô tả, điều cần thiết là tiêu đề kiểu nội dung cung cấp mô tả ngữ nghĩa hoàn chỉnh của thông báo. Nói cách khác, loại phương tiện của bạn là hợp đồng dữ liệu của bạn. Nếu bạn cung cấp ứng dụng / xml hoặc ứng dụng / json, bạn đang nói với khách hàng không có gì về những gì được chứa trong XML / Json đó. Thời điểm ứng dụng khách tiếp cận trong một lần kéo ra / Khách hàng / Tên mà bạn đang tạo khớp nối dựa trên thông tin không có trong tin nhắn. Việc loại bỏ khớp nối ngoài băng tần là rất quan trọng để đạt được RESTibility.
Darrel Miller

6
@Gili Khách hàng không được biết trước về các URL của API ngoài URL gốc. Bạn không nên buộc các định dạng đại diện với các URL cụ thể. Khi nói đến việc chọn các loại phương tiện, bạn thực sự cần phải chọn giữa một định dạng cụ thể như application / vnd.mycompany.myformat + xml hoặc một định dạng tiêu chuẩn như, XHtml, Atom, RDF, v.v.
Darrel Miller

4
Có hợp lý không khi đặt phiên bản API là một trường tiêu đề riêng biệt? Như vậy: Chấp nhận: application / com.example.myapp + json; version = 1.0
Erik

21

À, tôi đang đội lại chiếc mũ khó chịu cũ của mình.

Từ góc độ ReST, điều đó hoàn toàn không thành vấn đề. Không phải xúc xích.

Máy khách nhận được một URI mà nó muốn theo dõi và coi nó như một chuỗi mờ. Đặt bất cứ thứ gì bạn muốn vào đó, khách hàng không biết về thứ như mã định danh phiên bản trên đó.

Những gì khách hàng biết là nó có thể xử lý loại phương tiện và tôi sẽ khuyên bạn nên làm theo lời khuyên của Darrel. Ngoài ra, cá nhân tôi cảm thấy rằng cần phải thay đổi định dạng được sử dụng trong một kiến ​​trúc khôi phục lại 4 lần sẽ mang lại những dấu hiệu cảnh báo lớn cho thấy bạn đang làm gì đó sai nghiêm trọng và hoàn toàn bỏ qua yêu cầu thiết kế loại phương tiện của bạn để phục hồi thay đổi.

Nhưng dù bằng cách nào, khách hàng chỉ có thể xử lý tài liệu có định dạng mà nó có thể hiểu được và theo các liên kết trong đó. Nó nên biết về các mối quan hệ liên kết (chuyển tiếp). Vì vậy, những gì trong URI là hoàn toàn không liên quan.

Cá nhân tôi sẽ bỏ phiếu cho http: // localhost / 3f3405d5-5984-4683-bf26-aca186d21c04

Một số nhận dạng hoàn toàn hợp lệ sẽ ngăn bất kỳ nhà phát triển khách hàng hoặc người nào khác chạm vào hệ thống để đặt câu hỏi liệu người ta nên đặt v4 ở đầu hay cuối URI (và tôi đề nghị rằng, từ góc độ máy chủ, bạn không nên có 4 phiên bản, nhưng 4 loại phương tiện).


Điều gì sẽ xảy ra nếu biểu diễn cần thay đổi đáng kể và không tương thích ngược?
Mike Pone

1
Bằng cách thiết kế loại phương tiện của bạn theo kiểu có thể mở rộng, chẳng hạn như bằng cách sử dụng không gian tên và xsd có thể mở rộng hoặc các định dạng xml ike nguyên tử hiện có, điều này có thể ngăn ngừa được. Nếu bạn thực sự phải làm vậy, một loại phương tiện truyền thông khác là cách để đi.
SerialSeb

1
Tôi thích câu trả lời hoàn toàn hợp lệ này, nhưng tôi nghĩ rằng URI được đề xuất là để chứng minh quan điểm hơn là cho một kịch bản thực tế mà bạn muốn các URI 'có thể hack'.
Dave Van den Eynde, 31/10/12

10

Bạn KHÔNG nên đặt phiên bản vào URL, bạn nên đặt phiên bản vào Tiêu đề Chấp nhận của yêu cầu - xem bài đăng của tôi trên chủ đề này:

Các phương pháp hay nhất để lập phiên bản API?

Nếu bạn bắt đầu gắn các phiên bản trong URL, bạn sẽ nhận được các URL ngớ ngẩn như sau: http://company.com/api/v3.0/customer/123/v2.0/orders/4321/

Và có một loạt các vấn đề khác cũng xảy ra - hãy xem blog của tôi: http://thereisnorightway.blogspot.com/2011/02/versinstall-and-types-in-resthttp-api.html


11
Xin lỗi, nhưng tôi không nghĩ rằng bạn sẽ kết thúc với những URL ngớ ngẩn như thế này. Bạn đang gắn số phiên bản với một tài nguyên cụ thể hoặc (tệ hơn) với một đại diện cụ thể. Điều đó thật ngớ ngẩn, IMO. Thay vào đó, bạn đang lập phiên bản API, vì vậy bạn sẽ không bao giờ có nhiều hơn một phiên bản trong URI.
crazy4jesus


3

Có 4 cách tiếp cận khác nhau để lập phiên bản API:

  • Thêm phiên bản vào đường dẫn URI:

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

    Khi bạn có thay đổi đột phá, bạn phải tăng phiên bản như: v1, v2, v3 ...

    Bạn có thể triển khai một bộ điều khiển trong mã của mình như sau:

    @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"));
    }
    
  • Yêu cầu lập phiên bản tham số:

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

    Tham số phiên bản có thể là tùy chọn hoặc bắt buộc tùy thuộc vào cách bạn muốn API được sử dụng.

    Việc triển khai có thể tương tự như sau:

    @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"));
    }
    
  • Chuyển một tiêu đề tùy chỉnh:

    http://localhost:8080/foo/produces
    

    Với tiêu đề:

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

    hoặc là:

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

    Lợi thế lớn nhất của lược đồ này chủ yếu là ngữ nghĩa: Bạn không làm lộn xộn URI với bất kỳ điều gì liên quan đến việc lập phiên bản.

    Có thể thực hiện:

    @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"));
    }
    
  • Thay đổi tên máy chủ hoặc sử dụng Cổng API:

    Về cơ bản, bạn đang di chuyển API từ tên máy chủ này sang tên máy chủ khác. Bạn thậm chí có thể gọi việc xây dựng này là một API mới cho các tài nguyên tương tự.

    Ngoài ra, bạn có thể thực hiện việc này bằng API Gateways.


2

Nếu các dịch vụ REST yêu cầu xác thực trước khi sử dụng, bạn có thể dễ dàng liên kết khóa / mã thông báo API với phiên bản API và thực hiện định tuyến nội bộ. Để sử dụng phiên bản mới của API, có thể yêu cầu khóa API mới, được liên kết với phiên bản đó.

Thật không may, giải pháp này chỉ hoạt động cho các API dựa trên xác thực. Tuy nhiên, nó không giữ các phiên bản của URI.



1

Tôi sẽ bao gồm phiên bản dưới dạng giá trị tùy chọn ở cuối URI. Đây có thể là một hậu tố như / V4 hoặc một tham số truy vấn như bạn đã mô tả. Bạn thậm chí có thể chuyển hướng / V4 đến tham số truy vấn để hỗ trợ cả hai biến thể.


1

Nếu bạn sử dụng URI để lập phiên bản, thì số phiên bản phải nằm trong URI của gốc API, vì vậy mọi định danh tài nguyên đều có thể bao gồm nó.

Về mặt kỹ thuật, REST API không bị phá vỡ bởi các thay đổi URL (kết quả của ràng buộc giao diện thống nhất). Nó chỉ bị phá vỡ khi ngữ nghĩa liên quan (ví dụ như vocab RDF cụ thể của API) thay đổi theo cách không tương thích ngược (hiếm gặp). Hiện tại rất nhiều ppl không sử dụng liên kết để điều hướng (ràng buộc HATEOAS) và vocabs để chú thích phản hồi REST của họ (ràng buộc thông báo tự mô tả), đó là lý do tại sao khách hàng của họ bị phá vỡ.

Các kiểu MIME tùy chỉnh và lập phiên bản kiểu MIME không giúp ích được gì, vì việc đặt siêu dữ liệu liên quan và cấu trúc của biểu diễn vào một chuỗi ngắn không hoạt động. Ofc. siêu dữ liệu và cấu trúc sẽ thường xuyên thay đổi, và do đó, số phiên bản cũng vậy ...

Vì vậy, để trả lời câu hỏi của bạn, cách tốt nhất là chú thích các yêu cầu và phản hồi của bạn bằng vocab ( Hydra , dữ liệu được liên kết ) và quên lập phiên bản hoặc chỉ sử dụng nó bằng các thay đổi vocab không tương thích ngược (ví dụ: nếu bạn muốn thay thế vocab bằng một từ khác).


0

Tôi bỏ phiếu cho việc này trong loại kịch câm nhưng không phải trong URL. Nhưng lý do không giống với những chàng trai khác.

Tôi nghĩ rằng URL phải là duy nhất (ngoại trừ những chuyển hướng đó) để định vị tài nguyên duy nhất. Vì vậy, nếu bạn chấp nhận /v2.0trong URL, tại sao nó không được /ver2.0hoặc /v2/hoặc /v2.0.0? Hoặc thậm chí -alpha-beta? (sau đó nó hoàn toàn trở thành khái niệm về semver )

Vì vậy, phiên bản ở loại kịch câm dễ chấp nhận hơn so với URL.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.