Hướng dẫn dùng apiversion trong PHP

Hiện nay mô hình API – Client đang ngày càng phổ biến trong việc xây dựng các Web App và đặc biệt là với việc xây dựng các Mobile App thì việc xây dựng API là điều gần như không thể thiếu. Với việc API được sử dụng nhiều như vậy đồng nghĩa với việc người ta phải tạo ra một chuẩn chung trong việc thiết kế API. Và thế là REST ra đời.

Hiểu một cách đơn giản thì REST là một kiểu thiết kế API, nó là tập hợp những quy định và nguyên tắc thiết kế dành cho các Web Service (cung cấp API).

Tuy nhiên, khi đã là một Web Service tức là chúng ta đã xác định rằng sẽ phải cung cấp các API cho Client để sử dụng đúng không nhỉ. Nếu không cung cấp ra bên ngoài thì việc xây dựng Web Service không có tác dụng gì cả. Tất nhiên rồi =)) Chính vì thế mà việc cần quan tâm đó là không làm ảnh hướng đến các Client đang sử dụng API của chúng ta.

Lưu ý: REST không quy định quy chuẩn nào cho việc đánh version API. Dưới đây là cách mà mình thấy nó phù hợp và cũng được sử dụng phổ biến nhất.

  • Đánh version cho REST API
    • Breaking Change?
  • Đánh version thông qua URI
    • URL Path
    • Query Parameter
  • Đánh version thông qua Header
    • Custom Header
    • Accept header
  • Túm váy lại

Đánh version cho REST API

Versioning an interface is just a “polite” way to kill deployed clients.

Roy Fielding.

Có một vấn đề trong việc xây dựng API đó là đánh version. Hiện nay đa phần người ta sử dụng nguyên tắc Semantic Versioning để đánh version cho các ứng dụng, thư viện, framework,… Tuy nhiên chúng ta có nên áp dụng nó cho API?

Bạn có thể đọc thêm về Semantic Versioning thông qua bài viết của một nguời anh mình: https://viblo.asia/p/semantic-versioning-OeVKBN2EKkW

MAJOR.MINOR.PATCH
  • Hướng dẫn dùng apiversion trong PHP

Tuy nhiên với API thì nó tồn tại một vấn đề đó là chỉ cần Web Service có một thay đổi nhỏ thôi thì sẽ phải update version và nó sẽ khiến cho tất cả Client phải update lại source code cho App của họ hay ít nhất là update lại biến môi trường. Và thực sự nó là một điều không một ai muốn cả, không ai có thể theo sát từng update nhỏ nhất của Service và update cho App của mình cả.

Khi xây dựng Web Service và release thì chúng ta vẫn đánh version dạng Semantic tuy nhiên nó chỉ dùng trong internal thôi. Còn với bên ngoài chúng ta chỉ sử dụng phần Major để đưa cho Client, còn phần Minor và Patch chúng sẽ bị “tàng hình” :))

Ví dụ như Web Service có version là 1.2.3 thì chúng ta chỉ cho Client biết là API dùng version 1. Như vậy thì với những update nhỏ chúng ta sẽ không cần phải thông báo cho Client để update app của họ. Chỉ khi Web Service có một Breaking Change và phải thay đổi Major thì Client mới cần update app của họ.

Breaking Change?

Hiểu đơn giản là khi có Breaking Change tức là API bị thay đổi và Client bắt buộc phải update lại app nếu không muốn bị lỗi. Những sự thay đổi đó có thể là:

Đổi format response: từ XML -> JSON chẳng hạn

Đổi cấu trúc response trả về.

Ví dụ như đổi property name từ:

{
    "name": "Tien Nguyen"
}

Sang thành:

{
    "displayName": "Tien Nguyen"
}

Hay là đổi cấu trúc sang thành:

{
    "data": {
        "displayName": "Tien Nguyen"
    }
}

Cách đánh version thì có rồi, còn giờ là việc đưa version vào sử dụng cho phía Client. Có 4 cách thông dụng nhất như sau.

Đánh version thông qua URI

Trong URI thì có 2 cách như dưới đây.

URL Path

http://www.example.com/api/1/products
http://www.example.com/api/v1/products
http://apiv1.example.com/api/products

Khi nhìn vào đây chắc hẳn các bạn sẽ thấy quen đúng không. Theo mình thấy thì cách này là cách đang được sử dụng rộng rãi và phổ biến nhất. Version sẽ được gắn trực tiếp vào trong URI của API. Như 3 cách ở trên cũng là ví dụ thôi, có thể có nhiều kiểu tùy theo nguyên tắc của team nữa. Ví dụ có thể là /api-version-1/ hay v1.example.com chẳng hạn.

Query Parameter

http://www.example.com/api/products?version=1

Cách này thì mình thấy hầu như không có mấy ai sử dụng cả. Vì có tồn tại khá là nhiều vấn đề trong việc routing phía server cũng như việc gọi API phía Client. Đặc biệt nhìn nó không ngầu tẹo nào. :))

Đánh version thông qua Header

Với cách sử dụng Header này thì nhìn chung URL của API trông sẽ khá là sạch sẽ, gọn gàng. Tuy nhiên cách này lại có 1 vài nhược điểm so với dùng URI đó là sẽ khó cho clear version hơn, khó test hơn,…

Custom Header

Cách này có nghĩa là bạn sẽ tự tạo ra 1 header riêng để nhận biết version khi Client request lên phía server. Ví dụ như:

Accepts-version: 1
Accept-version: 1
Version: 1
Phien-ban: 1

Accept header

Accept là một header quy định của HTTP. Các bạn có thể xem thêm ở đây:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept

Về cơ bản là các bạn sẽ thêm version trong value của nó kiểu:

Accept: application/json;version=1

Túm váy lại

  • REST không có quy chuẩn cụ thể cho việc đánh version API.
  • Sử dụng Semantic Versioning khá khó trong việc triển khai version cho API.
  • Có 2 cách để version đó là qua URI và Header.
  • Và quan trọng nhất: Hãy luôn làm tốt phần API doc và đặc biệt là cả change log.

Tham khảo:

  • https://www.xmatters.com/blog/devops/blog-four-rest-api-versioning-strategies/
  • https://restfulapi.net/versioning/
  • https://www.freecodecamp.org/news/how-to-version-a-rest-api