# Lesson 1 -  Web service

## Tổng quan về Web service

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/mAB5iyGJ2RNBteuMYdLc/web-service.webp" alt=""><figcaption></figcaption></figure>

Là tập hợp các ***giao thức*** và ***tiêu chuẩn*** mở được sử dụng để trao đổi dữ liệu giữa các ứng dụng hoặc giữa các hệ thống, giúp việc liên lạc giữa các hệ thống trở nên dễ dàng hơn.

{% hint style="info" %}
Để giải thích cho "giao thức" và "tiêu chuẩn", trước tiên ta sẽ cần biết về mô hình Client-Server
{% endhint %}

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/16D21pDLKvt26zwMnPpk/Client-server-model.svg.png" alt=""><figcaption><p>Hình ảnh mô hình</p></figcaption></figure>

* Clients: là các ứng dụng, thiết bị phía máy khách, sử dụng để tương tác, tổ chức giao tiếp giữ người dùng và máy chủ (Server) bằng tiếp nhận và gửi lên yêu cầu (**Request**) và nhận kết quả (**Response**) từ máy chủ (Server) thông qua các giao thức.
* Server: máy chủ, là nơi nhận các thông tin yêu cầu (**Request**) được gửi lên từ Clients, xử lý và trả về thông tin xử lý (**Response**) cho Clients

Vậy,

* Giao thức: là cách thức để client giao tiếp với server và giao thức phổ biến hiện nay là  giao thức **HTTP (HyperText Transfer Protocol).**

{% hint style="info" %}
Ta sẽ có định nghĩa gọi là Phương thức (Method) khi làm việc với HTTP gọi là Phương thức HTTP Request
{% endhint %}

