# Lesson 2 -  ExpressJs

## Lý do lựa chọn ExpressJs

Trong nội dung trước, ta đã được tìm hiểu cách sử dụng http module, một module được tích hợp trong NodeJs, dùng để khởi tạo một server với giao thức http.

Sẽ rất phức tạp nếu ta dùng thuần http module, nên ta có một Framework là ExpressJs, sẽ giúp chúng ta cài đặt, thiết lập server với giao thức http một cách dễ dàng và hiệu quả hơn, tối giản các logic không cần thiết.

Ưu điểm nổi trội của ExpressJs:

* Đơn giản và dễ sử dụng: ExpressJS có cú pháp đơn giản và dễ hiểu, giúp lập trình viên dễ dàng nắm bắt và triển khai các tính năng.
* Linh hoạt: ExpressJS không áp đặt một cấu trúc cụ thể, cho phép lập trình viên tự do tùy chỉnh và xây dựng ứng dụng theo ý muốn.
* Hỗ trợ middleware: ExpressJS cung cấp hệ thống middleware mạnh mẽ, cho phép thực hiện các chức năng như xác thực, ghi log, nén dữ liệu và xử lý lỗi một cách linh hoạt và dễ dàng.
* Hiệu suất cao: ExpressJS được xây dựng trên Node.js, nền tảng có hiệu suất cao, cho phép xử lý nhanh chóng các yêu cầu web đồng thời và có khả năng mở rộng tốt.

## Cài đặt ExpressJs

Để cài đặt ExpressJs, trước tiên ta vẫn cần tạo một dự án mới.

Tạo folder tên server và bật terminal lên

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/TqyX6dKugvN5SIETXhkj/image.png" alt=""><figcaption><p>Hình ảnh</p></figcaption></figure>

Sử dụng câu lệnh "npm init" và lựa chọn các thiết lập để tạo file package.json cho dự án (Bấm enter để lựa chọn mặc định cho đến hết)

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/2SLvR92KLLrdSS0ukU3V/image.png" alt=""><figcaption><p>Tạo file package.json</p></figcaption></figure>

Cài dặt Expressjs với câu lệnh: npm i express

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/kbbV5r2v6qY4d1r46x7G/image.png" alt=""><figcaption><p>Sau khi chạy lệnh</p></figcaption></figure>

Ta có thể thấy file package.json có thêm một key là dependencies, với thông tin của express và phiên bản đã cài đặt.

## Khởi tạo server với ExpressJs

Tạo file `index.js` và thiết lập theo đoạn code phía dưới

```javascript
import express from 'express';
const app = express();

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

{% hint style="info" %}
Để dùng được cú pháp ES6 module, cần phải config type trong file package.json như tài liệu buổi 1.
{% endhint %}

Chạy thử server với lệnh node index.js và xem kết quả

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

Như vậy ta đã có thể khởi tạo server với express nhanh chóng và dễ dàng.

## GET Request base endpoint với ExpressJs

Như đã được tìm hiểu phần học trước, ta muốn tương tác với server với giao thức http, ta cần phải làm việc với các phương thức và được thực hành với phương thức căn bản nhất là phương thức GET.

Khởi tạo phương thức get với base API Endpoint:

```javascript
import express from 'express';
const app = express();

