[Công nghệ Thông tin] -- [Web] -- [Công nghệ phần mềm] -- [PhoThong] -- [Đăng ký các khóa học] -- [Langbiang's Portfolio] -- [Học viên cũ] -- [10.000 giờ]
--------------- <> -----------------
---  KHOA HỌC - CÔNG NGHỆ - GIÁO DỤC - VIỆC LÀM --->>>  CÁC KHÓA HỌC...
---  Nhận làm website, web app, chạy quảng cáo, digital marketing --->>>  LIÊN HỆ...

Tìm kiếm trong Blog

Web back-end (15) - Event-driven, Route handler và Middleware trong Express

Bài trước: Web back-end (14) - Lập trình hướng sự kiện

-----
15. Event-driven, Route handler và Middleware trong Express

Sau bài học trước, chúng ta đã có ý niệm về lập trình hướng sự kiện (event-driven), đã thực hành viết một chương trình đơn giản về lập trình hướng sự kiện trong môi trường Nodejs.

Trong phần này, chúng ta sẽ tìm hiểu về lập trình hướng sự kiện, route handler và middleware trong môi trường Express.

15.1 Lập trình hướng sự kiện trong Express

Express là một framework, xây dựng trên nền tảng Nodejs. Express sử dụng mô hình lập trình hướng sự kiện để xử lý các HTTP request, đọc/ghi tập tin, làm việc với cơ sở dữ liệu, websocket, stream.

Chúng ta cùng tìm hiểu cách Express sử dụng mô hình lập trình hướng sự kiện để xử lý các HTTP request.

Trong mô hình này:

- Mỗi request từ client (như GET, POST, PUT, DELETE) được xem là một sự kiện (Event).

- Các module http, fs, stream là các Bộ quản lý sự kiện (Event Emitter) của Express.

- Express sử dụng Vòng lặp sự kiện (Event Loop) của Node.js để lắng nghe và xử lý các sự kiện theo kiểu bất đồng bộ (asynchronous), không chặn luồng (non-blocking).

- Các route handler và middleware đóng vai trò như các Hàm xử lý sự kiện (Event Handler), được gọi khi sự kiện tương ứng xảy ra.

Xem hình minh họa.

15.2 Thực hành với GET request

Để hiểu rõ hơn về lập trình hướng sự kiện trong Express, chúng ta cùng thực hành với GET request.

Tình huống cụ thể như sau:

- Client gửi GET request tới web server

- Web server phát hiện sự kiện GET request và chuyển nó đến Express.

- Express kiểm tra URL và method (GET) để tìm route handler phù hợp.

- Hàm callback (route handler) được gọi để xử lý sự kiện, trả về response cho client.

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

 

// Express lắng nghe sự kiện GET request, tại route /

// nếu có sự kiện, gọi hàm callback (route handler) tương ứng

app.get('/', (req, res) => {

    const name = req.query.name;

    res.send(`Web server chào bạn ${name}`);

});

 

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

Lưu lại mã nguồn tập tin index.js, khởi động lại web server.

Mở trình duyệt web, nhập đường dẫn sau:

http://localhost:9000/?name=Teo

Giao diện của trình duyệt web sẽ có dòng nội dung sau:

Web server chào bạn Teo

Sử dụng Middleware cho GET request 

Chúng ta sẽ sử dụng middleware với vai trò như là một Event Handler (Hàm xử lý sự kiện) cho GET request.

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

 

// Middleware: ghi log mỗi khi có GET request

app.use((req, res, next) => {

    console.log(`[${new Date().toISOString()}] nhận GET request tại ${req.url}`)

    // Chuyển tiếp sự kiện đến route handler

    next();

});

 

// Express lắng nghe sự kiện GET request, tại route /

// nếu có sự kiện, gọi hàm callback (route handler) tương ứng

app.get('/', (req, res) => {

    const name = req.query.name;

    res.send(`Web server chào bạn ${name}`);

});

 

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

Lưu lại mã nguồn tập tin index.js, khởi động lại web server.

Mở trình duyệt web, nhập đường dẫn sau:

http://localhost:9000/?name=Teo

Giao diện của trình duyệt web sẽ có dòng nội dung sau:

Web server chào bạn Teo

Và cửa sổ console của Web server sẽ có dòng thông báo như sau:

server dang chay tren cong 9000

[2025-03-31T11:54:20.737Z] nhận GET request tại /?name=Teo

15.3 Route handler và Middleware trong Express

Ở phần trước, bạn đã thực hành trải nghiệm với Route handler và Middleware.

Phần này, chúng ta sẽ tìm hiểu kĩ hơn về 2 khái niệm này.

Route handler

Route handler là các hàm xử lý được gắn với một luồng (route) cụ thể trong ứng dụng Express. Chúng được gọi khi một HTTP request (như GET, POST, PUT, DELETE) từ client khớp với route và method tương ứng. Route handler đóng vai trò như Event handler trong lập trình hướng sự kiện, xử lý logic chính cho request và trả về response.

Route handler nhận 3 tham số chính:

- req (request): đối tượng chứa thông tin về request từ client (URL, headers, body).

- res (response): đối tượng dùng để gửi response về client.

- next (optional): hàm gọi để chuyển tiếp request sang middleware hoặc handler tiếp theo (nếu có).

Cú pháp:

app.METHOD(path, callback);

- Trong đó METHOD là HTTP method (get, post, put, delete), path là luồng, và callback là Route handler.

// Express lắng nghe sự kiện GET request, tại route /

// nếu có sự kiện, gọi hàm callback (route handler) tương ứng

app.get('/', (req, res) => {

    const name = req.query.name;

    res.send(`Web server chào bạn ${name}`);

});

Đặc điểm của Route handler:

- Cụ thể cho route và method: mỗi Route handler chỉ được gọi khi request khớp (match) với route và HTTP method đã định nghĩa.

- Xử lý logic chính: thường chứa logic nghiệp vụ như truy vấn cơ sở dữ liệu, xử lý dữ liệu, hoặc trả về kết quả.

- Có thể nối tiếp: nhiều Route handler có thể được gắn vào cùng một route bằng cách truyền nhiều callback hoặc dùng next().

Ví dụ nối tiếp Route handler

[index.js]

 

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

  

// Nối tiếp Route handler

app.get('/profile', (req, res, next) =>

{

      console.log('Kiểm tra quyền truy cập...');

      req.user = { name: "Ti"}; // Giả lập thêm dữ liệu

      next(); // Chuyển tiếp

    },

    (req, res) => {

res.send(`Chào bạn: ${req.user.name}`);

    }

  );

 

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

Lưu lại mã nguồn tập tin index.js, khởi động lại web server.

Mở trình duyệt web, nhập đường dẫn sau:

http://localhost:9000/profile

Giao diện của trình duyệt web sẽ có dòng nội dung sau:

Chào bạn: Ti

Middleware

Middleware là các hàm được thực thi trong quá trình xử lý một HTTP request, trước hoặc sau Route handler. Chúng có thể:

- Xử lý request (như xác thực, ghi log).

- Sửa đổi đối tượng req hoặc res.

- Chuyển tiếp request bằng next() hoặc dừng luồng xử lý bằng cách gửi response.

Middleware hoạt động như một "lớp trung gian" trong pipeline (dây chuyền, đường ống) xử lý request, giúp tách biệt logic chung khỏi Route handler.

Cấu trúc cơ bản

- Middleware cũng nhận 3 tham số: req, res, và next.

- Được đăng ký bằng app.use() (áp dụng cho tất cả route) hoặc gắn vào route cụ thể.

Cú pháp:

app.use(middlewareFunction);

Ví dụ:

// Middleware: ghi log mỗi khi có GET request

app.use((req, res, next) => {

    console.log(`[${new Date().toISOString()}] nhận GET request tại ${req.url}`)

    // Chuyển tiếp sự kiện đến route handler

    next();

});

Xem hình minh họa.

Các loại Middleware

[1] Application-level middleware: áp dụng cho toàn bộ ứng dụng với app.use().

// middleware mức ứng dụng

app.use((req, res, next) => {

    req.timestamp = new Date();

    next();

});

app.get('/',(req, res) => {

    res.send(`Khach truy cap web ap luc ${req.timestamp.toISOString()}`);

});

[2] Router-level middleware: áp dụng cho một nhóm route cụ thể bằng express.Router()

[3] Error-handling middleware: xử lý lỗi, nhận thêm tham số err.

[4] Built-in middleware: các middleware do Express cung cấp sẵn như express.json(), express.static().

[5] Third-party middleware: middleware của các nhà cung cấp khác, ví dụ body-parser, cors, morgan.

15.4 Bài tập

Bài tập 15.1 Cài đặt các đoạn mã trong bài học.

Câu hỏi 15.2 Mô hình lập trình hướng sự kiện của Express. Phát biểu nào sau đây không đúng?

A. Mỗi request từ client (như GET, POST, PUT, DELETE) được xem là một sự kiện (Event).

B. Các module http, fs, stream là các Bộ quản lý sự kiện (Event Emitter) của Express.

C. Express sử dụng Vòng lặp sự kiện (Event Loop) của trình duyệt để lắng nghe và xử lý các sự kiện theo kiểu bất đồng bộ (asynchronous), không chặn luồng (non-blocking).

D. Các route handler và middleware đóng vai trò như các Hàm xử lý sự kiện (Event Handler), được gọi khi sự kiện tương ứng xảy ra.

Câu hỏi 15.3 Route handler trong Express là gì? Phát biểu nào sau đây không đúng?

A. Route handler chỉ được gọi khi request khớp với route và HTTP method đã định nghĩa.

B. Route handler thường chứa logic nghiệp vụ như truy vấn cơ sở dữ liệu hoặc xử lý dữ liệu.

C. Route handler có thể chuyển tiếp request sang middleware hoặc handler tiếp theo bằng hàm next().

D. Chỉ có duy nhất một Route handler được gắn vào một route.

15.4. Middleware trong Express là gì? Phát biểu nào sau đây không đúng?

A. Middleware là các hàm được thực thi trong quá trình xử lý một HTTP request, trước hoặc sau Route handler.

B. Xử lý request (như xác thực, ghi log).

C. Sửa đổi đối tượng req hoặc res.

D. Middleware nhận 2 tham số: req, res.

-----
Cập nhật: 2/4/2025
-----
Bài sau:

Web back-end (14) - Lập trình hướng sự kiện

Bài trước: Web back-end (13) - Lập trình client-server

-----
14. Lập trình hướng sự kiện

Như bạn đã trải nghiệm ở các bài học trước, quan sát mã nguồn của index.js, bạn sẽ thấy: hàm app.listen() luôn được viết ở cuối tập tin, và mặc dù viết ở cuối tập tin, nhưng dường như nó lại luôn luôn được chạy trước? Nó chạy trước thì mới lắng nghe được các request từ client, để gọi các hàm xử lý tương ứng? Các hàm xử lý request lại được viết ở phía trên hàm app.listen().

Bạn đã thấy: logic xử lý của chương trình không phải luôn luôn thực thi tuần tự từ trên xuống dưới?

Để giải đáp hiện tượng trên, chúng ta cùng tìm hiểu một số chủ đề liên quan.

14.1 Lập trình hướng sự kiện

Lập trình hướng sự kiện (event-driven) là một mô hình lập trình mà luồng thực thi của chương trình được quyết định bởi các sự kiện (events). Các sự kiện này có thể là:

- Hành động của người dùng (nhấp chuột, gõ phím).

- Các thông điệp từ các chương trình khác.

- Các sự kiện do hệ thống tạo ra (nhận được request, thao tác đọc/ghi tập tin).

Thay vì chạy theo thứ tự mã nguồn từ trên xuống dưới, chương trình sẽ chờ đợi các sự kiện xảy ra và thực thi các hàm xử lý sự kiện (event handler) tương ứng.

14.2 Lập trình hướng sự kiện trong Nodejs

Nodejs là một môi trường được xây dựng dựa trên mô hình lập trình hướng sự kiện. Đây là một trong những đặc điểm cốt lõi giúp Node.js hoạt động hiệu quả và có khả năng xử lý nhiều kết nối đồng thời, đặc biệt phù hợp với các ứng dụng thời gian thực, các ứng dụng chuyên về I/O như ứng dụng web, API, hoặc ứng dụng mạng.

Ứng dụng chuyên về I/O (I/O-intensive application) là các ứng dụng mà phần lớn thời gian xử lý hoặc tài nguyên được dành cho các hoạt động nhập/xuất (Input/Output), tức là các tác vụ liên quan đến việc đọc/ghi dữ liệu từ hoặc đến các nguồn bên ngoài như tập tin, cơ sở dữ liệu, mạng, hoặc thiết bị phần cứng, thay vì tập trung nhiều vào tính toán (CPU-intensive).

Các thành phần của Mô hình lập trình hướng sự kiện

Mô hình lập trình hướng sự kiện trong Nodejs gồm các thành phần:

- Event: sự kiện

- Event Emitter: bộ quản lý sự kiện

- Event loop: vòng lặp sự kiện

- Event handler: hàm xử lý sự kiện

Xem hình minh họa:


Mô tả cách hoạt động của mô hình:

[1] EventEmitter

Trong hệ thống sẽ có một thành phần điều khiển, nó quản lý việc phát ra sự kiện của các đối tượng và gửi sự kiện tới nơi cần nghe (các đối tượng đang lắng nghe sự kiện tương ứng). Thành phần này được gọi là EventEmitter - Bộ quản lý sự kiện). 

