express 基本使用

Nodejs 第二十九章(express)
Nodejs 第三十章(防盗链)

1. 安装

pnpm init
pnpm add express
  • 配置package.json
  "main": "app.js",
  "type":"module",

2. 使用

1. 监听端口

  • app.js
// 引入
import express from 'express';
// 实例
const app = express();
// 监听3000 端口
app.listen(3000, () => {
  console.log('Server is running on port 3000')
})
  • 执行命令
node app.js
  • 控制台输出
Server is running on port 3000

2. 基本的get和post请求

  • /app.js
import express, { json } from 'express';

const app = express();

app.get('/login',(req,res)=>{
  // http://localhost:3000/login?name=lili
  console.log(req.query)  // { name: 'lili' }
  res.send('login page')
})

app.get('/reg/:user',(req,res)=>{
  // http://localhost:3000/reg/lily
  console.log(req.params) // { user: 'lily' }
  res.send('reg page')
})

app.use(json())
// post 要接收json数据,需要配置 app.use(json())
app.post('/list',(req,res)=>{
  // http://localhost:3000/list   数据: {"username": "jack"}
  console.log(req.body) // { username: 'jack' }
  res.send('list page')
})

app.listen(3000, () => {
  console.log('Server is running on port 3000')
})

3. 使用路由

  • ./src/list.js
import express from 'express';

const router = express.Router();

router.post('/list',(req,res)=>{
  if (req.body.username == 'jack')
  // 服务器返回json格式数据
    res.json({
      code: 1,
      message: 'success',
      data: []
    })
  else{
    res.json({
      code:0,
      message: 'fail'
    })
  }
})

export default router;
  • ./src/user.js
import express from "express";
const router = express.Router();

router.get("/login", (req, res) => {
  res.send("login page");
});

router.get("/reg/:user", (req, res) => {
  res.send("reg page");
});

export default router;
  • app.js
import express, { json } from 'express';
// 引入两个路由
import User from './src/user.js'
import List from './src/list.js'

const app = express();
app.use(json())
// 挂载路由,用户访问时路径不同,使用的路由不同
app.use('/',User)
app.use('/api',List)


app.listen(3000, () => {
  console.log('Server is running on port 3000')
})

4. 中间件

**作用:**所有请求都会先通过中间件进行处理

  • ./middleware/middle.js
const middleware = (req,res,next)=>{
  console.log('所有请求都会经过中间件')
  next()	// 必须有next,不然会卡在这里
}

export default middleware
  • ./app.js
import express, { json } from 'express';
// 引入中间件
import middleware from './middleware/middle.js'
const app = express();
// 使用中间件,必须在路由前面
app.use(middleware)

5. 在中间件中记录日志

  1. 安装log4js
pnpm add log4js
  1. 配置log4js
  • ./middleware/logger.js
import log4js from 'log4js';
// 配置log4js
log4js.configure({
    // 输出方式
    appenders:{
      // 在控制台输出
        out:{
          type:'stdout',
          layout:{  // 控制台输出的样式
            type:'colored'   // 输出颜色
          }
        },
        // 在文件中输出
        file:{
          type:'file',
          filename:'./log/server.log',
          // filename:'./server.log',
        }
    },
    // 配置记录,什么样级别的事件,要如何处理    
    categories:{
      // 默认配置:debug级别,并且在控制台和文件中都输出
      default:{
        appenders:['out','file'],
        level:'debug'
      }
    }
})

export default log4js.getLogger('default')
  1. 在中间件中使用日志记录
  • ./middleware/middle.js
// 使用日志记录
import logger from './logger.js'
const middleware = (req,res,next)=>{
  // 日志中记录请求的方法和请求的地址。
  // logger.debug,调用事件记录,记录到debug的事件中
  logger.debug(`[${req.method}]${req.url}`)
  next()
}

export default middleware

3. 防盗链

作用: 防止其他人使用本站的静态资源

  • 在请求头的referer记录请求静态资源的网址,需要比对referer中的值,制作可以访问静态资源的白名单
