Nói theo một cách nguyên lí REST và cấu trúc tài liệu RESTful được nghe biết rộng rãi trong giới lập trình web nói chung và lập trình ứng dụng nói riêng.
Nói theo một cách bản thân REST không phải là một loại công nghệ. Nó là phương thức tạo API với nguyên tắc tổ chức nhất định. Những nguyên tắc này nhằm hướng dẫn lập trình viên tạo môi trường thiên nhiên xử lý API request được toàn diện.
Để nắm vững hơn về RESTful API ta sẽ đi tuần tự giảng giải các khái niệm API, REST hay RESTful.
RESTful API là gì?
RESTful API là một tiêu chuẩn dùng trong việc thiết kế API cho những ứng dụng web (thiết kế Web services) để tiện cho việc quản lý các resource. Nó chú trọng vào tài nguyên mạng lưới hệ thống (tệp văn bản, ảnh, âm thanh, video, hoặc tài liệu động…), gồm có các trạng thái tài nguyên được định dạng và được truyền tải qua HTTP.
Xem thêm: các vị trí tuyển dụng lập trình API quyến rũ tại Topdev
Diễn giải các thành phần
API (Application Phườngrogramming Interface) là một tập các quy tắc và cơ chế mà Từ đó, một ứng dụng hay một thành phần sẽ tương tác với một ứng dụng hay thành phần khác. API có thể trả về tài liệu mà bạn phải cho ứng dụng của mình ở những kiểu tài liệu phổ quát như JSON hay XML.
REST (REpresentational State Transfer) là một dạng chuyển đổi cấu trúc tài liệu, một kiểu kiến trúc để viết API. Nó sử dụng phương thức HTTP đơn giản để tạo cho giao tiếp giữa các máy. Vì vậy, thay vì sử dụng một URL cho việc xử lý một số thông tin người dùng, REST gửi một yêu cầu HTTP như GET, POST, DELETE, vv đến một URL để xử lý tài liệu.
RESTful API là một tiêu chuẩn dùng trong việc thiết kế các API cho những ứng dụng web để quản lý các resource. RESTful là một trong những kiểu thiết kế API được sử dụng phổ quát ngày này để cho những ứng dụng (web, mobile…) khác nhau giao tiếp với nhau.
Chức năng quan trọng nhất của REST là quy định cách sử dụng các HTTP method (như GET, POST, PUT, DELETE…) và cách định dạng các URL cho ứng dụng web để quản các resource. RESTful không quy định logic code ứng dụng và không giới hạn bởi tiếng nói lập trình ứng dụng, bất kỳ tiếng nói hoặc framework nào cũng luôn tồn tại thể sử dụng để thiết kế một RESTful API.
RESTful hoạt động ra sao?
REST hoạt động chủ yếu dựa vào giao thức HTTP. Những hoạt động cơ bản nêu trên sẽ sử dụng những phương thức HTTP riêng.
- GET (SELECT): Trả về một Resource hoặc một list Resource.
- POST (CREATE): Tạo mới một Resource.
- PUT (UPDATE): Update thông tin cho Resource.
- DELETE (DELETE): Xoá một Resource.
Những phương thức hay hoạt động này thường được gọi là CRUD tương ứng với Create, Read, Update, Delete – Tạo, Đọc, Sửa, Xóa.
Ngày nay phần nhiều lập trình viên viết RESTful API giờ đây đều chọn JSON là format chính thức nhưng cũng luôn tồn tại nhiều người chọn XML làm format, nói chung dùng thế nào thì cũng được miễn tiện và nhanh.
Authentication và tài liệu trả về
RESTful API không sử dụng session và cookie, nó sử dụng một access_token với mỗi request. Tài liệu trả về thường có cấu trúc như sau:
{ “data” : { “id”: “1”, “name”: “TopDev” } }
Status code
Khi tất cả chúng ta request một API nào này thường thì sẽ sở hữu được vài status code để nhận mặt sau:
- 200 OK – Trả về thành công cho những phương thức GET, PUT, PATCH hoặc DELETE.
- 201 Created – Trả về khi một Resouce vừa mới được tạo thành công.
- 204 No Content – Trả về khi Resource xoá thành công.
- 304 Not Modified – Client có thể sử dụng tài liệu cache.
- 400 Bad Request – Request không hợp thức
- 401 Unauthorized – Request cần có auth.
- 403 Forbidden – bị từ chối không được chấp nhận.
- 404 Not Found – Không tìm thấy resource từ URI
- 405 Method Not Allowed – Phương thức không được chấp nhận với user ngày nay.
- 410 Gone – Resource không còn tồn tại, Version cũ dường như không còn tương trợ.
- 415 Unsupported Truyền thông Type – Không tương trợ kiểu Resource này.
- 422 Unprocessable Entity – Tài liệu không được xác thực
- 429 Too Many Requests – Request bị từ chối do bị giới hạn
Nên sử dụng Version
Luôn sử dụng version để khi bạn phải nâng cấp API mà vẫn tương trợ các API cũ.
Xây dựng API với Laravel
Lấy việc xây dựng api trên Laravel để làm ví dụ, trước lúc đi vào ta tổng quan về Http Request.
HTTP Request
HTTP request có tất cả 9 loại method , 2 loại được sử dụng phổ quát nhất là GET và POST
- GET: được sử dụng để lấy thông tin từ server theo URI đã cung cấp.
- HEAD: giống với GET nhưng response trả về không có toàn thân, chỉ có header.
- POST: gửi thông tin tới sever thông qua các biểu mẫu http.
- PUT: ghi đè tất cả thông tin của đối tượng người sử dụng với những gì được trình lên.
- PATCH: ghi đè các thông tin được thay đổi của đối tượng người sử dụng.
- DELETE: xóa tài nguyên trên server.
- CONNECT: thiết lập một kết nối tới server theo URI.
- OPTIONS: mô tả các tùy chọn giao tiếp cho resource.
- TRACE: thực hiện một bài test loop – back theo đường dẫn đến resource.
RESTful Route
Viết Api thì sẽ khai báo router vào file routes/api.php thay vì sử dụng file routes/web.php. Các setting mặc cho file api.php trong laravel:
- Url: những route được khai báo trong file này mặc định có prefix url là api (ví dụ: topdev.vn/api/products)
- Middleware: mặc định sẽ tiến hành gán Middleware Group là api, trong file app/Http/Kernel sẽ thấy 2 middleware thuộc Middleware Group: api là throttle (giới hạn request / time) và bindings (model binding).
Có thể tùy chỉnh giá trị mặc định này trong method mapApiRoutes trong file app/Providers/RouteServiceProvider.php
Tạo các route để thực hiện các thao tác như CRUD (Create, Read, Update, Delete):
// Lấy list sản phẩm Route::get(‘products’, ‘ApiProductController@index’)->name(‘products.index’); // Lấy detail sản phẩm theo id Route::get(‘products/{id}’, ‘ApiProductController@show’)->name(‘products.show’); // Add sản phẩm Route::post(‘products’, ‘ApiProductController@store’)->name(‘products.store’); // Update info sản phẩm theo id # Sử dụng put nếu update toàn bộ các field Route::put(‘products/{id}’, ‘ApiProductController@update’)->name(‘products.update’); # Sử dụng patch nếu update 1 vài field Route::patch(‘products/{id}’, ‘ApiProductController@update’)->name(‘products.update’); // Xóa sản phẩm theo id Route::delete(‘products/{id}’, ‘ApiProductController@destroy’)->name(‘products.destroy’);
Mặc định route đã được gán middleware bindings, nếu muốn sử dụng model binding trong controller thì tất cả chúng ta sửa lại thông số trong route như sau:
Route::get(‘products/{product}’, ‘ApiProductController@show’)->name(‘products.show’); Route::put(‘products/{product}’, ‘ApiProductController@update’)->name(‘products.update’); Route::patch(‘products/{product}’, ‘ApiProductController@update’)->name(‘products.update’); Route::delete(‘products/{product}’, ‘ApiProductController@destroy’)->name(‘products.destroy’);
Ngoài ra trong laravel cũng tương trợ tất cả chúng ta một cách khai báo ngắn gọn hơn:
//Nếu không muốn sử dụng toàn bộ method trong apiResource mọi người dân có thể chỉ định sử dụng 1 vài method bằng hàm only Route::apiResource(‘products’, ‘ApiProductController’)->only([‘index’, ‘show’]); //Hoặc nếu muốn loại bỏ đi 1 số method không dùng thì có thể sử dụng hàm except Route::apiResource(‘products’, ‘ApiProductController’)->except([‘show’, ‘update’]);
Resource Controllers
Tương ứng với những Route RESTful đã khai báo ở trên, đặc biệt quan trọng nếu dùng method apiResource thì laravel cũng tương trợ các method xử lí tương ứng trong controller.
Để tạo ra Resource Controllers tất cả chúng ta chạy lệnh sau
php artisan make:controller Api/ProductController -api
File ProductController tạo ra sẽ như sauvàlt;?php namespace AppHttpControllersApi; use IlluminateHttpRequest; use AppHttpControllersController; class ProductController extends Controller { /** * Display a listing of the resource. * * @return IlluminateHttpResponse */ public function index() { // } /** * Store a newly created resource in storage. * * @param IlluminateHttpRequest $request * @return IlluminateHttpResponse */ public function store(Request $request) { // } /** * Display the specified resource. * * @param int $id * @return IlluminateHttpResponse */ public function show($id) { // } /** * Update the specified resource in storage. * * @param IlluminateHttpRequest $request * @param int $id * @return IlluminateHttpResponse */ public function update(Request $request, $id) { // } /** * Remove the specified resource from storage. * * @param int $id * @return IlluminateHttpResponse */ public function destroy($id) { // } }
Ngoài ra nếu muốn sử dụng model binding khi tạo Resource Controllers thì dùng lệnh phía dưới
php artisan make:controller Api/ProductController -api -model=Models/Product
File ProductController tạo ra sẽ như sau, tất cả chúng ta để ý thông số của không ít method show, update, destroy sẽ thay đổi 1 chút.
<?php namespace AppHttpControllersApi; use AppModelsProduct; use IlluminateHttpRequest; use AppHttpControllersController; class ProductController extends Controller { /** * Display a listing of the resource. * * @return IlluminateHttpResponse */ public function index() { // } /** * Store a newly created resource in storage. * * @param IlluminateHttpRequest $request * @return IlluminateHttpResponse */ public function store(Request $request) { // } /** * Display the specified resource. * * @param AppModelsProduct $product * @return IlluminateHttpResponse */ public function show(Product $product) { // } /** * Update the specified resource in storage. * * @param IlluminateHttpRequest $request * @param AppModelsProduct $product * @return IlluminateHttpResponse */ public function update(Request $request, Product $product) { // } /** * Remove the specified resource from storage. * * @param AppModelsProduct $product * @return IlluminateHttpResponse */ public function destroy(Product $product) { // } }
Demo 1 đoạn code đơn giản trong controller kết phù hợp với model binding và route apiResource khi xây dựng API:
<?php namespace AppHttpControllersApi; use AppHttpControllersController; use AppModelsProduct; use IlluminateHttpRequest; class ProductController extends Controller { /** * Display a listing of the resource. * * @return Product[]|IlluminateDatabaseEloquentCollection */ public function index() { return Product::all(); } /** * Store a newly created resource in storage. * * @param Request $request * @return Product|IlluminateDatabaseEloquentModel */ public function store(Request $request) { return Product::create($request->all()); } /** * Display the specified resource. * * @param Product $product * @return Product */ public function show(Product $product) { return $product; } /** * Update the specified resource in storage. * * @param Request $request * @param Product $product * @return bool */ public function update(Request $request, Product $product) { return $product->update($request->all()); } /** * Remove the specified resource from storage. * * @param Product $product * @throws Exception */ public function destroy(Product $product) { $product->delete(); } }
Mặc định khi sử dụng route apiResource thì tài liệu trả về sẽ tự động hóa được chuyển sang kiểu JSON và sẽ sở hữu được status tương ứng nên chỉ việc return tài liệu ra là được.
Còn nếu muốn tùy biến status trả về thì có thể tham khảo cách phía dưới có sử dụng class IlluminateHttpResponse để lấy status thay vì fix giá trị vào ví dụ như HTTP_OK tương ứng sẽ là 200
<?php namespace AppHttpControllers; use AppModelsProduct; use IlluminateHttpRequest; use IlluminateHttpResponse; class ProductController extends Controller { /** * Display a listing of the resource. * * @return IlluminateHttpJsonResponse */ public function index() { $products = Product::all(); return response()->json($products, Response::HTTP_OK); } } Eloquent Resources
Khi xây dựng API, bạn cũng có thể cần transform tài liệu từ controller trước lúc trả về cho những người dùng ứng dụng của bạn, laravel đã và đang tương trợ điều này với Eloquent Resources
Để tạo ra 1 class chuyển đổi tất cả chúng ta chạy lệnh sau
php artisan make:resource Product
File app/Http/Resources/Product.php sẽ sở hữu được nội dung như sau
<?php namespace AppHttpResources; use IlluminateHttpResourcesJsonJsonResource; class Product extends JsonResource { /** * Transform the resource into an array. * * @param IlluminateHttpRequest $request * @return array */ public function toArray($request) { return parent::toArray($request); } }
Mình sẽ tùy chỉnh tài liệu trả về là chỉ có title và price
<?php namespace AppHttpResources; use IlluminateHttpResourcesJsonJsonResource; class Product extends JsonResource{ /** * Transform the resource into an array. * * @param IlluminateHttpRequest $request * @return array */ public function toArray($request){ return [ ‘title’ => $this->title, ‘price’ => $this->price, ]; } }
Ở controller thì mình sẽ sửa lại như sau
<?php namespace AppHttpControllersApi; use AppHttpControllersController; use AppModelsProduct; use IlluminateHttpRequest; use AppHttpResourcesProduct as ProductResource; class ProductController extends Controller{ /** * Display a listing of the resource. * * @return Product[]|IlluminateDatabaseEloquentCollection */ public function index(){ $products = Product::all(); return ProductResource::collection($products); } /** * Store a newly created resource in storage. * * @param Request $request * @return Product|IlluminateDatabaseEloquentModel */ public function store(Request $request){ $product = Product::create($request->all()); return new ProductResource($product); } /** * Display the specified resource. * * @param Product $product * @return Product */ public function show(Product $product){ return new ProductResource($product); } /** * Update the specified resource in storage. * * @param Request $request * @param Product $product * @return bool */ public function update(Request $request, Product $product){ return $product->update($request->all()); } /** * Remove the specified resource from storage. * * @param Product $product * @throws Exception */ public function destroy(Product $product){ $product->delete(); } }
Ngoài giới hạn tài liệu trả về như title hay price, laravel cũng tương trợ rất nhiều thứ như thêm relationships, data …, mọi người dân có thể đọc thêm docs trên Laravel.
Authorization
Ngày nay có 3 cơ chế Authorize chính:
- HTTP Basic
- JSON Web Token (JWT)
- OAuth2
Tùy thuộc vào service của bạn, mà hãy lựa chọn loại Authorize có mức độ phù hợp, cố gắng nỗ lực giữ nó càng đơn giản càng tốt.
CORS Policy
Viết API thì cũng phải lưu ý về CORS là gì?
API Document
Ai cũng biết việc viết API docs là cấp thiết, tuy nhiên để sở hữu một API docs hoàn chỉnh cũng tiêu tốn khá nhiều thời kì. Nhất là trong lúc dự án gấp rút thì mọi người thường chỉ để API docs ở tại mức siêu cơ bản. Tham khảo thêm cách viết API Document.
API document là một phần tương tự như Unit Test vậy – lấy ngắn để nuôi dài.
Nếu không được chăm sóc kỹ, thì đến lúc maintain hoặc thay đổi spec thì hậu quả sẽ rất thảm khốc, sau này là một số lưu ý lúc viết docs:
- Mô tả đầy đủ về params request: gồm những params nào, datatype, require hay optional.
- Nên đưa ra các ví dụ về HTTP requests và responses với data chuẩn.
- Update Docs thường xuyên, để sát nhất với API có bất kể thay đổi gì.
- Format, cú pháp cần phải nhất quán, mô tả rõ ràng, chuẩn xác.
Tham khảo thêm các việc làm API lương cao quyến rũ tại đây