URI và REST

Thêm một tí về REST.

Hiểu HTTP

Đúng ra bài viết  là về HTTP, vì REST không bắt buộc dùng HTTP. Tuy vậy những vấn đề về URI chủ yếu được để ý khi mọi người “viết REST”, còn lúc làm web bình thường thì URI kiểu nào cũng không bị để ý. Trong khi đó những khái niệm về URI đều từ HTTP mà ra cả, không hề liên quan tới REST.

Về HTTP thì đọc RFC là tốt nhất. RFC tương đối ngắn gọn, súc tích, dạng plain text rõ ràng, nhưng lại hay bị bỏ qua. Dưới đây tôi cũng chủ yếu tóm lược lại và link tới những tài liệu quan trọng để bạn có thể dễ dàng tìm đọc và hiểu đúng, chứ tôi viết thì cũng có thể sai sót.

POST, PUT, tạo và cập nhật

Thường thì hai loại method này được hiểu là POST dùng cho tạo, PUT dùng cho cập nhật. Điều này không hoàn toàn đúng. Có hai chỗ bạn có thể đọc thêm, một là RFC 2615, hai là trong quyển RESTful web services. RFC là chính xác nhất. Dịch thì cũng hơi khó, nhưng ý tưởng cơ bản là như sau:

  • POST là để cung cấp thành phần phụ cho một resoure xác định bởi URI, theo kiểu thêm một bài viết vào blog, hay thêm bình luận vào một bài viết (bài viết là resource), v.v. POST cũng có thể dùng để đẩy dữ liệu tới một quá trình xử lí nào đó. Kết quả của POST có thể không phải là một resource được xác định bởi một URI, chẳng hạn như khi bạn xem bình luận của một bài viết không phải là resource. Tất nhiên kết quả của POST cũng có thể là một resource với URI xác định. Điều này thường dùng trong viết REST khi chúng ta tạo một đơn vị resource mới trong một tập các resource cùng loại, ví dụ POST /article để tạo ra một bài báo mới ở article/{id}. Trong trường hợp có resource tạo ra như vậy thì phải trả về 201, chứ không phải 200 hay 204.
  • PUT là để đưa dữ liệu tới một resource xác định bởi URI. Tùy thuộc vào resource đã tồn tại hay chưa mà hành động này là create hay cập nhật. Chẳng hạn PUT /user/nmh để tạo hay cập nhật user nmh, chứ server không thể tạo user abc để trả về được. Chính vì vậy là không thể nói là POST dùng cho tạo, PUT dùng cho cập nhật.

Tóm lại có thể nói đơn giản là POST có thể dùng cho những việc hoàn toàn không liên quan đến tạo resource. Trong trường hợp POST dùng để tạo resource, thì resource sẽ được tạo ra chưa có URI xác định lúc gửi request. Với PUT thì resource sẽ được tạo ra hay cập nhật luôn có URI xác định ngay lúc gửi request.

Path variable, request parameter, và matrix URI

Dùng path variable hay request parameter? Câu trả lời là thế nào cũng được. Nhưng trong quyển RESTful web services có một đề xuất dựa trên RFC 3986. Dùng path variable nếu bạn muốn thể hiện sự phân cấp, ví dụ node/{id}/comment thay cho comment?node={id}. Trong trường hợp các biến không thể hiện sự phân cấp, hoặc có thể có có thể không, thì nên dùng request parameter.

Matrix URI thì là một thứ hơi khó hiểu và ít được nhắc đến. Về những ví dụ cụ thể có thể xem ở các web framework hỗ trợ nó, như Spring chẳng hạn. Về lí do ra đời thì có thể hiểu đơn giản là đâu đó có thể có nhu cầu dùng một associate array dưới dạng path variable, trong đó một số element có thể có hoặc không. Ví dụ (từ Restful web service) bạn muốn cho kinh độ và vĩ độ vào path variable để tạo URI thể hiện một điểm nào đó trên bản đồ, trong khi đó kinh độ và vĩ độ ngang hàng nhau nên không thể xếp một trong yếu tố đứng trước hoặc sau. Trong tình huống này bạn cần dùng matrix URI.

Advertisements

Cứ phải là REST sao

RESTful web services là xu hướng mới của thời đại, trong nước và ngoài nước. Trong khi người tạo ra REST và những nhà REST lí thuyết thì số vẫn đang bận rộn chỉ ra những API đội lốt RESTful thì những bộ API dạng REST vẫn liên tục xuất hiện. REST gần như là “chuẩn”, tức là nói tới việc viết API là mọi người sẽ nghĩ “viết REST”.