Các phương thức chính của EventEmitter:

- on(eventName, listener): khai báo một tên sự kiện (eventName) sẽ phát ra, và đăng ký một hàm lắng nghe và xử lý đi kèm.

- emit(eventName, [arguments...]): phát ra một sự kiện, có tên là eventName, và các tham số đi kèm (nếu có).

[2] Event

Event là một hành động hoặc sự thay đổi trạng thái xảy ra trong ứng dụng, gọi chung là sự kiện (Event). Ví dụ:

- Yêu cầu HTTP đến máy chủ (GET request, POST request).

- Hoàn thành việc đọc/ghi tập tin.

- Hết thời gian chờ (timeout).

- Sự kiện lỗi.

[3] Event Loop (Vòng lặp sự kiện)

- Event Loop là cơ chế cốt lõi của Nodejs, cho phép nó xử lý các sự kiện không đồng bộ một cách hiệu quả.

- Event Loop liên tục kiểm tra hàng đợi sự kiện (event queue) và thực thi các hàm callback khi có sự kiện xảy ra.

- Điều này cho phép Nodejs xử lý nhiều yêu cầu đồng thời mà không bị chặn (blocking).

[4] Event Handler (Hàm xử lý sự kiện)

- Event handler là một hàm được gọi khi một sự kiện xảy ra. 

