Node.js http 模块详解:request 对象

news2024/11/26 4:40:44

前言

前文介绍了 http 模块的基本用法,主要就是调用 createServerlisten 方法来创建和启动服务。要处理具体的 HTTP 请求,就要在 createServer 方法中写点什么。本文来介绍处理请求的两个核心对象之一的 request

URL

HTTP 协议最早设计出来,仅仅为了获取网络上的某个 HTML 文档。随着后来的发展,网络上的资源越来越丰富,种类也从单一的文本发展到图片,音频,视频等多媒体类型。但是无论是何种资源,它都有在整个互联网世界中的唯一标识,这就是 URL —统一资源定位符(Uniform Resource Locator)

下面是 URL 的组成:

img

  1. scheme :就是我们常说的“协议”,在《HTTP 权威指南》中翻译为“方案”。常用的协议有 HTTP,FTP,SMTP 等等。
  2. user:password@:表示访问此资源的用户和密码。对于公开的网络资源并不需要验证。即使需要也不会这么用,很不安全。通常直接省略。
  3. host:port:表示资源所在的主机名和端口号。HTTP 协议的默认端口号是 80,HTTPS 协议的默认端口号是 443,都还可以省略。
  4. path:路径,表示资源在主机中的位置。
  5. query:查询,表示对资源附加的额外要求。
  6. #fragment:片段标识符,表示资源内部的一个锚点,浏览器可以跳转到它指示的位置。但是此部分不会发送到服务器。

request 对象

HTTP 协议是基于请求-响应模型的协议,在 HTTP2 以前,必须是客户端发起请求,服务器接收请求,再将处理的结果响应给客户端。

客户端在向服务器发送 HTTP 请求时,需要指定一个具体的 URL 和 HTTP 方法,告诉服务器我想要写什么,还是提交些什么。通常还会携带一些信息,这些信息可以放在 URL 中,或者放在 HTTP Header(首部)中,如果是向服务器提交数据,还可以放在 HTTP 报文实体中。

那么服务器就要想办法接收这些东西,http 模块中的 request 对象中就包含了这些东西,可以根据自己的需要有选择的解析出来使用。

解析 Method

HTTP 方法常用的有 GetHeadPostPutDelete 等等,可以直接使用 request.method 来获取。

const server = http.createServer((request, response) => {
	const method = request.method;
	console.log(method)
	response.end('Hello, World');
});

浏览器刷新一下页面,服务端打印:

image-20230201174119998

解析 URL

URL 构成比较复杂,通过 request.url 只能获取完整的 URL。比如浏览器访问 http://localhost:3000/list?page=10

const server = http.createServer((request, response) => {
    console.log(request.method)
	console.log(request.url)

	response.end('Hello, World');
});

控制台打印:

image-20230201174354196

若要获得某个部分,比如路径 path,查询参数 query,可以借助内置的 url 模块:

const http = require('http');
const url = require('url');

const server = http.createServer((request, response) => {
	
	const urlObj = url.parse(request.url)
	console.log(urlObj)

	response.end('Hello, World');
});

parse 方法,将原始的 URL 解析为一个对象:

image-20230201174634299

解析 Query

通过上面的方式,可以得到当前请求的资源的路径和查询参数。但是查询参数依然是一个字符串,不方便使用。

可以使用内置的 querystring 模块去解析,或者使用 URLSearchParams API 去解析,或者使用第三方的 qsquerystringify 等模块去解析。以内置模块 querystring 为例:

const http = require('http');
const url = require('url');
const qs = require('querystring');

const server = http.createServer((request, response) => {
	let { query } = url.parse(request.url)

	query = qs.parse(query)
	console.log(query)

	response.end('Hello, World');
});

就可以轻松得到一个 query 对象,方便读取查询参数了:

image-20230201181836136

解析 Header

HTTP 请求的首部信息都放在了 request.headers 对象中。

const server = http.createServer((request, response) => {

	console.log(request.headers);

	response.end('Hello, World');
});

浏览器发一次请求,服务端会打印:

image-20230201183255363

如图,像是 sec-ch-uasec-ch-ua-mobile 这种以 sec- 为前缀的请求头,表示的是禁止使用代码修改的 HTTP 消息头,用户代理保留全部对它们的控制权。比如我们熟悉的 User-Agent,通常后端会根据它来判断用户的系统和平台,但是它很容易就被修改进行伪装,因此是不安全的。通过 sec-ch-ua 就能安全的将用户代理信息传给服务器。

除了这些安全的Header,剩下的我们都非常熟悉了:

  • host:此次请求到主机名。用于虚拟主机设置。

  • connection:控制网络连接的断开。HTTP/1.1 默认为 keep-alive,表示长连接

  • cache-control:设置强缓存。

  • accept:客户端可接收的内容的类型。

  • accept-encoding:客户端可用的内容编码方式——通常是某种压缩算法。