req.get('referer')	// 获取请求头中referer的值
import express, { json } from "express";
const app = express();
// 静态资源访问的白名单
const httpList = ["localhost"];
const placeStolenLinks = (req, res, next) => {
  // referer:请求来源
  const referer = req.get("referer");
  // 判断请求来源是否为 httpList中的地址
  if (referer) {
    const url = new URL(referer);
    const hostname = url.hostname;// 从referer中解析出主机名
    if (!httpList.includes(hostname)) {
      return res.status(403).send("非法请求");
    }
  }
  next();
};
app.use(placeStolenLinks);
// 设置静态资源访问的文件夹
app.use(express.static("public"));

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});

4. cors

CORS(Cross-Origin Resource Sharing,跨源资源共享)是一种安全机制,用于限制一个域上的网页如何与另一个域上的资源进行交互。当一个网页尝试从不同的源(协议、域名或端口)请求资源时,浏览器会实施同源策略,阻止这种请求,除非服务器明确允许。

1. 同源策略

  • app.js
import express from "express";

const app = express();

app.get('/',(req, res)=>{
  res.json({message: "Hello World"})
})
app.listen(3000, () => console.log("Server is running on port 3000"));
  • index.html
    • 网页通过fetch发送请求,默认发送的是get请求
<script>
  fetch('http://localhost:3000').then(res => res.json()).then(data => console.log(data))
</script>
  • 浏览器发生错误
    • 浏览器与请求的地址,域名和端口不同触发了浏览器的同源策略,无法发送请求
Access to fetch at 'http://localhost:3000/' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

2. 简单请求

  • 对于请求方法是:GET、HEAD、POST
  • 请求头:仅包含以下几种:Accept、Accept-Language、Content-Language、Content-Type(仅限于 application/x-www-form-urlencoded、multipart/form-data、text/plain)
app.use('*',(req,res,next)=>{
  // 所有来源都同意,缺点:无法设置session,一般不用这种方法
  // res.setHeader("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Origin", "http://127.0.0.1:5500")
  next()
})

说明:
1. res.setHeader:nodejs提供的原生方法
2. res.header:express提供的方法。返回res对象,支持链式调用

  • 浏览器响应头中的数据:

    在这里插入图片描述

3. 预检请求

触发预检请求的条件:
1. 请求方法不是:GET、HEAD、POST
2. Content-Type的值不是 application/x-www-form-urlencoded、multipart/form-data、text/plain这3个

  1. 发送除GET、HEAD、POST之外的请求
  • 发送patch请求
  fetch('http://localhost:3000/patch',{
    method:'PATCH'
  }).then(res => res.json()).then(data => console.log(data))
  • 浏览器错误
Access to fetch at 'http://localhost:3000/' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.
  • 解决方法
app.use('*',(req,res,next)=>{
  res.header("Access-Control-Allow-Origin", "http://127.0.0.1:5500")
  // 设置可以通过同源策略的请求方法
  res.header("Access-Control-Allow-Methods", "PUT,DELETE,PATCH")
  next()
})
app.patch('/patch',(req, res)=>{
  res.json({message: "patch request"})
})
  • 浏览器响应头的数据

    在这里插入图片描述

  • 浏览器网络请求中的预检
    在这里插入图片描述

  1. Content-Type的值
  • 请求体中 ‘content-type’: ‘application/json’
  fetch('http://localhost:3000', {
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: "xiaoming"
    }),
    method: 'POST'
  }).then(res => res.json()).then(data => console.log(data))
  • 浏览器报错
Access to fetch at 'http://localhost:3000/' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
  • 解决方法
app.use('*',(req,res,next)=>{
  res.header("Access-Control-Allow-Origin", "http://127.0.0.1:5500")
  res.header("Access-Control-Allow-Methods", "PUT,DELETE,PATCH")
  // 允许客户端在实际请求中使用 Content-Type 请求头
  res.header("Access-Control-Allow-Headers", "Content-Type")
  next()
})
app.post('/post',(req,res)=>{
  console.log(req.body)
  res.json({message: "post request"})
})
  • 浏览器的响应体
    在这里插入图片描述
  • 同样触发了预检
    在这里插入图片描述

4. 自定义响应头

  1. 定义响应头
app.get('/',(req, res)=>{
  // 自定义响应头
  res.set('self-defined-header', '123456')
  // 设置Access-Control-Expose-Headers,将自定义的响应头抛出
  res.header('Access-Control-Expose-Headers', 'self-defined-header')
  res.json({message: "Hello World"})
})
  1. 接收
fetch('http://localhost:3000').then(res => {
  // 通过res.headers.get获取到响应头
  console.log(res.headers.get('self-defined-header'))
  return res.json()}).then(data => console.log(data))

