Web API, thư viện HttpClient, RESTful API, OpenAPI, Swagger

    0

    Giới thiệu về web API

    Trong các bài học trước chúng ta đã làm quen với hệ thống web và giao thức HTTP. Mặc dù ban đầu chỉ là một giao thức truyền văn bản thông thường, HTTP đã phát triển để trở thành một giao thức đa năng, với ý nghĩa là bất kỳ phần mềm nào cũng có thể sử dụng HTTP để truyền tải bất kỳ loại dữ liệu nào. 

    Sự thay đổi này đòi hỏi việc phát triển thành phần server phải thực hiện theo một cách thức khác với ứng dụng web truyền thống. Loại ứng dụng server như vậy được gọi là Web API.

    Web API (Application Programming Interface) là một loại ứng dụng cho phép các ứng dụng khác tương tác với nhau sử dụng giao thức HTTP (hoặc HTTPS).

    Hãy hình dung tình huống như sau: bạn có một cơ sở dữ liệu SQL Server và một ứng dụng mobile. Về nguyên tắc, SQL Server không được “lộ mặt” ra Internet vì lý do an ninh. Các server cơ sở dữ liệu luôn phải nằm trong vùng được bảo vệ chặt chẽ trong hệ thống mạng. Vậy làm thế nào để ứng dụng mobile có thể tương tác với SQL Server?

    Giải pháp là xây dựng một ứng dụng dạng Web API. 

    Do bản thân Web API cũng là một loại ứng dụng web, nó sẽ được triển khai trên web server (thường thuộc vùng DMZ của mạng), và các ứng dụng khác ngoài Internet có thể truy cập vào nó. Khi này, ứng dụng mobile có thể gửi truy vấn HTTP đến Web API. Ứng dụng Web API này khi nhận được yêu cầu sẽ tương tác với cơ sở dữ liệu SQL Server giống như một ứng dụng web thông thường. Tuy nhiên, Web API sẽ chuyển đổi dữ liệu quan hệ nó nhận được về dạng JSON và gửi về cho ứng dụng mobile qua HTTP / HTTPS. Ứng dụng mobile lại chuyển đổi dữ liệu JSON về dạng object riêng của nó và sử dụng như các object cục bộ thông thường. Như vậy, Web API đóng vai trò một ứng dụng trung gian giúp các ứng dụng khác tương tác với nhau, trong đó việc tương tác giữa ứng dụng client với Web API được thực hiện qua giao thức HTTP / HTTPS. Ứng dụng client không biết về sự tồn tại của cơ sở dữ liệu. Nó chỉ nhìn thấy và tương tác với Web API.

    Hãy hình dung một ví dụ khác: bạn có một phần mềm cục bộ có khả năng chuyển đổi văn bản về tiếng nói (gọi là ứng dụng text-to-speech, TTS), và bạn mong muốn để cho một ứng dụng di động có thể sử dụng được dịch vụ TTS này. Giải pháp cũng tương  tự: bạn xây dựng một ứng dụng Web API làm trung gian. Web API nhận yêu cầu (văn bản cần chuyển đổi) từ ứng dụng mobile qua HTTP / HTTPS và gọi tới dịch vụ TTS cục bộ. Kết quả xử lý của TTS sẽ được Web API chuyển trở lại cho ứng dụng mobile. Ứng dụng mobile không biết gì về sự tồn tại của ứng dụng TTS. Mọi thứ nó nhìn thấy chỉ là Web API.

    Mô hình hoạt động của một hệ thống phần mềm mạng sử dụng Web API như vậy được thể hiện trong hình.

    Như vậy, trong ứng dụng dạng Web API, web server và client đã biến đổi rất nhiều, khác biệt với môi trường web truyền thống (cũng thường được gọi là ứng dụng Web HTML):

    • Thành phần server không còn cung cấp dữ liệu ở dạng HTML. Thay vào đó, server sinh ra dữ liệu ở các định dạng như JSON, XML, BSON. Dữ liệu này được đóng gói vào gói tin phản hồi HTTP và trả về client.
    • Thành phần client nhận dữ liệu JSON/XML sẽ chuyển đổi về dạng object của riêng mình và xử lý các object đó theo đúng cách nó làm với dữ liệu cục bộ, như hiển thị ra bảng, hiển thị trên form.
    • Thành phần client cũng có khả năng đóng gói các object cục bộ của nó vào truy vấn HTTP để gửi lại server. 

    Hiện nay, hầu hết các framework hỗ trợ phát triển ứng dụng Web HTML cũng đồng thời hỗ trợ phát triển ứng dụng Web API.

    Trên nền tảng .NET sử dụng công nghệ Asp.net Core cho phát triển cả ứng dụng Web HTML cũng như Web API. Bên trên Asp.net Core là 4 mô hình phát triển ứng dụng khác nhau: MVC, Razor Pages, Web API, Blazor. Trong đó, MVC và Razor Pages dùng cho phát triển ứng dụng web HTML, Blazor dành cho phát triển ứng dụng đơn trang.

    Lưu ý: .NET và .NET Framework là hai nền tảng phát triển (và thực thi) ứng dụng khác nhau. .NET chạy đa nền tảng, còn .NET Framework dành riêng cho Windows. Framework cho phát triển ứng dụng web trên .NET Framework có tên gọi là Asp.net, còn framework cho phát triển ứng dụng web trên .NET có tên gọi là Asp.net Core. .NET Framework và Asp.net là nền tảng đã cũ và hiện không được khuyến khích sử dụng cho các dự án mới. Trong bài học này chúng ta sẽ chỉ nói tới Asp.net Core trên .NET mới.

    Thư viện HttpClient

    HttpClient là một thư viện trong .NET được sử dụng để tạo các truy vấn HTTP cũng như hỗ trợ gửi và nhận các yêu cầu HTTP từ các ứng dụng .net. Thư viện này cung cấp lớp HttpClient để tạo và gửi các yêu cầu HTTP đến các máy chủ web, và nhận phản hồi từ máy chủ. 

    Một số tính năng của thư viện này là:

    • Cho phép tạo ra các đối tượng HttpClient để gửi các yêu cầu HTTP đến một địa chỉ URL xác định.
    • Hỗ trợ các phương thức HTTP phổ biến như GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS.
    • Hỗ trợ các loại nội dung khác nhau như chuỗi, byte, form-data, json, xml.
    • Hỗ trợ các kết nối bảo mật SSL/TLS và chứng chỉ số.
    • Hỗ trợ các kỹ thuật nâng cao như bộ đệm, hủy bỏ, chuyển hướng, cookie, proxy.
    • HttpClient có thể được khởi tạo một lần và sử dụng nhiều lần cho các yêu cầu khác nhau, giúp tối ưu hóa hiệu suất và tài nguyên.
    • Cung cấp các phương thức đồng bộ và bất đồng bộ để gửi và nhận dữ liệu.
    • HttpClient cho phép tùy chỉnh các thông số như thời gian chờ, tiêu đề, cookie và xác thực.

    Thư viện HttpClient hoạt động trên nền tảng .NET mới và do đó có thể được sử dụng trong các ứng dụng .net trên nhiều nền tảng khác nhau, bao gồm Windows, Linux và macOS.

    Chúng ta sẽ cùng tìm hiểu một số kỹ thuật cơ bản nhất về cách làm việc với thư viện này để giải thích cho ví dụ đã thực hiện trong bài học trước.

    Khởi tạo HttpClient

    Để khởi tạo đối tượng của HttpClient, chúng ta sử dụng cú pháp quen thuộc của C#:

    var client = new HttpClient();

    Tiếp theo chúng ta phải chỉ định địa chỉ cơ sở của server qua thuộc tính BaseAddress như sau:

    client.BaseAddress = new Uri("<a href="https://localhost:7074/">https://localhost:7074/</a>");

    Địa chỉ cơ sở là đường dẫn tuyệt đối tới dịch vụ API của server. Ví dụ, thường ứng dụng Web API sẽ có đường dẫn kiểu https://example.com/api/. Về sau, khi gửi truy vấn tới API (khi gọi các phương thức như GetAsync, PostAsync, PutAsync, DeleteAsync), HttpClient sẽ tự động ghép đường dẫn tương đối tới từng tài nguyên với địa chỉ gốc. Bạn không cần chỉ định đường dẫn tuyệt đối tới từng tài nguyên.

    Địa chỉ cơ sở của server phải là một địa chỉ URL hợp lệ và kết thúc bằng dấu gạch chéo (/). Nếu máy chủ đang chờ kết nối ở cổng mặc định 80 thì không cần chỉ định số cổng sau domain name.

    Khi làm việc với Web API, bạn cần chỉ định loại dữ liệu mong muốn nhận được bằng lệnh sau:

    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    Hai lệnh này sẽ xóa bỏ những gì đang có trong dòng tiêu đề của truy vấn HTTP, đồng thời chỉ định dòng tiêu đề Content-Type = application/json trong vùng tiêu đề của truy vấn. Lệnh thứ hai chỉ định rằng truy vấn này mong muốn nhận dữ liệu ở định dạng JSON. Khi server đọc tiêu đề này nó sẽ chuyển đổi dữ liệu sang dạng JSON trước khi đóng gói vào phản hồi HTTP.

    Đến đây bạn đã có thể sử dụng đối tượng client vừa tạo để phát truy vấn và nhận phản hồi.

    Thực thi truy vấn Get

    Truy vấn Get là loại truy vấn lấy dữ liệu thường dùng nhất khi làm việc với Web API. Khi sử dụng HttpClient, truy vấn Get được thực hiện qua phương thức GetAsync như sau:

    HttpResponseMessage response = await client.GetAsync("weatherforecast");

    Cần lưu ý rằng, gần như tất cả các phương thức truy vấn dữ liệu trong HttpClient đều là phương thức bất đồng bộ (có hậu tố Async). Vì vậy, bạn cần sử dụng kỹ thuật lập trình bất đồng bộ theo mô hình TAP với từ khóa await trước các phương thức này. 

    Phương thức chứa lời gọi này cần đặt từ khóa async. Trong ví dụ ở phần trước, chúng ta sử dụng phiên bản bất đồng bộ của phương thức Main:

    static async Task Main(string[] args) { … }

    Lưu ý rằng, phiên bản bất đồng bộ của phương thức Main chỉ sử dụng được trên C# phiên bản 7 về sau. Các phiên bản trước không hỗ trợ tính năng này.Tham số của phương thức GetAsync là đường dẫn tương đối tới controller của API cung cấp dịch vụ tương ứng. Trong ví dụ trên, đường dẫn này là weatherforecast, được chỉ định khi tạo API bằng attribute [HttpGet(Name = "GetWeatherForecast")] trước action tương ứng của controller. Ở đây chúng ta không cần chỉ định đường dẫn đầy đủ vì ở bước khởi tạo HttpClient, chúng ta đã cung cấp đường dẫn cơ sở. HttpClient sẽ tự động ghép nối đường dẫn tương đối với đường dẫn cơ sở để tạo ra Url đầy đủ cho truy vấn.

    Xử lý kết quả truy vấn Get

    Truy vấn Get với Web API trả về kết quả là chuỗi JSON cùng với các thông tin khác. Chúng ta phải xử lý để lấy kết quả ra để sử dụng trong chương trình.

    HttpClient tự động phân tích gói tin phản hồi của HTTP và tách các phần của gói phản hồi này để tạo ra các object tương ứng:

    • Toàn bộ phản hồi HTTP được dùng để tạo ra object của lớp HttpResponseMessage.
    • Phần thân của phản hồi HTTP sẽ được dùng để tạo ra một object kiểu HttpContent. Object này được đặt vào thuộc tính Content của lớp HttpResponseMessage.

    Do đó, để lấy được chuỗi JSON chứa trong phần thân của phản hồi HTTP, chúng ta gọi phương thức ReadAsStringAsync của HttpContent như sau:

    var data = await response.Content.ReadAsStringAsync();

    Sau lệnh này, biến data sẽ chứa chuỗi kết quả dạng JSON do server trả về.

    Để sử dụng được trong chương trình, chúng ta cần chuyển đổi chuỗi JSON này về 1 đối tượng của chương trình C#. Có nhiều thư viện hỗ trợ chuyển đổi chuỗi JSON. Trong ví dụ trên chúng ta sử dụng thư viện của NewtonSoft. Đây là bộ thư viện JSON thông dụng nhất trong .NET mà chúng ta đã từng làm quen trong bài học về trình tự hóa dữ liệu.

    Để chuyển đổi chuỗi JSON về đối tượng, chúng ta cần có kiểu dữ liệu class tương ứng với kiểu dữ liệu trên server. Trong trường hợp này, kiểu dữ liệu ban đầu trên server là WeatherForecast. Vì vậy, chúng ta tạo ra một bản sao của kiểu dữ liệu này trên client. 

    Ở đây cần lưu ý rằng, nếu hai dự án cùng sử dụng .NET thì chúng ta hoàn toàn có thể đặt các lớp thực thể (như WeatherForecast) vào một dự án thư viện dùng chung. Nhưng nếu client sử dụng một nền tảng khác (như JavaScript), chúng ta bắt buộc phải tạo class riêng trên client theo ngôn ngữ đang sử dụng.

    Việc chuyển đổi chuỗi JSON về đối tượng của C# được thực hiện qua phương thức Deserialize của lớp JsonConvert như sau:

    var weatherForecasts = JsonConvert.DeserializeObject&lt;List&lt;WeatherForecast&gt;&gt;(data);

    Đến đây, chúng ta có thể sử dụng biến weatherForecasts trong các lệnh xử lý dữ liệu tiếp theo như một đối tượng cục bộ thông thường. Trong ví dụ này, weatherForecasts là một đối tượng chứa mảng động các phần tử có kiểu là WeatherForecast. Chúng ta chỉ xử lý đơn giản là in mảng động này ra màn hình.

    Các loại truy vấn khác

    HttpClient cho phép thực thi tất cả các loại truy vấn HTTP qua các phương thức có tên tương ứng như PostAsync, PutAsync, DeleteAsync. 

    Để thực hiện các truy vấn này yêu cầu Web API phải cung cấp các phương thức action tương ứng. Trong ví dụ đơn giản của chúng ta không thực thi các action này. Do đó ở chương trình client chúng ta không thực hiện được 3 loại truy vấn Post, Put và Delete.

    Như chúng ta đã biết, mỗi loại truy vấn này yêu cầu dữ liệu đóng gói dữ liệu theo một cách khác nhau. Do vậy, chúng ta cần tìm hiểu riêng rẽ cách thực hiện đóng gói cho từng loại truy vấn.

    Do đây là một bài học mang tính chất giới thiệu khái niệm và kiến thức cơ sở, chúng ta không đi sâu vào kỹ thuật làm việc với Web API. Thực tế, nội dung liên quan đến xây dựng ứng dụng với Web API đòi hỏi cả một môn học riêng biệt.

    RESTful API

    REST là viết tắt của Representational State Transfer, tạm dịch là chuyển trạng thái biểu diễn của dữ liệu. REST là một nguyên lý kiến trúc phần mềm cho các hệ thống phân tán, đặc biệt là các ứng dụng web. REST được đề xuất bởi Roy Fielding vào năm 2000 trong luận án tiến sĩ của ông. 

    Mục tiêu của REST là đơn giản hóa và chuẩn hóa việc thiết kế và phát triển các ứng dụng web bằng cách sử dụng các giao thức và tiêu chuẩn đã có sẵn trên Internet. REST cũng nhấn mạnh vào tính khả chuyển (interoperability), khả năng mở rộng (scalability) và hiệu suất (performance) của các hệ thống phân tán.

    REST đưa ra các nguyên tắc thiết kế cơ bản như:

    • Mỗi tài nguyên (resource) được xác định duy nhất bởi một định danh (identifier), thường là một URL.
    • Các tài nguyên có thể được truy xuất, tạo, cập nhật hoặc xóa (các thao tác CRUD) bằng cách sử dụng các phương thức HTTP chuẩn như GET, POST, PUT hoặc DELETE.
    • Các tài nguyên có thể được biểu diễn bằng nhiều định dạng khác nhau, ví dụ như XML, JSON, HTML hoặc plain text.
    • Các tài nguyên có thể có các liên kết (hyperlinks) với các tài nguyên khác để tạo thành một mạng lưới thông tin.

    Restful API là một loại ứng dụng Web API được xây dựng tuân thủ theo kiến trúc REST. Cần lưu ý rằng, ứng dụng dạng Web API không nhất thiết phải tuân thủ kiến trúc REST. Và không nhất thiết rằng RESTful API tốt hơn Web API thông thường. Tuy nhiên, do kiến trúc REST được chuẩn hóa tốt hơn, RESTful API thường sẽ tốt hơn nếu nó cung cấp dịch vụ công cộng cho nhiều đối tượng sử dụng. Nếu chỉ sử dụng trong nội bộ thì không có gì khác biệt giữa hai loại API.

    Asp.net Core được thiết kế chuyên để xây dựng RESTful Web API. Vì vậy, mặc định Web API do bạn xây dựng trên nền tảng này đều tuân thủ nguyên tắc thiết kế của REST. Ví dụ bạn đã thực hiện ở phần thực hành chính là một RESTful API.

    OpenAPI

    Khái niệm OpenAPI

    OpenAPI là một loại đặc tả dành cho việc định nghĩa và diễn đạt RESTful APIs. OpenAPI cho phép các nhà phát triển và người dùng biết được các chức năng, tham số, định dạng và phản hồi của một API một cách rõ ràng và chuẩn xác. 

    OpenAPI là một chuẩn giao tiếp giữa các ứng dụng phần mềm dựa trên RESTful API. Được phát triển bởi OpenAPI Initiative (OAI), OpenAPI định nghĩa cách tài nguyên của một ứng dụng được truy cập và sử dụng thông qua giao thức HTTP.

    Với OpenAPI, một ứng dụng có thể được mô tả dưới dạng một tập hợp các tài nguyên, mỗi tài nguyên có một URI riêng và một tập hợp các thao tác như GET, POST, PUT, PATCH, DELETE, và nhiều hơn nữa. Các tài nguyên này được truy cập thông qua các địa chỉ URI và các thao tác được định nghĩa bởi OpenAPI, giúp đảm bảo tính đúng đắn và nhất quán của các giao tiếp giữa các ứng dụng.

    OpenAPI cũng cho phép các nhà phát triển định nghĩa các tham số và kiểu dữ liệu cho các yêu cầu và phản hồi của API. Điều này giúp đảm bảo tính nhất quán và đúng đắn của các giao tiếp giữa các ứng dụng.

    OpenAPI đã trở thành một trong những chuẩn giao tiếp phổ biến nhất giữa các ứng dụng RESTful API. Nó đã được sử dụng trong nhiều dự án lớn và được hỗ trợ bởi nhiều công cụ và framework khác nhau. Điều này giúp đơn giản hóa quá trình phát triển và tích hợp giữa các ứng dụng khác nhau, đồng thời tăng tính khả dụng và tiện lợi cho người dùng cuối.

    Một trong những ưu điểm của OpenAPI là khả năng tạo ra tài liệu API tự động và tự động sinh mã. Với OpenAPI, mô tả API được định nghĩa dưới dạng các tài liệu, chẳng hạn như các tệp YAML hoặc JSON. Những tài liệu này có thể được sử dụng để tạo ra các tài liệu hướng dẫn, giúp người phát triển hiểu rõ cách sử dụng các API, cũng như sinh ra mã cho việc phát triển các ứng dụng trên các nền tảng khác nhau.

    Swagger

    Swagger là một công cụ do SmartBear Software phát triển cho phép người dùng tạo ra tài liệu API tự động. Swagger giúp người phát triển dễ dàng tạo ra các tài liệu hướng dẫn, cho phép người dùng hiểu rõ cách sử dụng các API, cũng như sinh ra mã cho việc phát triển các ứng dụng trên các nền tảng khác nhau.

    Swagger cũng cho phép các nhà phát triển định nghĩa các tham số và kiểu dữ liệu cho các yêu cầu và phản hồi của API, giúp đảm bảo tính nhất quán và đúng đắn của các giao tiếp giữa các ứng dụng.

    Swagger định nghĩa các API dưới dạng các tài liệu YAML hoặc JSON, giúp đơn giản hóa quá trình phát triển và tích hợp giữa các ứng dụng khác nhau. Nó cung cấp cho người phát triển một giao diện người dùng trực quan để tạo và chỉnh sửa các tài liệu API, giúp tiết kiệm thời gian và nâng cao tính linh hoạt trong việc phát triển.

    Swagger cũng hỗ trợ kiểm thử API tự động, giúp người dùng kiểm tra tính đúng đắn của các API một cách tự động và hiệu quả. Nó cũng cung cấp cho người dùng khả năng tạo ra tài liệu API tương thích với nhiều ngôn ngữ lập trình khác nhau, đảm bảo tính khả dụng và tiện lợi cho người dùng cuối.

    Swagger đã trở thành một công cụ rất phổ biến trong việc tạo và quản lý các tài liệu API, được sử dụng rộng rãi trong nhiều dự án phát triển phần mềm lớn. Các công cụ khác như Postman, Insomnia, và Stoplight cũng sử dụng các tài liệu Swagger để quản lý API và hỗ trợ việc tích hợp giữa các ứng dụng khác nhau.

    Ban đầu Swagger là một dự án riêng rẽ. Năm 2015, Swagger được chuyển sang cho OAI. Từ đó Swagger cũng được gọi là OpenAPI. Hiện nay tên gọi Swagger và OpenAPI được sử dụng song song. Khi cần thiết, người ta dùng thuật ngữ OpenAPI để nói về chuẩn đặc tả, còn Swagger để nói về công cụ tạo tài liệu API theo chuẩn OpenAPI.

    OpenAPI và Swagger trên Asp.net Core

    Mặc định Asp.net Core không trực tiếp hỗ trợ OpenAPI. Chúng ta cần cài đặt thêm một số gói thư viện từ NuGet để làm việc với OpenAPI trên Asp.net Core, bao gồm:

    • Swashbuckle.AspNetCore: một thư viện hỗ trợ việc tạo ra các tài liệu OpenAPI từ các API web asp.net core.
    • Microsoft.OpenApi: một thư viện cung cấp các lớp đại diện cho các thành phần của OpenAPI, như đối tượng, tham số, phản hồi, v.v.
    • NSwag.AspNetCore: một thư viện hỗ trợ việc sinh ra các mã nguồn khách hàng (client) và máy chủ (server) từ các tài liệu OpenAPI.

    Sau khi cài đặt các gói nuget này, chúng ta có thể tiến hành cấu hình OpenAPI trên asp.net core. Có hai bước chính là:

    • Thêm middleware Swashbuckle.AspNetCore vào pipeline xử lý yêu cầu (request) của ứng dụng web. Middleware này sẽ tự động sinh ra các tài liệu OpenAPI từ các API web asp.net core và cung cấp một giao diện người dùng (UI) để xem và thử nghiệm các API web.
    • Thêm thuộc tính (attribute) [OpenApi] vào các phương thức (method) của các lớp điều khiển (controller) để chỉ định các thông tin chi tiết về các API web, như mô tả, tham số, phản hồi, v.v.

    Trong ví dụ ở phần đầu, thực tế chúng ta cũng đã xây dựng Web API theo chuẩn OpenAPI và tích hợp Swagger. Khi chạy ứng dụng, giao diện Swagger cũng thể hiện trên trình duyệt:

    + Nếu bạn thấy site hữu ích, trước khi rời đi hãy giúp đỡ site bằng một hành động nhỏ để site có thể phát triển và phục vụ bạn tốt hơn.
    + Nếu bạn thấy bài viết hữu ích, hãy giúp chia sẻ tới mọi người.
    + Nếu có thắc mắc hoặc cần trao đổi thêm, mời bạn viết trong phần thảo luận cuối trang.
    Cảm ơn bạn!

    Kết luận

    Theo dõi
    Thông báo của
    guest

    0 Thảo luận
    Phản hồi nội tuyến
    Xem tất cả bình luận