Express框架req?res對象使用詳解
正文
Express 請求 req 和響應 res 對象定義:
var req = Object.create(http.IncomingMessage.prototype) var res = Object.create(http.ServerResponse.prototype)
下面是屬性繼承關系:
原型 | 繼承來源類 |
---|---|
http.IncomingMessage.prototype | Stream.Reabable |
http.ServerResponse.prototype | IncomingMessage |
IncomingMessage
class IncomingMessage extends stream.Readable { constructor(socket: Socket); aborted: boolean; httpVersion: string; httpVersionMajor: number; httpVersionMinor: number; complete: boolean; connection: Socket; socket: Socket; headers: IncomingHttpHeaders; rawHeaders: string[]; trailers: NodeJS.Dict<string>; rawTrailers: string[]; setTimeout(msecs: number, callback?: () => void): this; method?: string | undefined; url?: string | undefined; statusCode?: number | undefined; statusMessage?: string | undefined; destroy(error?: Error): this; }
ServerResponse
class ServerResponse<Request extends IncomingMessage = IncomingMessage> extends OutgoingMessage<Request> { statusCode: number; statusMessage: string; constructor(req: Request); assignSocket(socket: Socket): void; detachSocket(socket: Socket): void; writeContinue(callback?: () => void): void; writeEarlyHints(hints: Record<string, string | string[]>, callback?: () => void): void; writeHead( statusCode: number, statusMessage?: string, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[], ): this; writeHead(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this; writeProcessing(): void; }
接下來的任務還是很簡單,看看 express 是如何處理請求 req 對象上的屬性和方法。
請求對象 req
在 req 對象上擴展方法
屬性和方法名 | 說明 |
---|---|
get()/header() | 返回指定的 HTTP 請求頭字段(不區(qū)分大小寫的匹配)。 |
accepts() | 根據(jù)請求的 HTTP 標字段檢查指定的內(nèi)容類型是否可接受。 |
acceptsEncodings() | 返回指定編碼的第一個接受編碼。 |
acceptsCharsets() | 返回指定字符集的第一個接受的字符集。 |
acceptsLanguages() | 返回指定語言的第一個接受語言。 |
range() | Range 標頭解析器。 |
param() | 返回 req 對象中 params |
is() | 如果傳入請求的 內(nèi)容類型 HTTP 頭字段,則返回匹配的內(nèi)容類型 匹配參數(shù)指定的 MIME 類型。 |
使用 defineGetter 函數(shù)擴展屬性:
function defineGetter(obj, name, getter) { Object.defineProperty(obj, name, { configurable: true, enumerable: true, get: getter }); }
屬性 | 說明 |
---|---|
protocol | 協(xié)議 |
secure | 是否安全 |
ip | 請求的 ip 地址 |
ips | 請求頭中的 ip 地址數(shù)組 |
subdomains | 請求中的子域名 |
path | 包含請求 URL 的路徑部分。 |
hostname | 主機名 |
fresh | 是否為最新的 |
stale | 是否為過時的 |
xhr | 請求中是否包 xmlHTTPRequest 字符串 |
這是屬性還是跟 HTTP 通信,前后端通信 xhr,如:完整的路徑 path/protocol/secure/subdomains, ip 相關,服務器相關 fresh/stable。
響應對象
在 res 對象上擴展方法:
屬性和方法名 | 說明 |
---|---|
status() | 設置響應狀態(tài)碼。 |
links() | 用給定的 links 設置頭字段 |
send() | 發(fā)送 HTTP 響應。 |
json() | 發(fā)送 JSON 響應。 |
jsonp() | 發(fā)送 JSONP 響應。 |
sendStatus() | 發(fā)送狀態(tài)碼 |
sendFile() | 在給定的路徑處傳輸文件。 |
sendfile() | 在給定的 .設置響應 HTTP 頭字段 基于文件名的擴展名。 |
download() | 下載文件 |
type() | 將 HTTP 標頭設置為由指定的。 |
format() | 格式化請求對象的上內(nèi)容 |
attachment() | 在響應頭中添加額外的內(nèi)容 |
append() | 將數(shù)據(jù)最加到尾部 |
set()/header() | 設置 http 頭信息 |
get() | 獲取指定 http 頭數(shù)據(jù) |
clearCookie() | 清除 cookie 內(nèi)容 |
cookie() | 設置 cookie |
location() | 將響應 HTTP 標頭設置為指定的參數(shù)。 |
redirect() | 重定向地址 |
vary() | 使用 vary 方法添加字段到請求頭 |
render() | 渲染模板中 html |
設置狀態(tài)碼
res.status(203) console.log(res.statusCode) res.send("get v1: hello world!")
如何來快速測試這些屬性和方法呢?
- 準備好接口, 熟悉 restful api 或者其他范式的形式接口
- 準備寫接口時的工具。curl(熟悉命令行)、工具(類似于:postman 等等)
- 將工具接口與 express 的接口對應起來進行調(diào)試測試,驗證屬性。本項目使用
下面給出一些示例代碼
目錄結(jié)構(gòu)
. ├── __tests__ ├── babel.config.js ├── index.js ├── index.md ├── jest.config.js ├── node_modules ├── package.json ├── pnpm-lock.yaml ├── public └── views
安裝依賴
- views 中的 home.ejs 需要 ejs, 內(nèi)容如下:
<html> <head> <title>Home 頁面</title> </head> <body> <h2>歡迎來到 Home 頁面</h2> </body> </html>
安裝其他的依賴包:
pnpm install ejs babel-jest dirname-filename-esm jest nodemon supertest @babel/preset-react @babel/preset-env @babel/plugin-syntax-jsx @babel/core
看看 package.json 項目配置
{ "name": "debugger-source-code", "version": "1.0.0", "description": "", "main": "index.js", "type": "module", "scripts": { "dev": "nodemon index.js", "test": "NODE_OPTIONS=--experimental-vm-modules jest" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@babel/core": "^7.21.0", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", "babel-jest": "^29.4.3", "dirname-filename-esm": "^1.1.1", "ejs": "^3.1.8", "express": "^4.18.2", "jest": "^29.4.3", "nodemon": "^2.0.20", "supertest": "^6.3.3" } }
看看 babel 配置
export default { presets: [ ["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-react", ], };
看看 eslint 配置
module.exports = { "env": { "browser": true, "es2021": true }, "extends": "eslint:recommended", "overrides": [ ], "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "rules": { } }
看看 jest 配置
export default { transform: { '\\.[jt]s?$': 'babel-jest' }, };
express 主要服務 index.js
import express from "express"; import path from "path"; import { dirname } from "dirname-filename-esm"; const __dirname = dirname(import.meta); const app = express(); app.set("view engine", "ejs"); app.use(express.static(path.join(__dirname, "public"))); app.get("/req", (req, res, next) => { console.log(req.protocol); // http 協(xié)議 console.log(req.secure); //fals console.log(req.ip); //::1 console.log(req.ips); // [] console.log(req.subdomains); // [] console.log(req.path); // /favicon.ico console.log(req.host); // localhost 已經(jīng)被廢棄 console.log(req.hostname); // localhost console.log(req.fresh); // false console.log(req.stale); // true console.log(req.xhr); //false //------------- get ------------- // let a1 = req.get("set-cookie"); console.log("set-cookie", a1); // undefined //------------- header ------------- // let a2 = req.header("set-cookie"); console.log("set-cookie", a2); // undefined //------------- accepts ------------- // let b1 = req.accepts(); console.log("accepts", b1); // accepts [ // 'image/avif', // 'image/webp', // 'image/apng', // 'image/svg+xml', // 'image/*', // '*/*' // ] //------------- acceptsEncodings ------------- // let b2 = req.acceptsEncodings(); console.log("acceptsEncodings", b2); // [ 'gzip', 'deflate', 'br', 'identity' ] //------------- acceptsLanguages ------------- // let c1 = req.acceptsLanguages(); console.log("acceptsLanguages", c1); // [ 'zh-CN', 'zh' ] //------------- range ------------- // let range = req.range(10, {}); console.log("range", range); // undefined //------------- param ------------- // let param = req.param(); console.log("param", param); // undefined res.send("hello world!"); }); app.get("/res/status", (req, res, next) => { res.status(203); console.log(res.statusCode); res.send("get v1: hello world! and status code: 203 === " + res.statusCode); }); app.get("/res/statusCode", (req, res, next) => { res.send("get v1: hello world! and status code:" + res.statusCode); }); app.get("/res/links", (req, res, next) => { res.links({ a: "http://localhost:3232", }); res.send("links set"); // header Link filed }); app.get("/res/send", (req, res, next) => { res.send("links set"); //type: string }); app.get("/res/send/object", (req, res, next) => { res.send({ msg: "123" }); // type object json }); app.get("/res/send/json", (req, res, next) => { res.json(JSON.stringify({ msg: "json" })); // type object json }); app.get("/res/send/jsonp", (req, res, next) => { let fn = req.query.fn; let data = JSON.stringify({ data: "mydata", }); res.end(fn + data); // type object json }); app.get("/res/send/sendStatus", (req, res, next) => { res.sendStatus(404); }); app.get("/res/send/sendFile", (req, res, next) => { res.sendFile(path.join(__dirname, "jest.config.js")); }); app.get("/res/send/download", (req, res, next) => { res.download(path.join(__dirname, "jest.config.js")); }); app.get("/res/send/type", (req, res, next) => { res.type(".html").send("<div>123</div>"); // image/png console.log(res.get("Content-type")); }); app.get("/res/send/format", (req, res, next) => { res.format({ "text/html": function () { res.send("<div>This is html</div>"); }, "text/pain": function () { res.send("this is html text"); }, "application/json": function () { res.send({ message: "This is html json" }); }, default: function () { res.status(406).send("Not Acceptable"); }, }); }); app.get("/res/send/attachment", (req, res, next) => { res.attachment("index.md"); console.log(req.get("Content-Disposition")); res.send("attachment"); // attachment; filename="index.md" }); app.get("/res/send/append", (req, res, next) => { res.append("Warning", "201 Warning"); console.log(res.get("Warning")); // Warning 201 Warning res.send("append"); }); app.get("/res/send/set", (req, res, next) => { res.set("set8", "set8888"); //響應 header 中 res.send("set"); }); app.get("/res/send/header", (req, res, next) => { res.header("set9", "set9999"); //響應 header 中 res.send("set9"); }); app.get("/res/send/get", (req, res, next) => { res.set({ "Content-Type": "text/plain", "Content-Length": "123", ETag: "12345", }); let ct = res.get("Content-Type"); //響應 header 中 res.send("[get => ]" + ct); }); app.get("/res/send/cookie", (req, res, next) => { res.cookie("abc", "dd"); //響應 header 中 res.send("cookie: abcdd"); }); app.get("/res/send/clearCookie", (req, res, next) => { res.cookie("abc", "dd"); res.cookie("def", "xj"); res.clearCookie("abc"); res.send("cookie: abcdd"); }); app.get("/res/send/location", (req, res, next) => { res.location("http://demo.com"); console.log(res.get("location")); // http://demo.com res.send(res.get("location")); }); app.get("/res/send/redirect", (req, res, next) => { res.redirect("/res/send/redirect-new"); }); app.get("/res/send/redirect-new", (req, res, next) => { res.send("this is redirect-new"); }); app.get("/res/send/vary", (req, res, next) => { res.vary("User-Agent").send("Field added to the Vary response header"); }); app.get("/res/send/render", (req, res, next) => { res.render('home') }); app.listen(3232, () => { console.log("listening on http://localhost:3232"); });
小結(jié)
本文主要介紹了 express 的請求和響應對象,以及集成對象,各種用途,并使用一個實例,來進行說明。在測試實際接口時候,使用了 nodemon 來自動重啟服務,使用 apifox 來保存接口重復發(fā)送測試接口。
更多關于Express框架req res對象的資料請關注腳本之家其它相關文章!
相關文章
JavaScript詞法作用域與調(diào)用對象深入理解
關于 Javascript 的函數(shù)作用域、調(diào)用對象和閉包之間的關系很微妙,關于它們的文章已經(jīng)有很多,本文做了一些總結(jié),需要的朋友可以參考下2012-11-11微信小程序中的canvas 文字斷行和省略號顯示功能的處理方法
大家都知道在canvas中沒有提供方法來處理文字的多行問題,只有通過截取指定字符串來達到目的。接下來通過本文給大家介紹微信小程序中的canvas 文字斷行和省略號顯示功能 ,需要的朋友可以參考下2018-11-11通過Tabs方法基于easyUI+bootstrap制作工作站
本教程給大家介紹如何制作easyUI+bootstrap工作站,主要學習tabs方法,本文介紹非常詳細,具有參考借鑒價值,需要的朋友參考下吧2016-03-03bootstrap jquery dataTable 異步ajax刷新表格數(shù)據(jù)的實現(xiàn)方法
這篇文章主要介紹了bootstrap jquery dataTable 異步ajax刷新表格數(shù)據(jù)的實現(xiàn)方法,需要的朋友可以參考下2017-02-02讓你的博文自動帶上縮址的實現(xiàn)代碼,方便發(fā)到微博客上
添加以下代碼到你的博客中: (呵呵,抄襲至lulu Studio http://s8.hk/0itw)2010-12-12微信小程序setInterval定時函數(shù)新手使用的超詳細教程
平時開發(fā)中為實現(xiàn)倒計時效果可以使用setInterval即可,下面這篇文章主要給大家介紹了關于微信小程序setInterval定時函數(shù)新手使用的超詳細教程,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-08-08