// phương thức get với base API
app.get('', (req, res) => {
    res.end("Hello MindX!");
});
app.listen(8080, () => {
    console.log('Server is running!');
});
```

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

{% hint style="info" %}
Phương thức phía trên (kể cả các phương thức khác), nhận đầu vào 2 tham số theo thứ tự:

1. route (đường dẫn).
2. callback function handler.

   Hàm này nhận đầu vào 2 tham số lần lượt chính là request và response, tuy nhiên sẽ có sự khác biệt với **requestListener** khi dùng http module, nhưng bản chất là giống nhau.
   {% endhint %}

Khi sử dụng res.end, có thể nó sẽ không được linh hoạt, trong lúc ta muốn gửi các dạng dữ liệu xuống cho client thì phải parse dữ liệu qua dạng string, đôi khi cũng sẽ làm cho client trong việc đọc dữ liệu khó khăn.

Vậy ta sẽ có một hàm là `res.send` giúp cho việc trả vể dữ liệu dễ dàng và linh động hơn, không cần parse qua định dạng string nữa.

```javascript
app.get('', (req, res) => {
    const data = { school: 'MindX technology school' };
    response.send(data);
});
```

## CRUD với ExpressJs

CRUD viết của Create, Read, Update, Delete. Trong RESTful API, chuẩn này cung cấp luật lệ làm việc với các phương thức của API.

**Read**

Buổi trước, ta đã được tìm hiểu về GET Method và với phương thức này, sẽ quy định chúng ta khi muốn lấy dữ liệu, phải dùng phương thức GET. Ví dụ:

```javascript
app.get('', (req, res) => {
    const data = { school: 'MindX technology school' };
    response.send(data);
});
```

Trường hợp, ta muốn có các điều kiện truy vấn thông tin, giống như ý số 2 ở bài tập demo buổi 1

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/7UjlVMrjgAOFbZzGJCN9/image.png" alt=""><figcaption><p>Bài tập 2</p></figcaption></figure>

Cách này là không sai, nhưng nó sẽ khó linh động trong việc truy vấn điều kiện, trường hợp ta muốn lấy người > 60 tuổi trên API đó, thì ta sẽ làm cách nào? Vì bài phía trên đã cố định điều kiện dữ liệu. Giải quyết vấn đề này, ta sẽ có khái niệm gọi là **`query params`**

Query params là cách chúng ta sẽ truyền truy vấn thông tin lên trên API, ý nghĩa của việc này là gì sẽ do nghiệp vụ quyết định. Ví dụ:

Khi truyền thông tin old và giá trị là 50, ta sẽ lấy dữ liệu với điều kiện tuổi cần >= 50 và tương tụ các trường hợp khác.

Lúc này query params là một lựa chọn phù hợp và nằm trong chuẩn RESTful API

Dạng của query params:&#x20;

`https://translate.google.com`<mark style="color:red;">`?sl=en&tl=vi&text=hello&op=translate`</mark>

Trên đường dẫn trên, đoạn được bôi đỏ chính là query params, với cú pháp:

?key=value, mỗi một cặp key=value là một truy vấn, nhiều truy vấn sẽ được ngăn cách với nhau với dấu `&` luôn được ngăn cách với API endpoint bằng dấu '?'. Hãy thử xác định key value trên URL trên!

Cú pháp để lấy giá trị của query params:

```javascript
app.get('', (req, res) => {
    const queryParams = req.query;
    response.send(queryParams);
});
```

{% hint style="info" %}
req.query sẽ trả về kết quả là một object, nên hoàn toàn có thể dùng cú pháp object destructuring. (Các giá trị sẽ trả về là undefined nếu không được truyền)

Ví dụ:

<pre class="language-javascript"><code class="lang-javascript"><strong>const {userName, address} = req.query;
</strong><strong>response.send(queryParams);
</strong></code></pre>

{% endhint %}

Hãy thử dùng query params để giải quyết ý số 2 trong nội dung bài 1.

Đôi khi, ta sẽ không cần phải truyền các truy vấn thông tin một cách chi tiết như thế, ta hoàn toàn có thể tạo ra 1 API mà chỉ cần truyền các giá trị theo đúng thứ tự đã được định nghĩa để rút gọn lại "hình thức API". Sử dụng kỹ thuật truyền params trên API

API params mường tượng cũng giống như hàm, định nghĩa tham số hoặc nhiều tham số và ta chỉ cần truyền các giá trị tương ứng, đúng thứ tự. Ví dụ API dùng params để lấy thông tin user qua Id

URL: `https://domain-host/users/12345`

Câu hỏi được đặt ra ở đây, gần như ta chưa thấy sự khác biệt gì khi nhìn vào API này?