* Tiêu chuẩn: là các quy định chặt chẽ, yêu cầu phải tuân thủ, trong nội dung học này, chính là các tiêu chuẩn cho giao thức. Xuyên suốt khoá học ta sẽ thực hiện với chuẩn [**RESTful API**](http://surl.li/ldcsz) và sử dụng **MERN Stack** để thể hiện mô hình Client-Server.

## MERN Stack

MERN Stack là gì?

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/HP5qYGVjf3EYxdVoN4a7/mern.png" alt=""><figcaption><p>MERN Stack</p></figcaption></figure>

Lý do lựa chọn: MERN Stack là 1 Javascript Stack, nó giúp việc sử dụng dễ dàng hơn, nhanh chóng hơn, giúp mở rộng dự án, thích ứng về mặt dữ liệu nhanh chóng trong quá trình xây dựng ứng dụng Web fullstack với 4 công nghệ: MongoDB, ExpressJs, ReactJs, NodeJs.

Tài liệu đọc thêm: <http://surl.li/ldgrp>

> Vai trò, cách sử dụng của các Stack ta sẽ được học qua các nội dung học tiếp theo

## NodeJs

Sau khi đã hiểu về MERN Stack, ta sẽ cần phải giải quyết vấn đề đầu tiên, NodeJs sẽ đóng vai trò gì trong đây?

**Vai trò**:

* Là 1 môi trường thực thi các chương trình viết bằng Javascript, cho phép người dùng thực thi Javascript phía Server (ngoài trình duyệt)

  <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/qZCG6uWTPLr8fMGaHOXW/Screenshot%202023-09-15%20at%2015.12.54.png" alt=""><figcaption><p>Minh hoạ sử dụng Js với Browser và Terminal</p></figcaption></figure>

* Cho phép lựa chọn, cài đặt các gói thư viện miễn phí với Node Package Manager (NPM)

* NPM: là 1 chương trình quản lý thư viện ngầm định trong NodeJs, giúp tổ chức, cài đặt các thư viện Javascript cho NodeJs. Tải NodeJs phiên bản LTS tại: <https://nodejs.org/en>

  *Lưu ý: NPM với các phiên bản khác nhau, sẽ gây ảnh hưởng mức tương đối tới dự án, vậy ta sẽ cần phải có trình quản lý phiên bản của NPM là NVM, nó sẽ giúp cài đặt và linh hoạt thay đổi phiên bản NPM trên máy khi cần thiết.*

  1. **Đối với Window**
     1. Truy cập: <https://github.com/coreybutler/nvm-windows/releases>
     2. Lựa chọn file tương ứng (Recommend: nvm-noinstall.zip):&#x20;

        <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/cmvDIwkK7jRwsQ7z43Nw/image.png" alt=""><figcaption><p>Các gói cài đặt</p></figcaption></figure>

  2. **Đối với Mac** (Cần phải cài đặt HomeBrew trước, hướng dẫn: <http://surl.li/ldibi>)
     1. Mở terminal
     2. Chạy câu lệnh:

        `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash`
     3. Sau khi chạy xong, thử kiểm tra các phiên bản NodeJs đã cài dặt với NVM với lệnh:

        `nvm list hoặc nvm ls`&#x20;

        <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/3G6oDJhpqBFkWog9Otoq/image.png" alt=""><figcaption></figcaption></figure>
     4. Sử dụng phiên bản NodeJs với lệnh

        `nvm use`` `*`version  | Ví dụ: nvm use 8.10.0`*

## Javascript với NodeJs

Thực thi các chương trình Javascript với NodeJs.

Để thực thi chương trình Javascript với NodeJs, ta sẽ cần sử dụng câu lệnh như sau:

`node`` `*`file path`*

*Ví dụ:*

`node ./index.js`

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/dqJaZTfeUdH6IcV04TZj/image.png" alt=""><figcaption><p>Chạy file với lệnh node</p></figcaption></figure>

{% hint style="info" %}
Lưu ý:

* Dấu "**."** thể hiện vị trí đang trỏ hiện tại
* Dấu "/" giúp xác định file hoặc folder nào cần sử dụng
* "./" truy xuất tới file hoặc folder cùng cấp với vị trí đang trỏ hiện tại
* "../" truy xuất ngược ra phía bên ngoài folder vị trí đang trỏ hiện tại
* Đối với truy xuất file, folder cùng cấp, có thể không cần dùng, chỉ cần gõ tên file hoặc folder

Link đọc thêm: <https://docs.oracle.com/javase/tutorial/essential/io/path.html>
{% endhint %}

> Các đoạn chương trình khác sẽ thực hiện tương tự, tuy nhiên cần phải lưu ý, đối với các câu lệnh hay các module dùng trên trình duyệt sẽ không thể thực thi được, vì ta không dùng trình duyệt để làm môi trường chạy Javascript

## Module trong Javascript

Module là các file chứa code trong Javascript, sẽ làm các nhiệm vụ riêng biệt và giúp linh hoạt sử dụng các function trong đó ở nhiều file khác nhau.

*Làm thế nào để sử dụng các function của 1 file cho các file khác?*

Bản chất các file là riêng biệt, không thể liên quan được đến nhau, nhưng ta sẽ cho phép file khác sử dụng function của 1 file trong NodeJs.

Ví dụ:&#x20;

![](https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/Hxm61QjknEWzMkSqDe00/image.png)

`utils.js`

<pre class="language-javascript"><code class="lang-javascript">let formatPhoneNumber = (str) => {
    //Filter only numbers from the input
    let cleaned = ('' + str).replace(/\D/g, '');
    //Check if the input is of correct length
    let match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
    if (match) {
        return '(' + match[1] + ') ' + match[2] + '-' + match[3]
    };
    return null;
};

// cú pháp xuất
// module.exports = hàm hoặc giá trị nào muốn xuất để các file khác có thể sử dụng
<strong>// ví dụ: 
</strong><strong>module.exports = {
</strong>    formatPhoneNumber
};
</code></pre>

Lúc này, tất cả các file khác đều có thể sử dụng hàm `formatPhoneNumber` sau khi được dùng cúp pháp module.exports

`index.js`

Tại file index.js, ta muốn sử dụng module của utils, ta sẽ dùng cú pháp required("file path")

<pre class="language-javascript"><code class="lang-javascript"><strong>const utils = require('./utils.js');
</strong>
const format = utils.formatPhoneNumber('2345678900');
console.log(format);
// (234) 567-8900
</code></pre>

{% hint style="info" %}
Với cú pháp exports trên, giá trị là 1 object, có field là formatPhoneNumber và giá trị là hàm xử lý formatPhoneNumber.

Vậy khi tạo biến a = require('...'), a lúc này sẽ là object đó.
{% endhint %}

Từ phiên bản ES6 trở đi, chúng ta sẽ có thể dùng cú pháp thân thiện và phổ biến hơn là import, export.

Ví dụ:

```javascript
// import
import React from 'react';
// export
export default App;
```

Tuy nhiên, với NodeJs, ta sẽ cần phải làm 1 bước định nghĩa module cho project, ta mới có thể sử dụng được và đây cũng là cách khởi tạo 1 dự án NodeJs với NPM

1. Tạo một folder và mở bằng VS Code

   <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/RT2l7AjXQ4JXFxaWOrAA/image.png" alt=""><figcaption><p>Folder tên Server</p></figcaption></figure>

2. Bật terminal và trỏ tới folder server trong VS Code

   <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/v2obGpFZcPgyNVvTMvWI/image.png" alt=""><figcaption><p>Trỏ tới folder với lệnh cd</p></figcaption></figure>

3. Sử dụng lệnh npm init và lựa chọn các cấu hình được yêu cầu (Bấm Enter để bỏ qua, lựa chọn mặc định cho tới khi hết yêu cầu)

   <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/qkZaFUKgUPdjOPyybsQT/image.png" alt=""><figcaption></figcaption></figure>

4. Ta sẽ có 1 file package.json như sau

   <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/O3N25glja40bRh1ciVRc/image.png" alt=""><figcaption><p>File package.json được tạo ra</p></figcaption></figure>

{% hint style="info" %}
File package.json sử dụng giống như 1 bản kê khai các thiết lập, thư viện và nhiều thứ khác được sử dụng trong ứng dụng. Đọc thêm tại [Link](https://codestus.com/posts/kien-thuc-co-ban-ve-file-packagejson)
{% endhint %}

5. Khai báo module mặc định trong file package.json cho file js trong dự án

   ```json
   {
     "name": "server",
     "version": "1.0.0",
     "description": "",
     "main": "index.js",
     // dòng khai báo module
     "type": "module",
     "scripts": {
       "test": "echo \"Error: no test specified\" && exit 1"
     },
     "author": "",
     "license": "ISC"
   }
   ```

Lúc này, ta sẽ có thế sử dụng cú pháp export hoặc import của ES6 trong dự án.

Ví dụ:

`utils.js`

```javascript
let formatPhoneNumber = (str) => {
    //Filter only numbers from the input
    let cleaned = ('' + str).replace(/\D/g, '');
    //Check if the input is of correct length
    let match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
    if (match) {
        return '(' + match[1] + ') ' + match[2] + '-' + match[3]
    };
    return null;
};

// cú pháp xuất
// module.exports = hàm hoặc giá trị nào muốn xuất để các file khác có thể sử dụng
// ví dụ: 
// module.exports = {
//  formatPhoneNumber
// };
// trường hợp chỉ muốn export cụ thể 1 giá trị nào đó, ta chỉ cần dùng cú pháp
// export giá trị cần export

const PI=3.14;
export PI;
export default formatPhoneNumber;
```

<mark style="color:red;">**Lưu ý**</mark>: chỉ được phép export default 1 lần duy nhất

`index.js`

```javascript
// đối với export default
import formatPhoneNumber from './utils.js';
// đổi với export cụ thể
import {PI} from './utils.js';
// hoặc lồng 2 cách import lại
import formatPhoneNumber, {PI} from './utitls.js';
```

Các cú pháp khác tham khảo thêm tại [Link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)

{% hint style="info" %}
Vậy, để tiện lợi cho quá trình học và xây dựng, ta sẽ sử dụng cú pháp module ES6 phía trên
{% endhint %}

## Khởi tạo Server với NodeJs

NodeJs cung cấp module giúp chúng ta có thể truyền tải dữ liệu qua giao thức HTTP tên là **http**

Cú pháp sử dụng

```javascript
import http from 'http';
```

Để khởi tạo Server với module http ta sẽ cùng xem đoạn code phía dưới và chú thích

```javascript
import http from 'http';
// createServer là phương thức giúp chúng ta khởi tạo 1 Server với giao thức http
// và sẽ giúp xử lý các request và response cho client
const app = http.createServer();
// để lăng nghe được, ta cần sử dụng phương thức listen
// và có 2 tham số truyền vào
// app.listen(Cổng khởi tạo, callback Function)
// callback Function sẽ được thực thi sau khi server được khởi tạo thành công
app.listen(8080, () => {
    console.log('Server is running!');
})
```

Thực thi chương trình

```
trankhoa@Air-cua-Tran-2 server % node ./index.js
Server is running!
```

{% hint style="info" %}
Chúng ta có thể thấy, màn hình của terminal hiển thị "Server is running!" và  ứng dụng đang được **chạy liên tục** mà không **hề ngắt.** Để nhận biết ứng dụng bị ngắt ta chỉ cần thấy có 1 dòng  hiển thị path của dự án ngay phía bên dưới, đó là dấu hiệu ứng dụng bị ngắt

<img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/7zLnZtbcBkYKN3u88B3s/image.png" alt="" data-size="original">
{% endhint %}

Vậy lý do tại sao chương trình khi được chạy lại không tự ngắt?

Khi gọi phương thức **listen**, Server sẽ **liên tục** lắng nghe các request được gửi lên từ client

Lưu ý:

* Khi gọi **listen** và thực thi thành công, ứng dụng đã được nạp tất cả các logic trước đó và chỉ đợi khi có request tương ứng, thì sẽ xử lý.
* Trong quá trình xây dựng (dev tại local) **luôn phải** **tắt** Server và **khởi động lại** khi có logic mới được thêm (Ta sẽ được học cách xử lý vấn đề này ở bài sau).
* Chủ động ngắt server local bằng cách Ctrl + c hoặc Command + c trên terminal

## Khởi tạo request với http.clientRequest

Sau khi tạo xong Server với phương thức createServer, ta nhận thấy rằng Server vẫn đang được chạy, nhưng không thấy logic xử lý request được gửi lên ở đâu.

Vậy làm thế nào để ta thiết lập logic tiếp nhận và xử lý request?

Phương thức createServer() sẽ cho phép chúng ta truyền một callback function, callback này nhận đầu vào lần lượt là request, response.

```javascript
import http from 'http';
const app = http.createServer((request, response) => {

});

app.listen(8080, () => {
    console.log('Server is running!');
});
```

GIải thích:

* request: là tham số đầu vào, nhận các thông tin được gửi lên từ client
* response: là tham số, hỗ trợ cho server trả về kết quả cho client

Ví dụ:

```javascript
import http from 'http';
const app = http.createServer((request, response) => {
    response.end("Hello mindX");
});

app.listen(8080, () => {
    console.log('Server is running!');
})
```

Lúc này, ta sẽ có thể gọi tới server bằng trình duyệt với url: <http://localhost:8080> và nhận kết quả.

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/NkF7d2zXlEVRz2eEo5jo/image.png" alt=""><figcaption><p>Kết quả khi gọi tới server</p></figcaption></figure>

* 8080: là port đã khai báo trong phương thức **listen**
* response.end:&#x20;

  * Là phương thức giúp trả kết quả cho client là các giá trị được truyền trong end như ví dụ phía trên
  * Chỉ chấp nhận tham số truyền vào có kiểu dữ liệu là string (hoặc các dạng về Buffer, Uint8Array)

  \=> Vậy, để có thể truyền được các định dạng data khác, ta có thể truyền dạng string của data đó (có thể truyền cả html), xem ví dụ sau:

  ```javascript
  import http from 'http';
  const app = http.createServer((request, response) => {
      response.end("[1, 2, 3, 4, 5]");
  });

  app.listen(8080, () => {
      console.log('Server is running!');
  });
  ```

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/hd1bEjsPqu8Q2VebRYSZ/image.png" alt=""><figcaption><p>Kết quả</p></figcaption></figure>

&#x20;      Để có thể dễ nhìn, linh hoạt hơn, ta có thể cài đặt tiện ích JSON Formatter tại [Link](https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa).

{% hint style="info" %}
Để an toàn về việc truyền dữ liệu theo string, ta nên dùng cú pháp JSON.stringify. Ví dụ:

```javascript
const app = http.createServer((request, response) => {
    const data = { school: 'MindX Technology' };
    response.end(JSON.stringify(data));
});
```

{% endhint %}

Lưu ý: Trường hợp nếu chúng ta không dùng cú pháp 'end' hoặc logic đang bị đứng ở đoạn nào đó trước 'end' thì request đó sẽ không trả về kết quả gì mà sẽ trong trạng thái **pending.**

Ta thấy rằng, khi truy cập tới đường dẫn: <http://localhost:8080>, thì server đã trả ra kết quả cho chúng ta tương ứng trong phương thức **end.**

*Câu hỏi được đề ra ở đây, đường dẫn kia là gì?*

Ta cùng quay trở lại một chút với giao thức http. Giao thức http giúp kết nối tới các server thông qua địa chỉ IP. localhost (hoặc 127.0.0.1) cũng là 1 địa chỉ IP, là nơi cung cấp các dịch vụ (**service**) cho phía client.

Cùng phân tích thêm về URL tại [Link](https://quantrimang.com/cong-nghe/url-la-gi-158090).

\=> Sử dụng server ta sẽ thông qua URL để gửi request tới server. Trong quá trình học, sử dụng server local thì ta sẽ có base URL: [http://localhost:\*\*PORT](https://mindxschool.gitbook.io/full-stack-web/http:/localhost:**PORT)\*\* (PORT là cổng được khai báo trong **listen**)

\=> Tất cả các client, muốn làm việc với server, sẽ đều cần dùng URL dạng như trên và sẽ có cách gọi là **API**

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/iZXVq0a1IsTDytGRK93H/image.png" alt=""><figcaption><p>Mô tả API</p></figcaption></figure>

\=> Để truy cập vào server như logic đã demo phía trên, ta sẽ sử dụng API là <http://localhost:8080>. Câu hỏi đặt ra, khi truy cập vào API này, ta chỉ có duy nhất một hàm xử lý.

Vậy làm thế nào để ta có thể tạo ra nhiều API cũng như các hàm xử lý tương ứng của chúng (Giống như việc một nhà hàng cần có nhiều nhân viên?).

Để giải quyết vấn đề này, ta cần tìm hiểu về **route** (đường dẫn). Giống như một nhà hàng có nhiều phòng, nhiều tầng, nhiều bàn... để khách hàng có thể sử dụng các dịch vụ được cung cấp tương ứng.

## Route

Route đơn giản chỉ là một đường dẫn định tuyến. Ví dụ:

Đường dẫn:  <https://facebook.com/login>

Ta sẽ có base API là <https://facebook.com> và **path** (đường dẫn) login (sau này sẽ có cách gọi là **API endpoint**), kết hợp lại sẽ thành <https://facebook.com/login>

Trong bài học, ta sẽ cài đặt các **route** (định tuyến) mà server có thể nhận và xử lý.

Đầu tiên, ta có một ví dụ demo như sau:

1. Truy cập vào base API với trình duyệt, sẽ có kết quả

   ```javascript
   import http from 'http';
   const app = http.createServer((request, response) => {
       const data = { school: 'MindX technology school' };
       response.end(JSON.stringify(data));
   });

   app.listen(8080, () => {
       console.log('Server is running!');
   });
   ```

   <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/TS2peKGRUvhi30fp89OD/Screenshot%202023-09-16%20at%2016.50.09.png" alt=""><figcaption><p>Kết quả truy cập</p></figcaption></figure>

2. Truy cập với API: <http://localhost:8080/students> và xem kết quả

   <figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/AtBjv4MK4eCo8zht8iF2/image.png" alt=""><figcaption><p>Kết quả truy cập</p></figcaption></figure>

   Lý do tại sao kết quả trả về vẫn như trước? Đó là vì server chỉ nhận đầu vào duy nhất một **requestListener** và mọi request khi gửi lên với base API sẽ đều vào **requestListener** này.

   Ví dụ:&#x20;

   ```javascript
   import http from 'http';
   // tham số của createServer chính là requestListener
   const app = http.createServer((request, response) => {
      // code ...
   });

   app.listen(8080, () => {
       console.log('Server is running!');
   });
   ```

Làm thế nào để ta định nghĩa được các **route** và các hàm xử lý cho chúng?

Rất đơn giản, ta sẽ kiểm tra các URL được gửi lên ngay trong hàm tham số **requestListener**  (chính là các path (endpoint) mà được truyền trên API).

Cú pháp để lấy endpoint từ request là request.url

```javascript
const app = http.createServer((request, response) => {
    const endpoint = request.url;
    response.end(`Endpoint is ${endpoint}`);
});
```

Kết quả:

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/4yaDTgQfWwvIwXc1RKs8/image.png" alt=""><figcaption><p>Endpoint</p></figcaption></figure>

Như vậy, ta chỉ cần kiểm tra các API tương ứng, để xử lý logic tương ứng là xong rồi.

Cùng xét ví dụ và chú thích dưới đây:

```javascript
import http from 'http';
// data học sinh
const listStudent = [
    {
        id: 1,
        fullName: "Jackie",
        age: 5,
        class: "5A"
    },
    {
        id: 2,
        fullName: "Juli MTP",
        age: 5,
        class: "5A"
    },
    {
        id: 3,
        fullName: "Denis",
        age: 5,
        class: "5B"
    },
]
const app = http.createServer((request, response) => {
    const endpoint = request.url;
    switch (endpoint) {
    // với base endpoint (base API), mặc định base endpoint sẽ là /
        case '/':
            response.end(`Hello MindX`);
            break;
    // với endpoint /students
        case '/students':
            response.end(JSON.stringify(listStudent));
            break;
    // nếu không khớp bất kỳ một endpoint nào
        default:
            response.end(`Error, Notfound API!`);
            break;
    }
});

app.listen(8080, () => {
    console.log('Server is running!');
});
```

## Tổng quan về Method

Method (phương thức) là cách chúng ta dùng API. Giống việc ta có nhiều cách gọi nhân viên phục vụ trong nhà hàng. Để dễ dàng và thống nhất trong khoá học, ta sẽ tìm hiểu các phương thức mà chuẩn RESTful API sử dụng.

* GET
* POST
* PUT
* DELETE

{% hint style="info" %}
Để học tập về các phương thức này và trong khoá học, ta sẽ sử dụng công cụ Postman để thực hiện gọi API và dùng các phương thức, tải công cụ tại [Link](https://www.postman.com/downloads/)
{% endhint %}

Mục đích của các phương thức là giống nhau, đều giúp client gửi request và nhận về response từ server, nhưng ý nghĩa là khác nhau

**GET METHOD**

Phương thức GET có ý nghĩa: Client **chỉ gửi** request vào API này, server sẽ xử lý và trả về kết quả.

`index.js`

```javascript
import http from 'http';
const listStudent = [
    {
        id: 1,
        fullName: "Jackie",
        age: 5,
        class: "5A"
    },
    {
        id: 2,
        fullName: "Juli MTP",
        age: 5,
        class: "5A"
    },
    {
        id: 3,
        fullName: "Denis",
        age: 5,
        class: "5B"
    },
]
const app = http.createServer((request, response) => {
    const endpoint = request.url;
    switch (endpoint) {
        case '/':
            response.end(`Hello MindX`);
            break;
        case '/students':
            response.end(JSON.stringify(listStudent));
            break;

        default:
            response.end(`404 Notfound`);
            break;
    }
});

app.listen(8080, () => {
    console.log('Server is running!');
});
```

{% hint style="info" %}
**Chỉ gửi** ở đây, giống như chỉ là truy cập vào đường dẫn, ví dụ dùng browser truy cập vào đường dẫn. Cách này, dùng với browser chính là sử dụng phương thức Get và browser chỉ hỗ trợ phương thức Get
{% endhint %}

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/oQPsQsrDLK2titFuehsd/image.png" alt=""><figcaption><p>Kết quả</p></figcaption></figure>

Dùng Postman thực hiện phương thức Get

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/ZSwWI8UPLmwZrJfKXf6V/image.png" alt=""><figcaption><p>Demo</p></figcaption></figure>

Giải thích một số công cụ cơ bản trên giao diện này

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/BeXdVRBAyLwaeGLbjRj5/image.png" alt=""><figcaption><p>Chú thích</p></figcaption></figure>

Nếu trường hợp, ta gửi một phương thức khác Get thì vấn đề gì sẽ xảy ra?

Đó chính là chương trình vẫn trả ra được kết quả, do đoạn code phía trên, chúng ta chưa hề kiểm tra phương thức gửi lên để xử lý và trả ra kết quả.

Điều này có ý nghĩa rất lớn với phương thức vì chúng sẽ có ý nghĩa khác nhau, nên ta bắt buộc phải kiểm tra phương thức gửi lên là gì và có hàm xử lý riêng biệt cho phương thức tương ứng.

Để kiểm tra phương thức từ request, ta sẽ có cú pháp: request.method

{% hint style="info" %}
Các giá trị của request.method mặc định sẽ viết hoa tất cả các ký tự
{% endhint %}

Theo dõi đoạn code phía dưới:

```javascript
import http from 'http';
const listStudent = [
    {
        id: 1,
        fullName: "Jackie",
        age: 5,
        class: "5A"
    },
    {
        id: 2,
        fullName: "Juli MTP",
        age: 5,
        class: "5A"
    },
    {
        id: 3,
        fullName: "Denis",
        age: 5,
        class: "5B"
    },
]
const app = http.createServer((request, response) => {
    const endpoint = request.url;
    // lấy phương thức được gửi lên từ request
    const method = request.method;

    switch (endpoint) {
        case '/':
            response.end(`Hello MindX`);
            break;
        case '/students':
            // kiểm tra request và xử lý logic tương ứng
            if (method === "GET") {
                // code...
                response.end(JSON.stringify(listStudent));
            }
            break;
        default:
            response.end(`404 Notfound`);
            break;
    }
});

app.listen(8080, () => {
    console.log('Server is running!');
});
```

Với đoạn code phía trên, trường hợp ta sử dụng phương thức khác GET, request sẽ ở trạng thái pending khi không nhận được kết quả trả về từ server.

Ví dụ:

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/QwM3doeGydnW1ShMXleU/image.png" alt=""><figcaption><p>Ví dụ pending</p></figcaption></figure>

Vậy qua nội dung trên, ta sẽ có một số bài thực hành ví dụ đơn giản phía dưới:

Tạo một file `data.js` có một mảng users rỗng, với mỗi user có các trường **bắt buộc** sau

```json
{
    "id":,
    "userName":,
    "email":,
    "address":,
    "age":,
}
```

**TẤT CẢ ĐỀU DÙNG PHƯƠNG THỨC GET.**

1. Viết API endpoint **/users** để lấy danh sách users.
2. Viết API endpoint **/users/old** để lấy danh sách user mà có tuổi >= 50.
3. Viết API endpoint **/users/add-random** để thêm một user mới với các thông tin ngẫu nhiên.
4. Viết API endpoint **/users/add/userName={giá trị}\&email={giá trị}\&address={giá trị}\&age={giá trị}** để thêm thông tin user được điền trên API (id vẫn lấy ngẫu nhiên).

   Ví dụ:&#x20;

   **/users/add/userName="MindX School"\&email="<mindx@edu.vn>"\&address="Hà Nội"\&age=8**
5. Viết API endpoint **/users/update/{user id}/tên trường = giá trị cần update**. Server sẽ tìm kiếm user có id bằng với id được truyền trên API và cập nhật thông tin

   Ví dụ:

   1. Cập nhật 1 trường thông tin **/users/update/1/userName="Doraemon"**
   2. Cập nhật nhiều trường thông tin **/users/update/1/userName="Doraemon"\&age="5"**

{% hint style="info" %}
Bài tập trên **chỉ** nằm trong phạm vi tập luyện và rèn logic, hãy cố gắng suy nghĩ, xử lý được nhiều trường hợp xảy ra nhất có thể.
{% endhint %}

## Kết

Trên đây là nội dung của buổi học giúp chúng ta hiểu về các nội dung, cũng như có thể tạo được server với NodeJs sử dụng module http. Tuy nhiên, ta có thể thấy sẽ phức tạp nếu như xây dựng một hệ thống hoàn chỉnh, kèm đó là sự phức tạp khi xử lý API.

Trong bài học sau, ta sẽ được tìm hiểu về ExpressJs để khắc phục các vấn đề đã gặp trong nội dung này, cũng như tiếp tục tìm hiểu các kiến thức liên quan.