- Event handler thường được đăng ký với một EventEmitter bằng phương thức on().

14.3 Thực hành lập trình hướng sự kiện

Chúng ta cùng thực hành để làm quen với lập trình hướng sự kiện.

Chúng ta sẽ viết một chương trình đơn giản như sau:

- Sử dụng module events của Nodejs để lập trình hướng sự kiện

- Tạo một bộ quản lý sự kiện (EventEmitter)

- Sử dụng EventEmitter để khai báo một sự kiện, và đăng ký hàm xử lý đi kèm

- Phát sinh sự kiện (đã khai báo), để kiểm tra hoạt động của các thành phần

Để cho dễ hiểu, chúng ta sẽ viết chương trình theo 2 cách: [1] viết theo kiểu hàm thông thường (cách này viết để hiểu cơ chế làm việc) và [2] viết theo kiểu hàm mũi tên (arrow function) (cách này viết theo kiểu lập trình trong ứng dụng thực tế).

[1] Viết theo kiểu hàm thông thường

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

 

// gọi module events

const events = require('events');

// tạo ra một EventEmitter

const eventEmitter = new events.EventEmitter();

// đăng ký tên sự kiện, gắn với hàm lắng nghe và

// xử lý sự kiện tương ứng - xuLythongBao là event handler

eventEmitter.on('hetGio', xuLyThongBao);