Sự khác biệt nằm ở endpoint 12345, đây không phải là endpoint 12345 mà nó là 1 API dạng như sau: `https://domain-host/users/:id`

Có thể nghĩ :id chính là một biến, giúp nhận giá trị với tên biến là id. Cú pháp để lấy giá trị từ params: `req.params`

Ví dụ sử dụng params:

```javascript
app.get('/users/:id', (req, res) => {
    const { id } = req.params;
    const user = users.find(item => item.id === id);
    res.send(user);
});
```

Có thể truyền nhiều params lên trên 1 API. Ví dụ:

```javascript
app.get('/users/:id/:postid/', (req, res) => {
    const { id, postId } = req.params;
    const user = users.find(item => item.id === id && item.postId === postId);
    res.send(user);
});
```

{% hint style="info" %}

* Không nên lạm dụng params như trên, vì sẽ khó nhận biết thứ tự cần truyền là gì nếu phía client không hiểu nghiệp vụ.
* Chỉ nên dùng 1 params là id của resource.
* Nên kết hợp nhiều params trong trường hợp truy vấn lồng và phải đặt tên params khác nhau để phân biệt.

Ví dụ:&#x20;

```javascript
app.get('/users/:id/posts/:postId', (req, res) => {
    const { id, postId } = req.params;
    const data = users.find(item => item.id === id && item.postId === postId);
    res.send(data);
});

URL: http://localhost:8080/users/12345/posts/123
```

{% endhint %}

**Create**

Để tạo một dữ liệu, với RESTful API, ta sẽ sử dụng phương thức POST.

Post có ý nghĩa là gửi đi một thông tin, dữ liệu nào đó trên một API. Trường hợp này gIống như một ví dụ của bài số 1:

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/4pa5Lwwl09tHSXlWnKt0/image.png" alt=""><figcaption><p>Bài 4 buổi 1</p></figcaption></figure>

Yêu cầu của bài này, là truyền các dữ liệu lên trên API và thêm dữ liệu đó vào danh sách dữ liệu đã có.

Trong yêu cầu trên, ta sẽ cần phải truyền dữ liệu lên API một cách "lộ liễu", nếu như trường hợp ta cần tạo một dữ liệu gì đó, giống như một tài khoản, vậy thì mọi thông tin sẽ đều có trên API, điều này sẽ không giúp được gì về tình trạng bảo mật mà logic xử lý phía server còn phức tạp.

