035.2 Bài 1
Chứng chỉ: |
Web Development Essentials |
---|---|
Phiên bản: |
1.0 |
Chủ đề: |
035 Lập trình Máy chủ Node.js |
Mục tiêu: |
035.1 Khái niệm cơ bản về NodeJS Express |
Bài: |
1 trên 2 |
Giới thiệu
Express.js, hay đơn giản là Express, là một khung phổ biến chạy trên Node.js và được sử dụng để viết các máy chủ HTTP xử lý các yêu cầu từ các máy khách ứng dụng web. Express hỗ trợ nhiều cách để đọc các tham số được gửi qua HTTP.
Tệp lệnh Máy chủ Ban đầu
Để minh họa các tính năng cơ bản của Express trong việc nhận và xử lý các yêu cầu, hãy mô phỏng một ứng dụng yêu cầu một số thông tin từ máy chủ, cụ thể là máy chủ trong ví dụ:
-
Cung cấp chức năng
echo
để trả về tin nhắn do khách gửi. -
Cho khách biết địa chỉ IP của nó theo yêu cầu.
-
Sử dụng cookie để xác định các khách đã biết.
Bước đầu tiên sẽ là tạo tệp JavaScript hoạt động như máy chủ. Hãy sử dụng npm
và tạo một thư mục có tên myserver
với tệp JavaScript:
$ mkdir myserver $ cd myserver/ $ npm init
Đối với điểm nhập, chúng ta có thể sử dụng tên tệp bất kỳ, nhưng ở đây ta sẽ sử dụng tên tệp mặc định là index.js
. Danh sách sau đây cho thấy tệp index.js
cơ bản sẽ được sử dụng làm điểm nhập cho máy chủ:
const express = require('express')
const app = express()
const host = "myserver"
const port = 8080
app.get('/', (req, res) => {
res.send('Request received')
})
app.listen(port, host, () => {
console.log(`Server ready at http://${host}:${port}`)
})
Một số hằng số quan trọng cho cấu hình máy chủ được xác định trong các dòng đầu tiên của tệp lệnh. Hai hằng số đầu tiên là express
và app
sẽ tương ứng với mô-đun express
được bao gồm và một trường hợp của mô-đun này chạy ứng dụng của chúng ta. Chúng ta sẽ thêm các hành động được thực hiện bởi máy chủ vào đối tượng app
.
Hai hằng số khác là host
và port
sẽ xác định máy chủ và cổng giao tiếp được liên kết với máy chủ.
Nếu có một máy chủ có thể truy cập công khai, hãy sử dụng tên của nó thay vì myserver
làm giá trị của host
. Nếu bạn không cung cấp tên máy chủ, Express sẽ mặc định là localhost
, tức máy tính chạy ứng dụng. Trong trường hợp đó, sẽ không có khách bên ngoài nào có thể tiếp cận được chương trình. Việc này có thể sẽ không thành vấn đề trong trường hợp thử nghiệm nhưng sẽ mang lại rất ít giá trị trong quá trình sản xuất.
Cổng cần phải được cung cấp; nếu không, máy chủ sẽ không khởi động.
Tệp lệnh này chỉ đính kèm hai thủ tục vào đối tượng app
: hành động app.get()
trả lời các yêu cầu do khách thực hiện thông qua HTTP GET
và lệnh gọi app.listen()
để kích hoạt máy chủ và gán cho nó một máy chủ và một cổng.
Để khởi động máy chủ, ta chỉ cần chạy lệnh node
và cung cấp tên tệp lệnh làm đối số:
$ node index.js
Ngay khi thông báo Server ready at http://myserver:8080
xuất hiện, máy chủ đã sẵn sàng nhận yêu cầu từ máy khách HTTP. Yêu cầu có thể được thực hiện từ một trình duyệt trên cùng một máy tính nơi máy chủ đang chạy hoặc từ một máy khác có thể truy cập máy chủ.
Tất cả các chi tiết giao dịch chúng ta thấy ở đây sẽ được hiển thị trong trình duyệt nếu ta mở một cửa sổ cho bảng điều khiển của nhà phát triển. Ngoài ra, lệnh curl
có thể được sử dụng cho giao tiếp HTTP và cho phép ta kiểm tra chi tiết kết nối một cách dễ dàng hơn. Nếu không quen thuộc với dòng lệnh vỏ, bạn có thể tạo biểu mẫu HTML để gửi yêu cầu đến máy chủ.
Ví dụ sau đây sẽ cho thấy cách sử dụng lệnh curl
trên dòng lệnh để thực hiện yêu cầu HTTP tới máy chủ mới được triển khai:
$ curl http://myserver:8080 -v * Trying 192.168.1.225:8080... * TCP_NODELAY set * Connected to myserver (192.168.1.225) port 8080 (#0) > GET / HTTP/1.1 > Host: myserver:8080 > User-Agent: curl/7.68.0 >Accept: / > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < X-Powered-By: Express < Content-Type: text/html; charset=utf-8 < Content-Length: 16 < ETag: W/"10-1WVvDtVyAF0vX9evlsFlfiJTT5c" < Date: Fri, 02 Jul 2021 14:35:11 GMT < Connection: keep-alive < * Connection #0 to host myserver left intact Request received
Tùy chọn -v
của lệnh curl
sẽ hiển thị tất cả các tiêu đề yêu cầu và phản hồi cũng như các thông tin gỡ lỗi khác. Các dòng bắt đầu bằng >
sẽ cho biết các tiêu đề yêu cầu do máy khách gửi và các dòng bắt đầu bằng <
sẽ cho biết các tiêu đề phản hồi do máy chủ gửi. Các dòng bắt đầu bằng *
là thông tin do chính curl
tạo ra. Nội dung của phản hồi chỉ được hiển thị ở cuối, trong trường hợp này là dòng Request received
.
URL của dịch vụ, trong trường hợp này chứa tên máy chủ và cổng (http://myserver:8080
), sẽ được cung cấp làm đối số cho lệnh curl
. Bởi vì không có thư mục hoặc tên tệp nào được cung cấp nên chúng được đặt mặc định ở thư mục gốc /
. Dấu gạch chéo sẽ xuất hiện dưới dạng tệp yêu cầu trong dòng > GET / HTTP/1.1
, theo sau là tên máy chủ và cổng trong đầu ra.
Ngoài việc hiển thị các tiêu đề kết nối HTTP, lệnh curl
cũng hỗ trợ phát triển ứng dụng bằng cách cho phép ta gửi dữ liệu đến máy chủ bằng các phương thức HTTP khác nhau và ở các định dạng khác nhau. Tính linh hoạt này giúp gỡ lỗi mọi sự cố và triển khai các tính năng mới trên máy chủ một cách dễ dàng hơn.
Tuyến
Các yêu cầu mà máy khách có thể thực hiện đối với máy chủ phụ thuộc vào việc tuyến nào được xác định trong tệp index.js
. Một tuyến sẽ chỉ định một phương thức HTTP và xác định một đường dẫn (chính xác hơn là một URI) mà máy khách có thể yêu cầu.
Cho đến nay, máy chủ chỉ có một tuyến được cấu hình:
app.get('/', (req, res) => {
res.send('Request received')
})
Mặc dù chỉ là một tuyến rất đơn giản và chỉ trả lại một thông báo văn bản thuần túy cho máy khách, nó vẫn đủ để xác định các thành phần quan trọng nhất được sử dụng để cấu trúc hầu hết các tuyến:
-
Phương thức HTTP được tuyến sử dụng. Trong ví dụ này, phương thức HTTP
GET
được biểu thị bằng đặc tínhget
của đối tượngapp
. -
Đường dẫn được tuyến sử dụng. Khi máy khách không chỉ định đường dẫn cho yêu cầu, máy chủ sẽ sử dụng thư mục gốc - đây là thư mục cơ sở dành cho máy chủ web sử dụng. Một ví dụ ở phần sau trong chương này sử dụng đường dẫn
/echo
tương ứng với yêu cầu được gửi tớimyserver:8080/echo
. -
Hàm được thực thi khi máy chủ nhận được yêu cầu trên tuyến này thường được viết dưới dạng viết tắt là hàm mũi tên vì cú pháp
=>
trỏ đến định nghĩa của hàm không tên. Tham sốreq
(viết tắt của “request”) và tham sốres
(viết tắt của “response”) cung cấp thông tin chi tiết về kết nối và được truyền vào hàm bởi chính ứng dụng.
Phương thức POST
Để mở rộng chức năng của máy chủ thử nghiệm, hãy xem cách xác định tuyến cho phương thức HTTP POST
. Nó được khách sử dụng khi họ cần gửi thêm dữ liệu đến máy chủ ngoài những dữ liệu có trong tiêu đề yêu cầu. Tùy chọn --data
của lệnh curl
sẽ tự động gọi phương thức POST
và sẽ bao gồm nội dung được gửi đến máy chủ qua POST
. Dòng POST / HTTP/1.1
trong đầu ra sau đây cho thấy phương thức POST
đã được sử dụng. Tuy nhiên, máy chủ của chúng ta chỉ xác định một phương thức GET
; do đó, sẽ xảy ra lỗi khi ta sử dụng curl
để gửi yêu cầu qua POST
:
$ curl http://myserver:8080/echo --data message="This is the POST request body" * Trying 192.168.1.225:8080... * TCP_NODELAY set * Connected to myserver (192.168.1.225) port 8080 (#0) > POST / HTTP/1.1 > Host: myserver:8080 > User-Agent: curl/7.68.0 >Accept: / > Content-Length: 37 > Content-Type: application/x-www-form-urlencoded > * upload completely sent off: 37 out of 37 bytes * Mark bundle as not supporting multiuse < HTTP/1.1 404 Not Found < X-Powered-By: Express < Content-Security-Policy: default-src 'none' < X-Content-Type-Options: nosniff < Content-Type: text/html; charset=utf-8 < Content-Length: 140 < Date: Sat, 03 Jul 2021 02:22:45 GMT < Connection: keep-alive < <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot POST /</pre> </body> </html> * Connection #0 to host myserver left intact
Trong ví dụ trước, việc chạy curl
với tham số --data message="This is the POST request body"
cũng tương đương với việc gửi một biểu mẫu chứa trường văn bản có tên message
và có phần This is the POST request body
.
Do máy chủ được định cấu hình chỉ với một tuyến cho đường dẫn /
và tuyến đó chỉ phản hồi với phương thức HTTP GET
nên tiêu đề phản hồi sẽ có dòng HTTP/1.1 404 Not Found
. Ngoài ra, Express sẽ tự động tạo một phản hồi HTML ngắn với cảnh báo Cannot POST
.
Sau khi đã xem cách tạo yêu cầu POST
thông qua curl
, hãy viết một chương trình Express có thể xử lý yêu cầu thành công.
Trước tiên, hãy lưu ý rằng trường Content-Type
trong tiêu đề yêu cầu sẽ cho biết dữ liệu do khách gửi ở định dạng application/x-www-form-urlencoded
. Express sẽ không nhận ra định dạng đó theo mặc định. Vì vậy, chúng ta cần sử dụng mô-đun express.urlencoded
. Khi bao gồm mô-đun này, đối tượng req
--được truyền dưới dạng tham số cho hàm xử lý-- sẽ có bộ đặc tính req.body.message
tương ứng với trường message
do máy khách gửi. Mô-đun được tải với app.use
nên sẽ được đặt trước phần khai báo tuyến:
const express = require('express')
const app = express()
const host = "myserver"
const port = 8080
app.use(express.urlencoded({ extended: true }))
Khi thực hiện xong, ta chỉ cần thay đổi app.get
thành app.post
trong tuyến hiện có để thực hiện các yêu cầu được thực hiện qua POST
và khôi phục nội dung yêu cầu:
app.post('/', (req, res) => {
res.send(req.body.message)
})
Thay vì thay thế tuyến hiện tại, một lựa chọn khác là chỉ cần thêm tuyến mới này vì Express sẽ xác định phương thức HTTP trong tiêu đề yêu cầu và sử dụng tuyến thích hợp. Vì chúng ta quan tâm đến việc thêm nhiều chức năng vào máy chủ này nên sẽ thuận tiện hơn khi tách riêng từng chức năng bằng các đường dẫn riêng, chẳng hạn như /echo
và /ip
.
Đường dẫn và Trình Xử lý Hàm
Sau khi đã xác định phương thức HTTP nào sẽ phản hồi yêu cầu, bây giờ chúng ta cần xác định một đường dẫn cụ thể cho tài nguyên và một hàm xử lý và tạo phản hồi cho máy khách.
Để mở rộng chức năng echo
của máy chủ, chúng ta có thể xác định tuyến bằng cách sử dụng phương thức POST
với đường dẫn /echo
:
app.post('/echo', (req, res) => {
res.send(req.body.message)
})
Tham số req
của hàm xử lý có chứa tất cả các chi tiết yêu cầu được lưu dưới dạng thuộc tính. Nội dung của trường message
trong nội dung yêu cầu sẽ có sẵn trong thuộc tính req.body.message
. Ví dụ chỉ cần gửi trường này trở lại máy khách thông qua lệnh gọi res.send(req.body.message)
.
Hãy nhớ rằng những thay đổi ta thực hiện sẽ chỉ có hiệu lực sau khi khởi động lại máy chủ. Vì đang chạy máy chủ từ cửa sổ dòng lệnh trong các ví dụ trong chương này, ta có thể tắt máy chủ bằng cách nhấn kbd:[Ctrl+C] trên cửa sổ dòng lệnh đó. Sau đó, hãy chạy lại máy chủ thông qua lệnh node index.js
. Phản hồi mà máy khách nhận được đối với yêu cầu curl
mà chúng ta đã có trước đây hiện đã thành công:
$ curl http://myserver:8080/echo --data message="This is the POST request body" This is the POST request body
Các cách khác để truyền và trả lại thông tin trong yêu cầu GET
Việc sử dụng phương thức HTTP POST
có thể sẽ hơi thừa nếu ta chỉ cần gửi các tin nhắn văn bản ngắn như tin nhắn được sử dụng trong ví dụ. Trong những trường hợp như vậy, dữ liệu có thể được gửi dưới dạng chuỗi truy vấn bắt đầu bằng dấu chấm hỏi. Do đó, chuỗi ?message=This+is+the+message
có thể được bao gồm trong đường dẫn yêu cầu của phương thức HTTP GET
. Các trường được sử dụng trong chuỗi truy vấn sẽ có sẵn cho máy chủ trong đặc tính req.query
. Do đó, một trường có tên message
sẽ có sẵn trong đặc tính req.query.message
.
Một cách khác để gửi dữ liệu qua phương thức HTTP GET
là sử dụng các tham số tuyến của Express:
app.get('/echo/:message', (req, res) => {
res.send(req.params.message)
})
Tuyến trong ví dụ này khớp với các yêu cầu được thực hiện bằng phương thức GET
thông qua việc sử dụng đường dẫn /echo/:message
, trong đó :message
là trình giữ chỗ cho bất kỳ cụm từ nào được máy khách gửi cùng với nhãn đó. Các tham số này có thể truy cập được trong đặc tính req.params
. Với tuyến mới này, hàm echo
của máy chủ có thể được máy khách yêu cầu ngắn gọn hơn:
$ curl http://myserver:8080/echo/hello hello
Trong các tình huống khác, thông tin mà máy chủ cần để xử lý yêu cầu sẽ không cần phải được cung cấp rõ ràng bởi máy khách. Chẳng hạn, máy chủ có một cách khác để truy xuất địa chỉ IP công khai của máy khách. Thông tin đó có trong đối tượng req
theo mặc định trong đặc tính req.ip
:
app.get('/ip', (req, res) => {
res.send(req.ip)
})
Giờ đây, máy khách có thể yêu cầu đường dẫn /ip
bằng phương thức GET
để tìm địa chỉ IP công cộng của chính nó:
$ curl http://myserver:8080/ip 187.34.178.12
Máy khách có thể sửa đổi các đặc tính khác của đối tượng req
, đặc biệt là các tiêu đề yêu cầu có sẵn trong req.headers
. Ví dụ như đặc tính req.headers.user-agent
sẽ xác định chương trình nào đang đưa ra yêu cầu. Mặc dù đây không phải là thông lệ nhưng máy khách vẫn có thể thay đổi nội dung của trường này; vì vậy, máy chủ không nên sử dụng nó để xác thực chắc chắn một máy khách cụ thể. Điều quan trọng hơn nữa là xác thực dữ liệu do máy khách cung cấp một cách rõ ràng để tránh sự không nhất quán về ranh giới và định dạng có khả năng ảnh hưởng xấu đến ứng dụng.
Điều chỉnh Phản hồi
Như chúng ta đã thấy trong các ví dụ trước, tham số res
chịu trách nhiệm trả về phản hồi cho máy khách. Hơn nữa, đối tượng res
có thể thay đổi các khía cạnh khác của phản hồi. Bạn có thể nhận thấy rằng, mặc dù các phản hồi mà chúng ta đã triển khai cho đến nay chỉ là các tin nhắn văn bản đơn giản ngắn gọn, tiêu đề Content-Type
của các phản hồi lại đang sử dụng text/html; charset=utf-8
. Mặc dù điều này không ngăn phản hồi văn bản thuần túy được chấp nhận nhưng sẽ đúng hơn nếu chúng ta xác định lại trường này trong tiêu đề phản hồi thành text/plain
với cài đặt res.type('text/plain')
.
Các loại điều chỉnh phản hồi khác sẽ liên quan đến việc sử dụng cookies và cho phép máy chủ xác định máy khách đã đưa ra yêu cầu trước đó. Cookie rất quan trọng đối với các tính năng nâng cao, chẳng hạn như tạo các phiên riêng tư liên kết yêu cầu với một người dùng cụ thể; nhưng ở đây, chúng ta sẽ chỉ xem xét một ví dụ đơn giản về cách sử dụng cookie để xác định máy khách đã truy cập máy chủ trước đó.
Với thiết kế được mô đun hóa của Express, trình quản lý cookie phải được cài đặt bằng lệnh npm
trước khi được sử dụng trong tệp lệnh:
$ npm install cookie-parser
Sau khi cài đặt, trình quản lý cookie phải được đưa vào tệp lệnh máy chủ. Định nghĩa sau đây nên được đưa vào gần đầu tệp:
const cookieParser = require('cookie-parser')
app.use(cookieParser())
Để minh họa việc sử dụng cookie, hãy sửa đổi chức năng xử lý của tuyến bằng đường dẫn gốc /
đã tồn tại trong tệp lệnh. Đối tượng req
có đặc tính req.cookies
, trong đó, cookie được gửi trong tiêu đề yêu cầu được lưu giữ. Mặt khác, đối tượng res
có phương thức res.cookie()
để tạo cookie mới gửi đến máy khách. Hàm xử lý trong ví dụ sau sẽ kiểm tra xem cookie tên known
có tồn tại trong yêu cầu hay không. Nếu một cookie như vậy không tồn tại, máy chủ sẽ giả định rằng đây là khách truy cập lần đầu và gửi cho nó một cookie có tên đó thông qua lệnh gọi res.cookie('known', '1')
. Chúng ta sẽ tùy ý gán giá trị 1
cho cookie vì nó được cho là có một số nội dung, nhưng máy chủ sẽ không tham khảo giá trị đó. Ứng dụng này chỉ giả định rằng sự hiện diện đơn giản của cookie cho biết máy khách này trước đây đã yêu cầu tuyến này:
app.get('/', (req, res) => {
res.type('text/plain')
if ( req.cookies.known === undefined ){
res.cookie('known', '1')
res.send('Welcome, new visitor!')
}
else
res.send('Welcome back, visitor');
})
Theo mặc định, curl
không sử dụng cookie trong các giao dịch. Nhưng nó có các tùy chọn để lưu trữ (-c cookie.txt
) và gửi các cookie đã lưu trữ (-b cookie.txt
):
$ curl http://myserver:8080/ -c cookies.txt -b cookies.txt -v * Trying 192.168.1.225:8080... * TCP_NODELAY set * Connected to myserver (192.168.1.225) port 8080 (#0) > GET / HTTP/1.1 > Host: myserver:8080 > User-Agent: curl/7.68.0 >Accept: / > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < X-Powered-By: Express < Content-Type: text/plain; charset=utf-8 * Added cookie known="1" for domain myserver, path /, expire 0 < Set-Cookie: known=1; Path=/ < Content-Length: 21 < ETag: W/"15-l7qrxcqicl4xv6EfA5fZFWCFrgY" < Date: Sat, 03 Jul 2021 23:45:03 GMT < Connection: keep-alive < * Connection #0 to host myserver left intact Welcome, new visitor!
Vì lệnh này là lần truy cập đầu tiên kể từ khi cookie được triển khai trên máy chủ nên máy khách sẽ không có bất kỳ cookie nào để đưa vào yêu cầu. Như mong đợi, máy chủ không xác định cookie trong yêu cầu và do đó đã đưa cookie vào tiêu đề phản hồi như được chỉ ra trong dòng Set-Cookie: known=1; Path=/
của đầu ra. Vì chúng ta đã bật cookie trong curl
, một yêu cầu mới sẽ bao gồm cookie known=1
trong tiêu đề yêu cầu và cho phép máy chủ xác định sự hiện diện của cookie:
$ curl http://myserver:8080/ -c cookies.txt -b cookies.txt -v * Trying 192.168.1.225:8080... * TCP_NODELAY set * Connected to myserver (192.168.1.225) port 8080 (#0) > GET / HTTP/1.1 > Host: myserver:8080 > User-Agent: curl/7.68.0 >Accept: / > Cookie: known=1 > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < X-Powered-By: Express < Content-Type: text/plain; charset=utf-8 < Content-Length: 21 < ETag: W/"15-ATq2flQYtLMYIUpJwwpb5SjV9Ww" < Date: Sat, 03 Jul 2021 23:45:47 GMT < Connection: keep-alive < * Connection #0 to host myserver left intact Welcome back, visitor
Bảo mật Cookie
Nhà phát triển cần biết về các lỗ hổng tiềm ẩn khi sử dụng cookie để xác định máy khách đưa ra yêu cầu. Những kẻ tấn công có thể sử dụng các kỹ thuật như thực thi tệp lệnh liên trang (XSS) và giả mạo yêu cầu liên trang (CSRF) để đánh cắp cookie từ máy khách và từ đó mạo danh họ khi đưa ra yêu cầu tới máy chủ. Nói chung, các kiểu tấn công này sử dụng các trường chú thích không hợp lệ hoặc các URL được xây dựng tỉ mỉ để chèn mã JavaScript độc hại vào trang. Khi được thực thi bởi một máy khách xác thực, mã này có thể sao chép các cookie hợp lệ và lưu trữ hoặc chuyển tiếp chúng đến một đích đến khác.
Do đó, đặc biệt là trong các ứng dụng chuyên nghiệp, điều quan trọng là phải cài đặt và sử dụng các tính năng Express chuyên dụng hơn được gọi là phần mềm trung gian. Mô-đun express-session
hoặc cookie-session
cung cấp khả năng kiểm soát đầy đủ và an toàn hơn đối với việc quản lý phiên và cookie. Các thành phần này cho phép kiểm soát bổ sung để ngăn cookie bị chuyển hướng khỏi nhà phát hành ban đầu của chúng.
Bài tập Hướng dẫn
-
Làm cách nào để đọc nội dung của trường
comment
được gửi trong chuỗi truy vấn của phương thức HTTPGET
trong một hàm xử lý? -
Hãy viết một tuyến sử dụng phương thức HTTP
GET
và đường dẫn/agent
để gửi lại cho máy khách nội dung của tiêu đềuser-agent
. -
Express.js có một tính năng gọi là tham số tuyến, trong đó một đường dẫn chẳng hạn như
/user/:name
có thể được sử dụng để nhận tham sốname
do máy khách gửi. Làm cách nào để truy cập tham sốname
trong hàm xử lý của tuyến?
Bài tập Mở rộng
-
Nếu tên máy chủ là
myserver
, tuyến Express nào sẽ nhận được nội dung gửi theo mẫu bên dưới?<form action="/contact/feedback" method="post"> ... </form>
-
Trong quá trình phát triển máy chủ, lập trình viên không thể đọc được đặc tính
req.body
ngay cả sau khi xác minh rằng máy khách đang gửi nội dung một cách chính xác qua phương thức HTTPPOST
. Nguyên nhân chủ yếu của vấn đề này là gì? -
Điều gì sẽ xảy ra khi máy chủ có một tuyến được đặt thành đường dẫn
/user/:name
và máy khách đưa ra yêu cầu tới/user/
?
Tóm tắt
Bài học này đã giải thích cách viết tệp lệnh Express để nhận và xử lý các yêu cầu HTTP. Express sử dụng khái niệm tuyến để xác định các tài nguyên có sẵn cho máy khách, giúp bạn linh hoạt trong việc xây dựng máy chủ cho bất kỳ loại ứng dụng web nào. Bài học này đã đi qua các khái niệm và quy trình sau:
-
Các tuyến sử dụng các phương thức HTTP
GET
và HTTPPOST
. -
Cách dữ liệu biểu mẫu được lưu trữ trong đối tượng
request
. -
Cách sử dụng tham số tuyến.
-
Tùy chỉnh tiêu đề phản hồi.
-
Quản lý cookie cơ bản.
Đáp án Bài tập Hướng dẫn
-
Làm cách nào để đọc nội dung của trường
comment
được gửi trong chuỗi truy vấn của phương thức HTTPGET
trong một hàm xử lý?Trường
comment
đã có sẵn trong đặc tínhreq.query.comment
. -
Hãy viết một tuyến sử dụng phương thức HTTP
GET
và đường dẫn/agent
để gửi lại cho máy khách nội dung của tiêu đềuser-agent
.app.get('/agent', (req, res) => { res.send(req.headers.user-agent) })
-
Express.js có một tính năng gọi là tham số tuyến, trong đó một đường dẫn chẳng hạn như
/user/:name
có thể được sử dụng để nhận tham sốname
do máy khách gửi. Làm cách nào để truy cập tham sốname
trong hàm xử lý của tuyến?Tham số
name
có thể truy cập được trong đặc tínhreq.params.name
.
Đáp án Bài tập Mở rộng
-
Nếu tên máy chủ là
myserver
, tuyến Express nào sẽ nhận được nội dung gửi theo mẫu bên dưới?<form action="/contact/feedback" method="post"> ... </form>
app.post('/contact/feedback', (req, res) => { ... })
-
Trong quá trình phát triển máy chủ, lập trình viên không thể đọc được đặc tính
req.body
ngay cả sau khi xác minh rằng máy khách đang gửi nội dung một cách chính xác qua phương thức HTTPPOST
. Nguyên nhân chủ yếu của vấn đề này là gì?Lập trình viên đã không bao gồm mô-đun
express.urlencoded
cho phép Express trích xuất nội dung của yêu cầu. -
Điều gì sẽ xảy ra khi máy chủ có một tuyến được đặt thành đường dẫn
/user/:name
và máy khách đưa ra yêu cầu tới/user/
?Máy chủ sẽ đưa ra phản hồi
404 Not Found
vì tuyến yêu cầu tham số:name
do máy khách cung cấp.