若要获取具体某个 Header 的信息,可以使用方括号语法:

const server = http.createServer((request, response) => {

	console.log(request.headers['content-type']);

	response.end('Hello, World');
});

解析请求体

HTTP 报文分为请求报文响应报文。报文由这三部分构成:

  • 起始行:分为请求行,状态行。
  • 首部:描述请求相关的信息,也会描述实体数据的信息。
  • 实体:携带的数据。

image-20230201190828182

有的请求,比如文件上传,表单提交,要携带一些数据,这些数据就是放在报文的实体中传输的

HTTP 请求只管发送数据,而不管数据是何类型。所以会在请求头中通过 Content-Type 来告知服务器,此次请求所携带的数据是什么格式的。request 对象将接收到的实体中的数据,都放在 requst.body 中。根据这两点,就可以解析出客户端所传的数据。

另外,request 对象是一个可读流,通过监听 data 事件,就能读取出来实体中所传输的数据。当监听到 end 事件,表示实体中数据读取完毕,就可以进行解析了。

const http = require('http');
const url = require('url');

const server = http.createServer((request, response) => {
	const method = request.method;
	const { pathname } = url.parse(request.url);

    // 处理 Post /user/login
    if(method === 'POST' && pathname === '/user/login') {

        let arr = [];
        const contentType = request.headers['content-type']
        if (contentType === 'application/json') {
            // 监听 data 事件,读取实体数据
            request.on('data', (data) => {
                console.log(data)
                arr.push(data)
            })

            // 监听 end 事件,处理数据
            request.on('end', () => {
                console.log('传输完毕')
                let json = JSON.parse(Buffer.concat(arr).toString())
                console.log(json)
            })
            // 结束响应
            response.end('Hello, World');
        }
    }
});

server.listen(3000, () => {
	console.log('服务器启动成功:http://localhost:3000')
})

以一个用户登录的表单提交为例,通常会使用 json 格式传递数据。打开 Postman 或者 ApiPost 来发送请求:

image-20230201210544034

服务端程序打印结果如下:

image-20230201210748466

总结

本文介绍了通过 request 对象几个常用到的属性来处理 HTTP 请求:

  • request.method:获取请求方法
  • request.url:获取请求 URL,还需要再借助 urlquerystring 等工具进一步解析
  • request.headers:获取请求头信息
  • request.body:获取请求体数据,需要根据 Content-Type 解析为不同的格式

下篇文章会介绍 reponse 对象,来完成完成的一次请求处理。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

车载TBOX嵌入式设备软件的性能测试

作者 | 李伟 上海控安安全测评中心安全测评部总监 来源 | 鉴源实验室 01 ECU软件和通用软件性能测试的区别 通用软件进行性能测试时通常会通过压力测试、负载测试、稳定性测试、疲劳强度测试、用户并发访问测试等等方法来了解当前软件系统的各项性能指标数据,并在…

【mybatis】实现分页查询