// định nghĩa hàm xuLyThongBao

function xuLyThongBao(tb) {

    console.log(tb);

}

// phát ra sự kiện, kèm theo thông điệp

setTimeout(()=> {

    eventEmitter.emit('hetGio','Hết giờ học rồi, về thôi!!!!!!!')

}, 2000);

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

[2] Viết theo kiểu hàm mũi tên

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

 

// gọi module events

const events = require('events');

// tạo ra một EventEmitter

const eventEmitter = new events.EventEmitter();

// đăng ký tên sự kiện, gắn với hàm lắng nghe và

// xử lý sự kiện tương ứng

eventEmitter.on('hetGio', (thongBao) => {

    console.log(thongBao);

});

// phát ra sự kiện, kèm theo thông điệp

setTimeout(()=> {

    eventEmitter.emit('hetGio','Hết giờ học rồi, về thôi!!!!!!!')

}, 2000);

 

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

Kết quả: khi chạy, sau 2 giây, cửa sổ console trên web server sẽ có dòng thông báo sau

server dang chay tren cong 9000

Hết giờ học rồi, về thôi!!!!!!!

14.4 Bài tập

Bài tập 14.1 Viết lại các đoạn mã trong bài học.

Bài tập 14.2 Sử dụng module events của Nodejs để lập trình hướng sự kiện. Viết một chương trình đơn giản như sau:

- Khai báo sự kiện vaoLop (vào lớp), với hàm xử lý đi kèm là xuLyVaoLop

- Sử dụng hàm setTimeOut() để hẹn giờ vào lớp là 5 giây

- Hết 5 giây, web server sẽ thông báo “Đã đến giờ học” tới cửa sổ console của web server

- Viết bằng 2 cách: hàm thông thường và hàm mũi tên.

Câu hỏi 14.3 Mô hình lập trình hướng sự kiện trong Node.js là gì? Phát biểu nào sau đây không đúng?

A. Event Emitter liên tục kiểm tra hàng đợi sự kiện và thực thi các hàm callback khi có sự kiện xảy ra.

B. Event là các hành động hoặc sự thay đổi trạng thái xảy ra trong ứng dụng.

C. Event Loop liên tục kiểm tra hàng đợi sự kiện và thực thi các hàm callback khi có sự kiện xảy ra.

D. Event Handler là các hàm được gọi khi một sự kiện xảy ra.

-----
Cập nhật: 31/3/2025
-----

Web back-end (13) - Lập trình client-server

Bài trước: Web back-end (12) - Ứng dụng client-server

-----
13. Lập trình client-server
13.1 Gửi request tới web server

Ở các phần trước, chúng ta đã có trải nghiệm với lập trình client-server. Tuy nhiên, chúng ta mới chỉ dừng lại mức độ làm theo hướng dẫn, mà chưa hiểu được cơ chế giao tiếp, cách thức xử lý giữa client và server. 

Phần này, chúng ta sẽ tìm hiểu chi tiết hơn về lập trình giao tiếp giữa client và server.

Như đã đề cập, các bước xử lý ở web server gồm 7 bước, như hình sau:

Cụ thể, 7 bước xử lý gồm:

[1] nhận request

[2] phân tích request, gửi tới ứng dụng web để xử lý

[3] đọc dữ liệu từ cơ sở dữ liệu

[4] đổ dữ liệu vào trang HTML (các template HTML)

[5] gửi trang HTML (đã bao gồm dữ liệu) (response) về trình duyệt người dùng

[6] trình duyệt người dùng hiển thị nội dung response

[7] trình duyệt gửi riêng một request khác để lấy các nội dung tĩnh của ứng dụng web (HTML, CSS, JavaScript, hình ảnh, và các tài nguyên khác)

Để đơn giản, chúng ta sẽ lập trình theo tình huống sau:

- Bước 1: web server luôn ở trạng thái đang hoạt động, sẵn sàng chờ client gửi yêu cầu (request) tới.

- Bước 2: một người dùng bất kỳ, sử dụng trình duyệt web, gửi request tới web server.

- Bước 3: web server nhận request

- Bước 4: web server phân tích, xử lý request

- Bước 5: web server gửi response về client

- Bước 6: client (trình duyệt) nhận response, hiển thị thông tin lên trình duyệt.

Chúng ta cùng lập trình từng bước.

Bước 1: web server luôn ở trạng thái đang hoạt động, sẵn sàng chờ client gửi yêu cầu (request) tới

Mở tập tin index.js nhập đoạn mã sau:

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

 

 

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

Dòng mã app.listen() luôn được đặt ở cuối tập tin index.js. Dòng mã này sẽ khởi chạy web server, mở cổng có số hiệu là port (ví dụ 9000) để chờ đón các request từ client; đồng thời xuất một dòng thông báo server dang chay tren cong ${port}.  Hiểu nôm na, hàm app.listen() giống như hành động mở cửa của tiệm bán quần áo, mời bà con vào mua. Tiệm quần áo là một kiot trong chợ, có số hiệu là 9000. Trong chợ có rất nhiều kiot bán quần áo, với các số hiệu khác nhau.

