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 请求头字段(不区分大小写的匹配)。
accepts() 根据请求的 HTTP 标字段检查指定的内容类型是否可接受。
acceptsEncodings() 返回指定编码的第一个接受编码。
acceptsCharsets() 返回指定字符集的第一个接受的字符集。
acceptsLanguages() 返回指定语言的第一个接受语言。
range() Range 标头解析器。
param() 返回 req 对象中 params
is() 如果传入请求的 内容类型 HTTP 头字段,则返回匹配的内容类型 匹配参数指定的 MIME 类型。

使用 defineGetter 函数扩展属性:

function defineGetter(obj, name, getter) {
  Object.defineProperty(obj, name, {
    configurable: true,
    enumerable: true,
    get: getter
  });
}
复制代码
属性 说明
protocol 协议
secure 是否安全
ip 请求的 ip 地址
ips 请求头中的 ip 地址数组
subdomains 请求中的子域名
path 包含请求 URL 的路径部分。
hostname 主机名
fresh 是否为最新的
stale 是否为过时的
xhr 请求中是否包 xmlHTTPRequest 字符串

这是属性还是跟 HTTP 通信,前后端通信 xhr,如:完整的路径 path/protocol/secure/subdomains, ip 相关,服务器相关 fresh/stable。

响应对象

在 res 对象上扩展方法:

属性和方法名 说明
status() 设置响应状态码。
links() 用给定的 links 设置头字段
send() 发送 HTTP 响应。
json() 发送 JSON 响应。
jsonp() 发送 JSONP 响应。
sendStatus() 发送状态码
sendFile() 在给定的路径处传输文件。
sendfile() 在给定的 .设置响应 HTTP 头字段 基于文件名的扩展名。
download() 下载文件
type() 将 HTTP 标头设置为由指定的。
format() 格式化请求对象的上内容
attachment() 在响应头中添加额外的内容
append() 将数据最加到尾部
set()/header() 设置 http 头信息
get() 获取指定 http 头数据
clearCookie() 清除 cookie 内容
cookie() 设置 cookie
location() 将响应 HTTP 标头设置为指定的参数。
redirect() 重定向地址
vary() 使用 vary 方法添加字段到请求头
render() 渲染模板中 html

设置状态码

res.status(203)
console.log(res.statusCode)
res.send("get v1: hello world!")
复制代码

如何来快速测试这些属性和方法呢?

  • 准备好接口, 熟悉 restful api 或者其他范式的形式接口
  • 准备写接口时的工具。curl(熟悉命令行)、工具(类似于:postman 等等)
  • 将工具接口与 express 的接口对应起来进行调试测试,验证属性。本项目使用

下面给出一些示例代码

目录结构

.
├── __tests__
├── babel.config.js
├── index.js
├── index.md
├── jest.config.js
├── node_modules
├── package.json
├── pnpm-lock.yaml
├── public
└── views
复制代码

安装依赖

  • views 中的 home.ejs 需要 ejs, 内容如下:
<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 协议
  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 已经被废弃
  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");
});
复制代码

小结

本文主要介绍了 express 的请求和响应对象,以及集成对象,各种用途,并使用一个实例,来进行说明。在测试实际接口时候,使用了 nodemon 来自动重启服务,使用 apifox 来保存接口重复发送测试接口。

以上就是Express框架req res对象使用详解的详细内容,更多关于Express框架req res对象的资料请关注脚本之家其它相关文章!

你可能感兴趣的:(Express框架req res对象使用详解)