Thay vào đó, ta sẽ dùng kỹ thuật truyền "dữ liệu ngầm" phía dưới, giúp cho việc viết API gọn gàng hơn mà các thông tin cũng sẽ không bị "lộ liễu", đó là request body.(Cấu trúc của một request tham khảo thêm tại: [Link](https://bkhost.vn/blog/http-request/)).

Ví dụ cú pháp cài đặt phương thức post và body từ request:

<pre class="language-javascript"><code class="lang-javascript"><strong>
</strong>app.use(express.json()); // đây là một cách xử lý, giúp cho server nhận dạng dữ liệu gửi lên là một json
                         // là một hàm xử lý trung gian, tất cả các request sẽ đều đi qua. (sau này gọi là middleware)
app.post('/users', (req, res) => {
    const body = req.body;
    users.push(body);
    res.send(users);
});
</code></pre>

{% hint style="info" %}
req.body gửi lên sẽ là một object, nên hoàn toàn có thể dùng cú pháp Object destructuring.
{% endhint %}

Cách gửi body từ Postman theo dõi các cấu hình phía dưới:

<figure><img src="https://content.gitbook.com/content/bApz6rKK01BWUpp5sM0n/blobs/x68gY9bPTfQKeFEsyMLy/image.png" alt=""><figcaption><p>Cấu hình gửi body từ Postman</p></figcaption></figure>

**Update**

Trong các phương thức đã được giới thiệu, chuẩn RESTful API sẽ quy định sử dụng phương thức PUT để thực hiện cập nhật một dữ liệu nào đó với:

1. Id của dữ liệu được truyền trên params
2. Thông tin cần cập nhật được gửi trên request body

Ví dụ:

```javascript
app.put('/users/:id', (req, res) => {
    const { id } = req.params;
    const fieldsUpdate = req.body;
    const currentUser = users.find(item => item.id === id);
    for (const key in fieldsUpdate) {
        currentUser[key] === fieldsUpdate[key];
    }
    res.send(users);
});
```

**Delete**

Để xoá một dữ liệu nào đó, với RESTful API ta sẽ dùng phương thức DELETE với id của dữ liệu cần xoá được truyền trên params.

Ví dụ:

```javascript
app.delete('/users/:id', (req, res) => {
    const { id } = req.params;
    const currentIndxUser = users.findIndex(item => item.id === id);
    users.splice(currentIndxUser, 1);
    res.send(users);
});
```

{% hint style="info" %}
Trong thực tế, khi đã triển khai trên môi trường production, ta sẽ không xoá hẳn một data ra khỏi resource, mà sẽ chỉ thêm một trường dạng như isDelete: true để thể hiện data này đã bị xoá và sẽ không trả về cho client dữ liệu này khi lấy thông tin
{% endhint %}

Vậy, tổng quan phía trên, ta đã được tìm hiểu qua về CRUD với RESTful API trong ExpressJs.

Có thêm một vấn đề, như các đoạn code phía trên, nó hoàn toàn được thử nghiệm trong trường hợp chắc chắn thành công, vậy nếu không thành công, ta sẽ cần có những cách thức, báo cho phía client biết hiện lỗi hiện tại là gì, để client có thể nắm thông tin.

Ta sẽ có cách như: khi response trả về thông tin, sẽ trả thêm một số thông tin như lời nhắn, trạng thái xử lý giống như đoạn code sau:

```javascript
app.get('/users/:id', (req, res) => {
    const { id } = req.params;
    const user = users.find(item => item.id === id);
    // kiểm tra tồn tại user hay không
    if(!user) {
        res.send({
            message:'Không tìm thấy user',
            success: false,
            data: null
        });
    } else{
        res.send({
            message:'Tìm thấy user',
            success: true,
            data: user
        });
    }
});
```

Đây sẽ là một cách khá hữu dụng trong một số trường hợp cần chi tiết hoá thông tin, nhưng để định nghĩa được đây là xuất phát lỗi từ client hay server thì lại khó xác định. Tất nhiên ta hoàn toàn có thể nói chi tiết hơn nhưng ta sẽ có cách hay hơn khi quy định lỗi trả về với HTTP Status (Tham khảo chi tiết thêm tại: [Link](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)).

1. [Informational responses](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#information_responses) (`100` – `199`)
2. [Successful responses](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses) (`200` – `299`)
3. [Redirection messages](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages) (`300` – `399`)
4. [Client error responses](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) (`400` – `499`)
5. [Server error responses](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses) (`500` – `599`)

Một số mã hay dùng và ý nghĩa:

1. 200 - OK: dùng khi trạng thái xử lý thành công.
2. 201 - Created: dùng khi thêm hoặc cập nhật thành công.
3. 401 - Unauthorized: dùng khi server không xác thực được thông tin xác thực của client gửi lên.
4. 403 - Forbidden: dùng khi request nào đó không được phép sử dụng API, khác với 401, 403 đã xác thực được client nhưng request này bị cấm.
5. 404 - Not found: dùng khi server không thể tìm thấy thông tin nguồn tài nguyên mà client yêu cầu.
6. 500 - Internal Server error: lỗi này thuộc về phía server khi không thể xử lý được thông tin và không biết xử lý như thế nào

Để trả về status code (mã trạng thái) của server ta sử dụng cú pháp:

```javascript
req.status(mã cần trả về).send();
```

Ví dụ:

```javascript
app.get('/users/:id', (req, res) => {
    const { id } = req.params;
    const user = users.find(item => item.id === id);
    // kiểm tra tồn tại user hay không
    if (!user) {
        res.status(500).send({
            message: 'Không tìm thấy user',
            success: false,
            data: null
        });
    } else {
        res.status(200).send({
            data: user,
            message: 'Tìm user thành công',
            success: true
        });
    }
});
```

Trên đây là tổng quan về ExpressJs, cách sử dụng các phương thức cho CRUD kết hợp RESTful API. Ta có thể ứng dụng và giải quyết bài tập ở buổi số 1 và tập luyện với bài tập sau:

## Ví dụ

Tạo file data.js với các dữ liệu ví dụ sau:

<details>

<summary>data.js</summary>

<pre class="language-javascript"><code class="lang-javascript"><strong>const users = [
</strong>    {
        id: "9fceb585-042f-4f10-9cb5-37c529d93166",
        userName: "Nobita",
        email: "nobita@japanese.com",
        age: 5,
        avatar: "https://i.kym-cdn.com/photos/images/original/000/985/256/d51.png"
    },
    {
        id: "6257644e-94f2-45fc-9803-fc862df55eaa",
        userName: "Doraemon",
        email: "doraemon@nobita.com",
        avatar: "https://i.pinimg.com/736x/11/e4/4d/11e44d85743b28fa62121b5ae71a914b.jpg"
    },
    {
        id: "e7a88219-c265-44b4-ba02-1d2571ee4173",
        userName: "Suneo",
        email: "suneo@jaien.com",
        avatar: "https://ecdn.game4v.com/g4v-content/uploads/2023/05/19100155/Suneo-2-game4v-1684465314-94.jpg"
    }
];
<strong>const posts = [
</strong>  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: 'd051b29e-d9c5-4cb1-89bf-38b31aef05f1',
    content: 'Chào mọi người!',
    createdAt: '2023-09-22T12:30:00.000Z',
    isPublic: true
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: 'cfcc73cd-5297-48a4-8d3a-2282a30a8c7a',
    content: 'Tôi đã tìm thấy một quyển sách tuyệt vời để đọc.',
    createdAt: '2023-09-22T12:31:00.000Z',
    isPublic: false
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: '86c961d8-0edc-4c59-a048-3f192a0e7ea3',
    content: 'Hôm nay thời tiết tuyệt vời!',
    createdAt: '2023-09-22T12:32:00.000Z',
    isPublic: true
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: 'e12a04e0-6b3b-4d6a-9f2d-60ebd21dbf3d',
    content: 'Cuối tuần tới, tôi sẽ tham gia một sự kiện thú vị.',
    createdAt: '2023-09-22T12:33:00.000Z',
    isPublic: false
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: '40b8d24e-70a5-4f75-8f71-0905b8e197cf',
    content: 'Yêu mọi người!',
    createdAt: '2023-09-22T12:34:00.000Z',
    isPublic: true
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: '3b8d6e1a-7601-43c3-9264-1f3653a1e5c9',
    content: 'Chúc mọi người cuối tuần vui vẻ!',
    createdAt: '2023-09-22T12:35:00.000Z',
    isPublic: true
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: '5f508d8e-407b-4b41-8ff2-e727590aaf5d',
    content: 'Làm điều tốt cho ngày hôm nay!',
    createdAt: '2023-09-22T12:36:00.000Z',
    isPublic: true
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: '1d8b6e16-c01a-4c80-8924-2bf9f5a548cc',
    content: 'Chia sẻ niềm vui!',
    createdAt: '2023-09-22T12:37:00.000Z',
    isPublic: true
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: '1b2b8c16-32ca-4e5a-9866-9df098c5e144',
    content: 'Hãy yêu đến mức bạn có thể!',
    createdAt: '2023-09-22T12:38:00.000Z',
    isPublic: true
  },
  {
    userId: '9fceb585-042f-4f10-9cb5-37c529d93166',
    postId: '4e5c8d1f-30a8-4d88-832e-79fb6d6a2cf1',
    content: 'Hãy sống với niềm đam mê!',
    createdAt: '2023-09-22T12:39:00.000Z',
    isPublic: true
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: 'a1d6d08c-356e-4f0e-8521-dc20ef12e882',
    content: 'Hôm nay là một ngày đáng nhớ!',
    createdAt: '2023-09-22T14:30:00.000Z',
    isPublic: true
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: '4b721d1f-99b9-4e4e-90d5-ef06dca0b99e',
    content: 'Chúc mọi người một ngày thật tươi đẹp!',
    createdAt: '2023-09-22T14:31:00.000Z',
    isPublic: false
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: 'd5e68c5a-50cd-4889-8a59-2b6be7d00aa3',
    content: 'Hãy luôn giữ nụ cười trên môi!',
    createdAt: '2023-09-22T14:32:00.000Z',
    isPublic: true
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: '32c8b9d3-5ecf-4a76-ba33-12f120ea2fb1',
    content: 'Tôi đang học một điều mới mẻ hôm nay.',
    createdAt: '2023-09-22T14:33:00.000Z',
    isPublic: false
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: 'e8c5d7b6-2b2a-4d68-a067-9cd0ec191f7a',
    content: 'Yêu cuộc sống!',
    createdAt: '2023-09-22T14:34:00.000Z',
    isPublic: true
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: 'f3e8d6a1-36b1-4e15-9a25-7d98b4a4fece',
    content: 'Nhớ người thân và bạn bè!',
    createdAt: '2023-09-22T14:35:00.000Z',
    isPublic: true
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: '17b2c3d4-97d0-43ef-9c5e-bc63dabf1a1f',
    content: 'Hãy làm điều tốt trong ngày hôm nay!',
    createdAt: '2023-09-22T14:36:00.000Z',
    isPublic: true
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: 'a9d8b2e1-2dcb-42a6-85c8-eb891d8b49f2',
    content: 'Chúc mọi người một cuối tuần vui vẻ!',
    createdAt: '2023-09-22T14:37:00.000Z',
    isPublic: true
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: 'c6e9a8f1-9013-4e8b-8f63-4f1a9a667c5f',
    content: 'Luôn học hỏi và phát triển bản thân!',
    createdAt: '2023-09-22T14:38:00.000Z',
    isPublic: true
  },
  {
    userId: '6257644e-94f2-45fc-9803-fc862df55eaa',
    postId: 'b1e3d9c8-6d97-4e86-94fc-7bcda8a1e0bd',
    content: 'Yêu mọi người từ trái tim!',
    createdAt: '2023-09-22T14:39:00.000Z',
    isPublic: true
  }
]
export {
<strong>  users, 
</strong>  posts
}
</code></pre>

</details>

Hãy sử dụng file data phía trên, chuẩn RESTful API để thực hiện các bài tập luyện tập sau:

1. Viết API lấy thông tin của user với id được truyền trên params.
2. Viết API tạo user với các thông tin như trên users, với id là random (uuid), email là duy nhất, phải kiểm tra được trùng email khi tạo user.
3. Viết API lấy ra các bài post của user được truyền userId trên params.
4. Viết API thực hiện tạo bài post với id của user được truyền trên params.
5. Viết API cập nhật thông tin bài post với postId được truyền trên params, chỉ có user tạo bài mới được phép.
6. Viết API xoá bài post với postId được truyền trên params, chỉ có user tạo bài mới được phép.
7. Viết API tìm kiếm các bài post với content tương ứng được gửi lên từ query params.
8. Viết API lấy tất cả các bài post với isPublic là true, false thì sẽ không trả về.

## Kết

Trên đây là nội dung kiến thức cơ bản về ExpressJs, kèm theo một số kiến thức về CRUD khi kết hợp chuẩn RESTful API và một số ví dụ với data đơn giản.

Bài kế tiếp, ta sẽ được học cách khởi tạo một resource để mô tả lại data, có thể lưu trữ, thay vì xử lý trên data được tạo trên JS.