Mở cửa sổ dòng lệnh, chạy lệnh node index.js hoặc nodemon để thực thi mã nguồn index.js.

Lưu ý dòng thông báo server dang chay tren cong ${port} sẽ xuất ở cửa sổ console tại máy web server, chứ không phải cửa sổ console của máy client. Bạn không tắt cửa sổ console này, vì tắt nó là web server sẽ ngừng hoạt động.

Bước 2: một người dùng bất kỳ, sử dụng trình duyệt web, gửi request tới web server

Khi web server đang chạy, và sẵn sàng nhận request. Chúng ta sẽ sử dụng trình duyệt để gửi các request về web server.

Để gửi request về web server, bạn có thể sử dụng thanh địa chỉ của trình duyệt, web form, hoặc dùng hàm JavaScript (AJAX, fetch). Để đơn giản, chúng ta sẽ sử dụng thanh địa chỉ của trình duyệt.

Mở trình duyệt web (tuy nhiên, bạn phải hiểu là mở trình duyệt trên máy tính của người dùng, vì đang trong giai đoạn phát triển phần mềm, nên máy web server và máy người dùng sẽ chạy chung trên một máy), gõ vào thanh địa chỉ URL sau:

http://localhost:9000/?name=shoes&size=40

Bấm Enter, bạn sẽ nhận được thông báo trên trình duyệt là:

Cannot GET /

Lý do có thông báo trên: client gửi request về web server, tuy nhiên, server mới chỉ mở cổng (9000) để lắng nghe request, nhận request, nhưng chưa có xử lý request và gửi trả lời (response) cho client. Nó giống như kiot đã mở bán, nhưng bên trong chưa có sản phẩm, chưa có người bán (kiot trống).

URL (Uniform Resource Locator) là địa chỉ duy nhất, dùng để định vị tài nguyên trên web, như trang HTML, API, hoặc tập tin tài nguyên tĩnh (ví dụ hình ảnh, âm thanh). Bạn có thể xem URL giống như địa chỉ của kiot.

Ví dụ một số URL:

- Định vị một trang web: https://www.example.com/index.html

- Gọi một API: https://api.example.com/v1/users/123

- Trỏ tới một hình ảnh: https://www.example.com/images/logo.png

- Định vị một ứng dụng web (trên máy cục bộ): http://localhost:9000/

Cú pháp của một URL:

protocol://domain:port/path?query#fragment

Giải thích các thành phần của một URL:

- protocol (giao thức): xác định phương thức giao tiếp mà trình duyệt sử dụng để giao tiếp với server. Các giao thức phổ biến bao gồm http (Hypertext Transfer Protocol) và https (Hypertext Transfer Protocol Secure).

- domain (tên miền): tên của máy server. Ví dụ: google.com, wikipedia.org, localhost.

- port (cổng) (tùy chọn): số cổng mà server sử dụng để lắng nghe yêu cầu (request). Cổng mặc định cho http là 80 và cho https là 443.

- path (đường dẫn): đường dẫn đến một vị trí (thư mục, tập tin, API) trên server. Ví dụ: /images/logo.png, /articles/how-to-use-url, /users.

- query (truy vấn) (tùy chọn): chuỗi các tham số được sử dụng để truyền dữ liệu đến server. Ví dụ: ?name=shoes&size=40.

- fragment (phân mảnh) (tùy chọn): một phần cụ thể của tài nguyên, thường là một phần của trang HTML. Ví dụ: #section-2.

Như vậy, URL http://localhost:9000/?name=shoes&size=40

Có nghĩa là:

- Client sử dụng giao thức http để gửi request tới web server

- Web server có địa chỉ là localhost

- Gửi request vào cổng 9000 của web server

- Gửi request, có kèm theo 2 tham số là name=shoes và size=40

Ngoài việc dùng thanh địa chỉ của trình duyệt để gửi request, chúng ta còn có 2 cách khác để gửi request là web form và hàm JavaScript (AJAX, fetch). Chúng ta sẽ tìm hiểu về web form, AJAX, fetch ở các phần sau.

13.2 Gửi response về client