一 .使用原生分页器的实体类 1.1 java代码部分 方法多 不易书写 package cn.bdqn.entity;public class Page {private Integer pageIndex;//页码private Integer pageSize;//页大小 显示多少行数据private Integer totalCounts;//数据的总行数private Integer totalPages;//…

docker安装部署dragonfly2镜像加速服务

Dragonfly安装部署文档 ​ Dragonfly 作为龙蜥社区的镜像加速标准解决方案,是一款基于 P2P 的智能镜像和文件分发工具。它旨在提高大规模文件传输的效率和速率,最大限度地利用网络带宽。在应用分发、缓存分发、日志分发和镜像分发等领域被大规模使用。 …

鸟哥的Linux私房菜读书笔记:Linux磁盘与文件系统管理

系统管理员很重要的任务之一就是管理好自己的磁盘文件系统, 每个分区不可太大也不能太小, 太大会造成磁盘容量的浪费, 太小则会产生文件无法储存的困扰。 前面谈到的文件权限与属性中, 这些权限与属性分别记录在文件系统的哪个区块…

[Golang实战]如何快速接入chatgpt/openai?[引入go-gpt3][新手开箱可用]

如何快速接入chatgpt?[引入go-gpt3]上文介绍了如何在网页使用chatgpt?V1.介绍下在golang中使用chatgpt?1.查看官网推荐的chatgpt项目2.访问go-gpt33.使用并运行在自己的项目中...(是因为例子很难理解,所以一一对应了属性做了配置)3.1安装项目3.2换上自己的代码3.3换上自己的…

LeetCode - 1109 - 航班预定统计

目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 1109. 航班预订统计 - 力扣(LeetCode) 题目描述 这里有 n 个航班,它们分别从 1 到 n 进行编号。 有一份航班预订表 bookings ,表中第 i 条预订记录 bookin…

【C语言】BCD码、十进制互相转换

目录 0. 前言: 1. BCD码 2. 算法原理 3. 进制转换 3.1 两位BCD码的转换: 3.2 其他进制转换 3.3 任意进制转二进制 参考资料: 0. 前言: 记录今天用15单片机写DS1302时钟芯片程序的时候遇到的问题 时间显示是这个样的 0 1…

电源浪涌保护器的演化发展与未来创新方向

随着科学信息技术和城市经济的发展,感应雷、电磁脉冲和雷电波浸入所造成的危害大大增加。一般建筑物的外部防雷措施只能预防直击雷,而强大的电磁场产生的感应雷和脉冲电压却能潜入室内危及电路上的设备。如今通讯网络、电脑仪器和各类用电设备越来越精密…

2023VR视频加密解决方案

如今VR技术在各个领域中的使用,使得我们在日常生活中也可以看到它的身影,常见的就是应用到培训、影院和游戏当中,我们都知道VR视频比传统的平面视频能给用户带来更好的体验,而且现在在教育、娱乐等领域VR类视频也越来越多。相比于…

运动基元(二):贝塞尔曲线

贝塞尔曲线是我第一个深入接触并使用于路径规划的运动基元。N阶贝塞尔曲线具有很多优良的特性,例如端点性、N阶可导性、对称性、曲率连续性、凸包性、几何不变性、仿射不变性以及变差缩减性。本章主要介绍贝塞尔曲线用于运动基元时几个特别有用的特性。 一、贝塞尔曲线的定义 …

C++复习笔记4

编译器给一个类默认生成的六个成员函数: 构造函数、析构函数、拷贝构造函数、赋值运算符重载、对象取地址运算符以及常对象取地址运算符。其中析构函数不能重载,默认的拷贝和赋值两个函数存在浅拷贝的问题。 对象取地址运算符重载和常对象取地址运算符…

KD03丨选品种-横截面动量

大家好,今天我们分享可达鸭系列第3篇策略——横截面动量。 想必这种逻辑大家也都熟悉,为了照顾大部分新人朋友,开始还是简单介绍一下该该逻辑理论。 横截面是一种非时序动量逻辑,从统计学感性描述(非严谨客观描述&am…

windows安装PaddleSpeech(无需visual studio)

前言 首先啊,狠狠的批评一下paddle,不想看请直接跳到用法,另外我python版本是3.9,所以包找的也都是3.9。 1.分成许多子项目涵盖AI的不同领域,初心是好,安装起来得安装多个环境。 2.官方文档推荐linux安装&…

anaconda详细介绍、安装及使用(python)

anaconda详细介绍、安装及使用1 介绍1.1 简介1.2 特点1.3 版本下载2 Anaconda管理Python包命令3 安装3.1 windows安装4 操作4.1 Conda 操作4.2 Anaconda Navigator 操作4.3 Spyder 操作4.4 Jupyter Notebook 操作5 示例参考1 介绍 1.1 简介 Anaconda是用于科学计算&#xff08…

力扣sql简单篇练习(十四)

力扣sql简单篇练习(十四) 1 银行账户概要|| 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # 高于相当于大于的意思 SELECT u.name,t.balance FROM Users u INNER JOIN (SELECT account,sum(amount) balanceFROM TransactionsGROUP BY accountHAVIN…

Kafka入门(四)

下面尝试一下Kafka 的生产者客户端和消费者客户端的实现。 1、客户端简介 生产者就是负责向Kafka发送消息的应用程序,消费者就是拉取Kafka消息的应用程序。 在Kafka的历史版本中,主要的客户端如下: 基于Scala语言编写的客户端,称…

JAVA工具篇--3 maven项目转gradle项目

前言:将已有的Maven 项目转换为Gradle 项目; 1 项目转换: 1.1 winr 打开cmd命令窗口, 然后进入到maven项目根目录后,输入命令: gradle init --info --type pom1.2 选择构建的语言: 输入 1 然后回车; 1.3…

Rust编码的信息窃取恶意软件源代码公布,专家警告已被利用

黑客论坛上发布了一个 用Rust编码的信息窃取恶意软件源代码 ,安全分析师警告,该恶意软件已被积极用于攻击。 该恶意软件的开发者称,仅用6个小时就开发完成,相当隐蔽, VirusTotal的检测率约为22% 。 恶意软件开发者在…

canal使用说明:MySQL、Redis实时数据同步

1. canal简介 canal是阿里开源的数据同步工具,基于bin log可以将数据库同步到其他各类数据库中,目标数据库支持mysql,postgresql,oracle,redis,MQ,ES等 canal分成服务端deployer和客户端adapter,我们可以部署多个,同时为了方便管…

AssertionError: 618 columns passed, passed data had 508 columns【已解决】

问题描述 程序中断,报错如下AssertionError: 618 columns passed, passed data had 508 columns Exception has occurred: ValueError 618 columns passed, passed data had 508 columns AssertionError: 618 columns passed, passed data had 508 columnsThe abo…