Express框架req res对象使用详解

目录
  • 正文
  • IncomingMessage
  • ServerResponse
  • 请求对象 req
  • 响应对象
    • 设置状态码
  • 如何来快速测试这些属性和方法呢?
  • 下面给出一些示例代码
    • 目录结构
    • 安装依赖
  • 小结

正文

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对象的资料请关注我们其它相关文章!

(0)

相关推荐

  • Express框架两个内置中间件方法详解

    目录 什么是中间件 两个内置的中间件 init 方法 query 中间件 被使用 小结 什么是中间件 中间件,就是具有串联执行能力的函数,Express中两种层面的中间件.app 层面的中间件, router 层面的中甲件.在 express 中, 一般通过 use 方法和路由的方法添加中间件. 两个内置的中间件 init 中间件方法 query 中间件方法 init 方法 exports.init = function(app){ return function expressInit(req

  • react express实现webssh demo解析

    目录 正文 实现 WebSSH 的基本思路 实现 Demo 的代码 服务器端代码 前端代码 在 React 应用中使用 WebSSH 组件 效果 总结 正文 下面是一个简单的 WebSSH Demo,实现了通过浏览器连接 SSH 服务器并进行交互的功能. 实现 WebSSH 的基本思路 WebSSH 可以分成以下几个模块: 前端界面:使用 xterm.js 实现一个基于浏览器的终端界面. WebSocket 连接:使用 WebSocket 连接连接 WebSSH 服务器后端. SSH 连接:使用

  • Express框架Router Route Layer对象使用示例详解

    目录 引言 Layer Route Router 方法统计 两个 stack 取出 stack 中 layer 从 Router 到 layer 的路径 Router.route 方法中的 dispatch next 函数 小结 引言 这使用倒叙的方式: 将 Layer 放在最前面讲解,然后是 Route 路由项目,最后是 Router 路由器. Layer Layer 是什么? Express 中最小的存储单元,存储的重要内容包括 handle 也就是 fn.path 等路径.fn 就是中间件

  • Express代理转发服务器实现

    目录 express的代理转发 项目结构 转发 转发记录 前端页面 express的代理转发 其实我的内心关于这个Express,我的内心是拒绝的,不是说,我对这个框架有什么看法,而是因为这个大作业的问题.是的我还是一个大三老菜鸡,苦练 Java 全干开发,Python 人工智能 整整 一坤年.期间拿了几个奖,水了篇论文 而已. 那么这篇文章主要做的,其实很简单就是,做个代理转发.前端请求,先到express服务器,然后转发到flask服务器,为什么非要转发呢,原因很简单,web作业非要用nod

  • Express框架中_router 对象数据结构使用详解

    目录 _router 对象介绍 使用调试直观的获取 _router 对象 一个简单的可以运行的 demo 使用 vscode 初始化一个调试文件 在合适的地点打一个断点 启动服务 观察全部属性并找到 _router 对象以及属性 找出 stack.layer 的排列顺序 分析 _router 的嵌套对象 _router 对象的相关源码 _router 的数据结构分析 小结 _router 对象介绍 _router 对象是一个私有的属性,但是它保存了重要的内容.其中就包括所有的合理的 Layer

  • node.js使用express框架进行文件上传详解

    关于node.js使用express框架进行文件上传,主要来自于最近对Settings-Sync插件做的研究. 目前的研究算是取得的比较好的进展. Settings-Sync中通过快捷键上传文件,其实主要还是请求后端接口. 于是我便使用node.js模拟一个服务,这个服务其实就相当于github api(Settings-Sync实际请求的接口,比如token验证,gist存储创建等都是来自github 对应的api). 话不多说,直接代码贴起讲解: 1.创建一个node.js项目(这里我以ex

  • Python测试框架pytest核心库pluggy详解

    目录 代码案例 实例化: 添加到钩子定义中 (add_hookspecs) 注册插件 register 运行插件 pm.hook.myhook 代码案例 import pluggy # HookspecMarker 和 HookimplMarker 实质上是一个装饰器带参数的装饰器类,作用是给函数增加额外的属性设置 hookspec = pluggy.HookspecMarker("myproject") hookimpl = pluggy.HookimplMarker("m

  • Windows系统下nodejs、npm、express的下载和安装教程详解

    1. node.js下载 首先进入http://nodejs.org/dist/,这里面的版本呢,几乎每个月都出几个新的,建议大家下载最新版本,看看自己的电脑是多少位的,别下错了. 下载完解压到你想放的位置就好了,解压后你会发现里面有node.exe.我解压到了D:\software_install文件夹. 接下来去命令行,即点击电脑左下角的开始-->运行-->cmd. 进入node.exe所在的目录,输入node -v,查看你的node版本.我的路径如下图所示: 如果你获得以上输出结果,说明

  • C#动态对象(dynamic)详解(实现方法和属性的动态)

    C#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种动态方法的实现,看起来有点javascript的对象味道: 1) 定义一个委托,参数个数可变,参数都是object类型:这里的委托多有个dynamic参数,代表调用这个委托的动态对象本身. public delegate object MyDelegate(dynamic Sender, params object[] PMs

  • Vue-router的使用和出现空白页,路由对象属性详解

    Vue-router的使用和出现空白页 2018.08.28 更新 vue-router:前端路由系统--改变视图的同时不会向后端发出请求 1. hash 2.history 2018.06.25 更新 get到一个新技能 import Vue from 'vue' import Router from 'vue-router' import api from '../lib/service' //接口文档 Vue.use(Router) const router = { mode: 'hist

  • Java下Struts框架中的ActionForm类详解

    ActionForm的应用 (1) .创建一个form类必须继承四个父类中的一个.比如继承ActionForm. (2) .一个form类中的每一个属性都将和页面中form 表单中的每一个元素一一对应 例如. 一个表单为: <form> <input type="text" name="username"></input> <input type="password" name="passwor

  • IDEA SSM框架整合配置及步骤详解

    参考 狂神说SpringMVC05:整合SSM框架 https://mp.weixin.qq.com/s?__biz=Mzg2NTAzMTExNg==&mid=2247484004&idx=1&sn=cef9d881d0a8d7db7e8ddc6a380a9a76&scene=19#wechat_redirect 前言 根据自己的环境参考狂神的视频进行了SSM框架整合,用于备忘 SSM框架整合步骤 1. 创建数据库 2. IDEA创建maven项目.在pom.xml中设设置

  • Java Spring框架简介与Spring IOC详解

    目录 Spring简介和配置 1.Spring概述 1.1 spring 是什么 1.2 Spring发展历程 1.3 Spring的优势 (理解) \1. 方便解耦,简化开发 \2. AOP 编程的支持 \3. 声明式事务的支持 \4. 方便程序的测试 \5. 方便集成各种优秀框架 \6. 降低 JavaEE API 的使用难度 \7. Java 源码是经典学习范例 1.4 Spring的体系结构(了解) 2.Spring IoC快速入门 2.1 IoC的概念和作用 2.2 Spring Io

  • Java集合框架之Set和Map详解

    目录 Set接口 HashSet TreeSet Map接口 HashMap TreeMap Set接口 set接口等同于Collection接口,不过其方法的行为有更严谨的定义.set的add方法不允许增加重复的元素.要适当地定义set的equals方法:只要俩个set包含同样的元素就认为它们是相同的,而不要求这些元素有相同的顺序.hashCode方法的定义要保证包含相同元素的俩个set会得到相同的散列码. --Java核心技术 卷一 public interface Set<E> exte

  • Spring Data JPA框架的Repository自定义实现详解

    目录 1. Spring Data Repository自定义实现 1.1 自定义特殊repository 1.2 配置类 1.3 解决歧义 1.4 手动装配 1.5 自定义Base Repository 1. Spring Data Repository自定义实现 Spring Data提供了各种选项来创建查询方法,只需少量编码.但是当这些选项不能满足你的需求时,你也可以为资源库方法提供你自己的自定义实现.本节主要介绍如何做到这一点. 1.1 自定义特殊repository 要用自定义的功能实

随机推荐