在这里插入图片描述

5. 单工通讯sse

作用: 后端可以一直给前端发数据,前端只在请求时给后端发一次数据

  • 后端
app.get('/sse',(req,res)=>{
  // 设置响应头
  res.header('Content-Type','text/event-stream')
  // 每隔一秒发送一次消息
  setInterval(()=>{
    res.write('data: ' + new Date() + '\n')
  },1000)
})
  • 前端
<script>
    const sse = new EventSource('http://localhost:3000/sse')
    // 默认监听的类型是message,可以在后端改,没必要
    sse.addEventListener('message',(e)=>{
      console.log(e.data)
    })
</script>
  • 效果
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/893420.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据分享】全国文化-限额以上文化批发和零售业企业情况(2017-2021年)

数据介绍 一级标题指标名称文化限额以上文化批发和零售业企业单位数文化限额以上内资文化批发和零售业企业企业单位数文化限额以上港、澳、台商投资文化批发和零售业企业企业单位数文化限额以上外商投资文化批发和零售业企业企业单位数文化限额以上国有控股文化批发和零售业企业…

设置 Notepad++ 制表符(Tab 缩进)宽度为2个空格大小

Notepad 默认的制表符宽度是 4 个空格的大小&#xff0c;一个规模比较大的代码段或者 xml 等文件&#xff0c;小屏幕打开时看到的情景真的和让人着急&#xff0c;拖来拖去&#xff01;有两种方案可以解决这种情况。 修改缩进为空格 这种我们不太推荐&#xff0c;但是有些公司…

刚刚,ChatGPT推出Windows客户端!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…

SpringBoot优雅下线

一&#xff0c;什么是优雅下线 当我们需要部署新版本代码的时候&#xff0c;需要重启服务&#xff0c;这个时候可能会出现一些问题&#xff0c;比如之前服务正在处理的请求还在处理&#xff0c;这个时候如果强制的停止服务&#xff0c;会造成数据丢失或者请求失败的情况。那么…

Vue项目中实现拖拽上传附件:原生JS与Element UI组件方法对比

在现代化的Web应用中&#xff0c;文件上传是一个基本功能。随着技术的发展&#xff0c;拖拽上传已经成为提升用户体验的一个重要特性。在Vue项目中&#xff0c;我们可以通过原生JavaScript或使用Element UI组件来实现这一功能。下面我们将分别介绍这两种方法&#xff0c;并对比…

第十二章 RabbitMQ之失败消息处理策略

目录 一、引言 二、RepublishMessageRecoverer 实现 2.1. 实现步骤 2.2. 实现代码 2.2.1. 异常交换机队列回收期配置类 2.2.2. 常规交换机队列配置类 2.2.3. 消费者代码 2.2.4. 消费者yml配置 2.2.5. 生产者代码 2.2.6. 生产者yml配置 2.2.7. 运行效果 一、引言 …

MiGPT让你的小爱音响更聪明

大家好&#xff0c;我是晓凡。 今天要给大家带来一个超级有趣的开源项目MiGPT。 这个项目&#xff0c;简直就是给小爱音箱装上了超级大脑&#xff0c;让你的小爱音箱更聪明。 想象一下&#xff0c;当小爱音箱接入大模型后&#xff0c;上知天文&#xff0c;下知地理&#xff…

Cuda By Example - 7 (光线追踪)

第6章以实现简单的光线追踪为例子&#xff0c;引入了Constant Memory和性能测量方法。 Constant Memory NVIDIA的硬件提供了64K的constant只读内存。定义constant内存的变量&#xff0c;使用关键字__constant__。从constant内存里读取出来的数据&#xff0c;可以缓存起来&…

星河飞雪计划_day1

安全见闻 编程语句应用介绍 程序介绍 操作系统介绍 操作系统 ios mac Iinux android Windows wince vxworks RT-ThreadWindows、mac0S、i0S和Linux通常被认为是非实时操作系统。 非实时操作系统: 主要致力于在各种情况下提供良好的整体性能、用户体验和多任务处理能力&…

10.13论文阅读

通过联合学习检测和描述关键点增强可变形局部特征 摘要 局部特征提取是计算机视觉中处理图像匹配和检索等关键任务的常用方法。大多数方法的核心理念是图像经历仿射变换&#xff0c;忽略了诸如非刚性形变等更复杂的效果。此外&#xff0c;针对非刚性对应的新兴工作仍然依赖于…