REST cũng tương tự Agile. Chúng có những lí thuyết riêng. Những lí thuyết này làm nên sức mạnh của chúng. Nhưng bản thân chúng thì lại ẩn sau vẻ ngoài dễ hiểu và đơn giản. Kết quả là những lí thuyết này thường không được tìm hiểu đầy đủ. Vậy nên những thứ không có quy tắc gì thì được gắn vào chúng. Viết web services dùng HTTP là viết REST. Làm phần mềm mà không có tính toán suy nghĩ gì thì tức là làm Agile.

Điều cần nói đầu tiên về REST là sự đơn giản giả tạo mà nó thể hiện. Điển hình là REST có vẻ gần gũi và tương đồng với HTTP. Người thiết kế REST quá chăm lo cho việc thiết kế media type, cách thể hiện tài nguyên (JSON hay XML, có field này hay không có field kia, v.v). Vấn đề thứ nhì là họ quá tập trung vào thiết kế URI cho đẹp, cho RESTful. Trong khi đó thì REST không quy định gì về URI hay JSON hay XML cả.

Trong khi đó hai thứ quan trọng mà người làm REST lại thường không để ý. Thứ nhất là URI của resources. URI tuyệt đối, chứ không phải ID như trong database, là cách mà REST dùng để định vị một resource. Thứ hai là HATEOAS, tức là hành vi của REST client của bạn trên mỗi resource phụ thuộc vào những hypermedia trong mỗi resource. Hypermedia là xương sống cho sự mềm dẻo và linh động và REST mang lại. Đây là những khái niệm không hiển nhiên nên đòi hỏi phải có sự tìm hiểu kĩ càng.

(Có một ví dụ kiểu tương tự mà bạn có thể sẽ hình dung đến khi tìm hiểu những khái niệm này. Khi bạn vào một tờ báo, chẳng hạn vnexpress.net, bạn sẽ thấy một danh sách tóm tắt các bài mới. Bạn đọc bài viết đầy đủ bằng cách bấm vào liên kết. Bạn không cần quan tâm ID của bài báo là gì, hay URI pattern của trang web là như thế nào. Bạn chỉ cần biết một điểm cuối duy nhất là vnexpress, từ đó bạn có thể đi khắp nơi. Khi bạn đọc một bài báo, bạn có thể bình luận hoặc không bình luận được, tùy vào sự hiện diện của form bình luận. Bạn không cần nhận về một field nào đó thể hiện điều này, hay phải thử bình luận rồi nhận về một status nào đó như 200, 400, 404, 500, v.v. Không chỉ bình luận, tất cả mọi thứ như in, chia sẻ lên mạng xã hội, v.v bạn biết là bạn làm được hay không làm được dựa vào sự hiện diện của nó ngay tại trang báo. Thứ bạn cần biết là cách nhận dạng những thành phần này, như biểu tượng máy in, biểu tượng facebook, v.v.)

Điều cần nói thứ hai, REST chỉ là công cụ, không phải đích đến. Và đến cuối ngày, REST không phải là thứ quan trọng. Tôi từng phải viết client để consume web services của một số phần mềm như BugZilla hay Jira. Điều mà tôi nhận ra, là API không bao giờ đủ. Có những nhu cầu hết sức bình thường và đơn giản thì API lại không có. Điều thứ hai tôi nhận ra là tôi cần làm dễ, làm nhanh chứ không cần cái “trình độ” của một API. Thế nên REST với tôi không tuyệt vời bằng một thư viện client, nơi tôi chỉ cần gọi hàm và nhận kết quả ngay trên ngôn ngữ lập trình mà tôi sử dụng. Vì vậy API tốt là API đầy đủ, dễ dùng, và có tài liệu tốt.

Và bây giờ, nếu bạn muốn tìm hiểu/tìm hiểu lại về REST thì đây là những thứ đáng đọc:

Luận án đã sinh ra REST

RESTful web services

REST in Practice: Hypermedia and Systems Architecture—cuốn này viết không chính xác lắm về REST, nhưng lại có đi sâu vào một số phần của HTTP mà chúng ta sẽ hay dùng khi viết REST over HTTP. Lâu lâu mới có một cuốn O’Reilly mà bìa không in hình thú vật.

Practical API Design: Confessions of a Java Framework Architect—vì phải biết xây dựng API tốt thì mới biết cách ứng dụng REST cho hợp lí

– Và tìm hiểu những bộ web services tốt nhất