Bước 3: web server nhận request, Bước [4] phân tích, xử lý request, Bước [5] gửi kết quả (response) về cho client

Tại web server, chúng ta sử dụng phương thức GET của Express để nhận và xử lý các HTTP request kiểu GET (request gửi bằng giao thức HTTP) do client gửi tới.

Cú pháp:

app.get(path, callback)

Trong đó:

- path: luồng dùng để xử lý các request kiểu GET (GET request). 

- callback: hàm sẽ được thực thi khi có GET request đến luồng tương ứng. Hàm này thường có dạng (req, res) => { ... }, trong đó: 

  + req (request): đối tượng chứa thông tin request từ client.

  + res (response): đối tượng dùng để gửi response về client.

Client có thể gửi nhiều loại request về web server, ví dụ: GET, POST, PUT, DELETE. Chúng ta dùng thanh địa chỉ của trình duyệt để gửi request, mặc định đó là request kiểu GET.

Dấu “/” trong http://localhost:9000/?name=shoes&size=40, có nghĩa là thư mục gốc.

Chúng ta sẽ viết đoạn mã xử lý như sau:

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

//xử lý khi người dùng gửi

//request kiểu GET tới thư mục gốc (/)

app.get("/", (req,res) => {

    //dùng phương thức query của req để lấy thông tin

    //của GET request

    const product = req.query.name;

    const size = req.query.size;

    //dùng hàm send() của đối tượng res

    //để gửi dữ liệu về client

    res.send(`Bạn muốn mua ${product} cỡ ${size}`);

});

//khoi dong web server

app.listen(port,() => {

    console.log(`server dang chay tren cong ${port}`);

});

Lưu lại mã nguồn, khởi động lại web server (nếu dùng Nodemon thì không cần).

Bước 6: client (trình duyệt) nhận response, hiển thị thông tin lên trình duyệt

Mở trình duyệt, nhập đường vào đường dẫn URL: http://localhost:9000/?name=shoes&size=40

Trên trình duyệt sẽ xuất hiện dòng chữ.

Bạn muốn mua shoes cỡ 40

Bạn có để ý là: đoạn mã app.listen() luôn được chạy trước, mặc dù nó nằm phía dưới đoạn mã app.get(). Về mặt xử lý: có thể hiểu nôm na app.listen() là động tác mở cửa kiot, chào đón khách tới mua hàng. Trong khi các đoạn mã phía trên là việc trưng bày hàng hóa, bán hàng, thanh toán. Như vậy, chúng ta sẽ trưng bày hàng hóa, sau đó, mở cửa hàng (app.listen()). Chờ có khách tới mua (request) thì sẽ thực hiện việc bán hàng, thanh toán.

Chúng ta sẽ tìm hiểu về kiến trúc của Nodejs, Express, lập trình hướng sự kiện ở các phần sau để hiểu rõ hơn về cách xử lý mã nguồn của ứng dụng web trên nền Express và Nodejs.

13.3 Bài tập

Bài tập 13.1 Viết đoạn mã thực hiện yêu cầu sau:

Từ trình duyệt, người dùng gửi GET request, có kèm theo MSSV, HoTen, DiemTrungBinh của một sinh viên. Ví dụ:

MSSV:11223344

HoTen:Nguyễn Văn Tèo

DiemTrungBinh:7.0 

Web server nhận request trên, lấy thông tin từ request và gửi về client dòng thông báo có nội dung và định dạng như sau:

Chào bạn Nguyễn Văn Teo

MSSV: 11223344

Điểm trung bình của bạn là: 70

Chúc bạn học chăm!

Câu hỏi 13.2 URL (Uniform Resource Locator) là gì? Phát biểu nào sau đây không đúng?

A. URL là một địa chỉ duy nhất xác định vị trí của một tài nguyên trên Internet.

B. URL bao gồm các thành phần như giao thức, tên miền, đường dẫn, truy vấn và phân mảnh.

C. Phần "truy vấn" (query) trong URL được sử dụng để truyền dữ liệu đến máy chủ thông qua các tham số.

D. Giao thức "FTP" là giao thức phổ biến nhất được sử dụng trong URL để truy cập các trang web.

-----

Cập nhật: 31/3/2025
-----
Bài sau: Web back-end (14) - Lập trình hướng sự kiện