UE4 材质学习笔记06(布料着色器/体积冰着色器)

一.布料着色器 要编写一个着色器首先是看一些参考图片&#xff0c;我们需要找出一些布料特有的特征&#xff0c;下面是一个棉织物&#xff0c;可以看到布料边缘的纤维可以捕捉光线使得边缘看起来更亮 下面是缎子和丝绸的图片&#xff0c;与棉织物有几乎相反的效果&#xff0c;…

docker harbor

文章目录 一&#xff0c;搭建私有仓库1.1下载registry1.2在 daemon.json 中添加私有镜像仓库地址1.3重新加载重启docker1.4运行容器1.5拉取一个centos7镜像1.6给镜像加标签1.7上传镜像1.8显示私有仓库的所有镜像1.8查看私有仓库的 centos 镜像有哪些tag 二&#xff0c;什么是ho…

Matlab中HybridFcn参数的用法

在 MATLAB 中&#xff0c;HybridFcn 参数允许你在全局优化&#xff08;如遗传算法 ga 或粒子群算法 particleswarm&#xff09;之后使用局部优化算法进一步微调解的精确度。HybridFcn 通过在全局优化找到的解基础上&#xff0c;进一步调用局部优化器&#xff0c;如 fmincon、pa…

ARM嵌入式学习--第四天

汇编与C混合编程 -汇编指令中调用C语言 .global _start _start:mov r0,#5mov r1,#3bl add stop:b stop int add(int a,int b) {int c a b;return c; } 无优化情况&#xff1a;&#xff08;反汇编之后&#xff0c;发现多了很多很多指令&#xff0c;运行之后结果是错误的&a…

掌握关键:全面数据分析键盘市场

键盘数据分析 一、市场分析 大盘销售额&#xff0c;销量&#xff1a; 共获取100个品牌每个品牌至多100页的数据&#xff0c;共计3***9个商品及其销量&#xff0c;销售额。 大盘数据 9月份键盘销售额&#xff1a;9***124.58元&#xff0c; 9月份键盘销量&#xff1a;1***0…

遇到“mfc100u.dll丢失”的系统错误要怎么处理?科学修复mfc100u.dll

遇到“mfc100u.dll丢失”的系统错误会非常麻烦&#xff0c;因为mfc100u.dll是Microsoft Visual C 2010 Redistributable Package的重要部分&#xff0c;许多应用程序和游戏在运行时都需要调用这个文件。如果这个文件缺失&#xff0c;可能会导致相关软件或游戏启动失败。面对这种…

操作系统实验三:基于BPF机制的系统跟踪与探测

实验内容 学习BPF机制&#xff0c;了解BCC&#xff08;BPF Compiler Collection&#xff09;和bpftarce的实现原理&#xff0c;利用BPF工具实现对系统的跟踪和探测&#xff0c;如跟踪新创建的进程&#xff0c;统计线程占用CPU的时间&#xff0c;统计某内核函数的调用次数&…

98. UE5 GAS RPG 实现技能眩晕效果

我们在技能伤害基类上面设置了对应的负面效果应用的配置项&#xff0c;用来实现技能的负面效果应用。 在之前实现火球术的负面效果时&#xff0c;我们我们在创建火球时&#xff0c;通过伤害基类上的创建技能配置用于后续应用。 在火球攻击到敌人时&#xff0c;通过函数库书写…

电脑技巧:优化Edge浏览器占用C盘空间的解决方案

大家在日常使用电脑的使用,Edge浏览器作为Windows电脑自带的浏览器,使用体验还是非常不错的。对于电脑新手来说直接使用微软自带的Edge浏览器也可以满足使用需求。但是随着电脑使用的越久,整体Edge浏览器也会占用几个G甚至更多的磁盘空间,并且还是C盘。 今天给大家分享如何…

使用Three.js和Force-Directed Graph实现3D知识图谱可视化

先看样式&#xff1a; 在当今信息爆炸的时代&#xff0c;如何有效地组织和展示复杂的知识结构成为一个重要的挑战。3D知识图谱可视化是一种直观、交互性强的方式来呈现知识之间的关系。本文将详细介绍如何使用HTML、JavaScript、Three.js和Force-Directed Graph库来实现一个交互…