Web前端高级工程师培训:使用 Node.js 构建一个 Web 服务端程序(3)

11、HTTP 协议

11-1、协议的定义

HTTP 是一种能够获取如 HTML 这样的网络资源的 protocol(通讯协议)。它是在 Web 上进行数据交换的基础,是一种 client-server 协议,也就是说,请求通常是由像浏览器这样的接受方发起的。一个完整的Web文档通常是由不同的子文档拼接而成的,像是文本、布局描述、图片、视频、脚本等等。(来源:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview)。

无论是客户端请求还是服务端响应,本质就是在交换数据。因为交换的数据的多样性,为了能够让双方正确的理解和处理交换的数据,就需要给这些数据定义一些交换的方式和格式,这就是 HTTP 协议的基本作用。

一些参考资料:

  • https://tools.ietf.org/html/rfc2616

11-2、报文

报文 可以理解为交换的数据,在 HTTP 协议中规定了交换的格式,报文分为:

  • 请求报文
  • 响应报文
请求报文

在这里插入图片描述

响应报文

在这里插入图片描述

HTTP Headers

HTTP Headers 允许客户端和服务端在请求和响应的时候携带一些附加信息,客户端会根据不同的头信息字段和对应内容做出不同的操作。根据不同的上下文环境,HTTP Headers 可分为:

  • General Headers : 普通头,同时适用于请求和响应消息,但与最终消息主体中传输的数据无关的消息头。
    • 参考:https://developer.mozilla.org/en-US/docs/Glossary/General_header
  • Request Headers : 请求头,包含更多有关要获取的资源或客户端本身信息的消息头。
    • 参考:https://developer.mozilla.org/en-US/docs/Glossary/Request_header
  • Response Headers : 包含有关响应的补充信息,如其位置或服务器本身(名称和版本等)的消息头。
    • 参考:https://developer.mozilla.org/en-US/docs/Glossary/Response_header
  • Entity Headers : 包含有关实体主体的更多信息,比如主体长(Content-Length)度或其MIME类型。
    • 参考:https://developer.mozilla.org/en-US/docs/Glossary/Entity_header

参考:https://tools.ietf.org/html/rfc4229#section-2.1.32

12、不同类型资源的处理

无论是请求还是响应,都会涉及到各种不同类型的资源要进行处理。为了能够让接收方(注:请求的接收方是服务端、响应的接收方是客户端)知道当前接收到内容类型,以便针对该类型进行对应的处理,所以需要在发送正文数据的同时需要同时告知该正文内容的类型格式。

12-1、使用 content-type 响应头返回资源类型

Content-Type 用于说明请求或相应中正文内容的 MIME 类型。

12-2、MIME 的作用与使用

MIME(Multipurpose Internet Mail Extensions) : 是一种用来表示 文档、文字或字节流的性质和格式的标准。

结构

MIME 的通用结构为 : type/subtypetype 为大类,subtype 为小类,如:text/htmltext/cssimage/png 等。

参考:https://www.iana.org/assignments/media-types/media-types.xhtml

12-3、设置响应头

使用 http 模块提供的 setHeader 方法就可以向响应中设置对应的头信息。

// #C12-3-1
...
server.on('request', (req, res) => {res.setHeader('Content-Type', 'text/html;charset="utf-8"');
});
...

13、动态资源

许多时候,服务端还可能会提供一些动态处理的资源,比如会根据当前时间,当前客户端访问用户的身份权限等条件进行一些逻辑处理后返回对应的资源,这个时候,针对同一个 URL 的请求可能会产生不一样的结果,这种资源我们可以成为:动态资源

13-1、使用 URL 路由表优化动态资源处理

因为动态资源的特性,资源并不能像静态资源一样简单的存储在一个外部文件中,然后使用一个 URL 与之关联。所以,针对这种资源,通常情况下,我们需要对不同的 URL 进行不同的处理。

  • 把不同的 URL 对应的一些逻辑分别保存(通常是函数)。
  • 准备一个路由表(可以使用对象格式进行存储,key是 URL,value是对应的函数)。
  • 根据当前访问的 URL ,找到路由表中的对应的函数并执行。
// #C13-1-1
...
// 路由表
const routesMap = new Map();
routesMap.set('/', async (req, res) => {res.setHeader('Content-Type', 'text/html;charset="utf-8"');res.end('首页');
});
routesMap.set('/list', async (req, res) => {res.setHeader('Content-Type', 'text/html;charset="utf-8"');res.end('列表');
});server.on('request', async (req, res) => {...const urlObj = new URL(req.url);...const pathname = urlObj.pathname;// 根据当前的 pathname 指定 routeMap 中对应的函数let routeHandler = routesMap.get(pathname);if (routeHandler) {await routeHandler(req, res);}
});
...

13-2、URL 重定向

我们通过一个 重定向 的需求应用场景来加深一下关于协议(如 http 头)等相关知识的理解

需求 : 访问不存在的 URL ,重新定向到 / 路由。

13-2-1、HTTP 状态码

我们通常在访问出现一些问题的时候返回一个友好的页面(或数据)给客户端,但是客户端仅仅从页面(数据)本身是无法知道这个页面(或数据)是这次请求本身应该对应的数据,还是我们给他的一个错误提示,这个时候就可以在响应的同时返回一个称为:状态码 的内容给客户端,它由一组具有特定含义的数字组成:

  • 信息响应(100199)
  • 成功响应(200299)
  • 重定向(300399)
  • 客户端错误(400499)
  • 服务器错误 (500599)

注:虽然服务端可以随意返回指定的状态码,但是我们应当按照实际的情况返回标准中定义好的状态码。

参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status

参考:https://tools.ietf.org/html/rfc2616#section-10

// #C13-2-1-1
...
// 路由表
...server.on('request', async (req, res) => {...const urlObj = new URL(req.url);...const pathname = urlObj.pathname;// 根据当前的 pathname 指定 routeMap 中对应的函数let routeHandler = routesMap.get(pathname);if (routeHandler) {await routeHandler(req, res);} else {// 告知客户端你应该重新发送请求,新的请求地址在 Location 头中。res.statusCode = 302;res.setHeader('Location', '/');res.end();}
});
...

13-3、404 Not Found

404 也是我们经常听到的一个词,它其实就是状态码中的一种

404 : 请求失败,请求所希望得到的资源未被在服务器上发现。

// #C13-3-1
...
// 路由表
...server.on('request', async (req, res) => {...const urlObj = new URL(req.url);...const pathname = urlObj.pathname;// 根据当前的 pathname 指定 routeMap 中对应的函数let routeHandler = routesMap.get(pathname);if (routeHandler) {await routeHandler(req, res);} else {// 返回一个404的状态码与提示页面res.statusCode = 404;res.end('<h1>页面丢失了</h1>');}
});
...

14、后端渲染

14-1、数据与视图

除了一些静态文件数据以外,服务端还会通过诸如:数据库程序运算 等各种方式产生数据,同时我们又需要把这些数据通过页面(HTML,CSS)的方式进行组织(也就是试图)返回给客户端。

// #C14-1-1
...let users = [{id: 1, username: '大海'},{id: 2, username: '子鼠'},{id: 3, username: '小蕊'},
];// 路由表
const routesMap = new Map();
routesMap.set('/', async (req, res) => {res.setHeader('Content-Type', 'text/html;charset="utf-8"');res.end(`<ul>${users.map(u => {return `<li>${u.username}</li>`}).join('')}</ul>`);
});
...server.on('request', async (req, res) => {...
});
...

14-2、数据与视图分离

如果视图内容直接写在后端程序中,后端程序不好维护,且前端不好配合。

我们可以把前端相关的内容提取到外部文件中,在利用 Node.jsfs 模块进行文件读取,并进行一些简单的替换。

// #C14-2-1
...
const fs = require('fs');// 数据
...// 路由表
const routesMap = new Map();
routesMap.set('/', async (req, res) => {res.setHeader('Content-Type', 'text/html;charset="utf-8"');let userListHtml = users.map(u => {return `<li>${u.username}</li>`}).join('');res.end( fs.readFileSync('./template/index.html').toString().replace(/${users}/gi, userListHtml) );
});
...server.on('request', async (req, res) => {...
});
...

./template/index.html

// #C14-2-2
...
<ul>${users}</ul>
...

模板 : 未被处理过的原始文件(如这里的:./template/index.html)。

视图 : 通过模板与数据和逻辑的处理生成的最终内容。

14-3、使用模板引擎优化渲染

以上的模板数据解析替换方式太简单,复杂一些的视图逻辑就不太方便了。这个时候我们就可以使用一些 模板引擎(功能更加强大的模板解析替换库) 来完成解析工作。

14-3-1、基于 JavaScript 的常用模板引擎
  • ejs
  • artTemplate
  • Nunjucks
14-3-2、Nunjucks

参考:http://mozilla.github.io/nunjucks/

15、案例:基于 Node.js 构建一个商城应用

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tailwind Starter Kit 一款极简的前端快速启动模板

Tailwind Starter Kit 是基于TailwindCSS实现的一款开源的、使用简单的极简模板扩展。会用Tailwincss就可以快速入手使用。Tailwind Starter Kit 是免费开源的。它不会在原始的TailwindCSS框架中更改或添加任何CSS。它具有多个HTML元素&#xff0c;并附带了ReactJS、Vue和Angul…

Docker安装Mysql5.7,解决无法访问DockerHub问题

Docker安装Mysql5.7&#xff0c;解决无法访问DockerHub问题 简介 Docker Hub 无法访问&#xff0c;应用安装失败&#xff0c;镜像拉取超时的解决方案。 摘要 &#xff1a; 当 Docker Hub 无法访问时&#xff0c;可以通过配置国内镜像加速来解决应用安装失败和镜像拉取超时的…

使用爬虫爬取Python中文开发者社区基础教程的数据

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

微信小程序文本收起展开

这里写自定义目录标题 微信小程序文本收起展开常见问题的梯形背景框 微信小程序文本收起展开 参考 https://juejin.cn/post/6963904955262435336 <!-- 常见问题解答 --><view classcontentBottom><view classBottomFirst><text id0 data-id0 class&quo…

python + mitmproxy 爬手机app (1)

起因&#xff0c; 目的: 想爬手机上某鱼。 mitmproxy 简介: 一句话: mitmproxy 就是中间人攻击. (只不过&#xff0c; 你安装&#xff0c;就代表你愿意承担风险。)源码&#xff1a;https://github.com/mitmproxy/mitmproxy文档: https://mitmproxy.org/ 安装过程: 见聊天记…

eCAP超声波测距-ePWM电机调速

目录 eCAP超声波测距 整体框架 关键模块 实验效果 PWM电机调速 DRV8833基本介绍 整体框架 eCAP超声波测距 本实验所用的超声波HC-SR04模块如下图所示&#xff0c;左边为正面图&#xff0c;右边为反面图。 HC-SR04基本工作原理&#xff1a; &#xff08;1&#xff09;采…

spring源码中的,函数式接口,注解@FunctionalInterface

调用方 /org/springframework/beans/factory/support/AbstractBeanFactory.java:333sharedInstance getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It mi…

Kafka之消费者客户端

1、历史上的二个版本 与生产者客户端一样&#xff0c;在Kafka的发展过程当中&#xff0c;消费者客户端主要有两个大的版本&#xff1a; 旧消费者客户端&#xff08;Old Consumer&#xff09;&#xff1a;基于Scala语言开发的版本&#xff0c;又称为Scala消费者客户端。新消费…

rpm 命令

rpm&#xff08;Red Hat Package Manager&#xff09;是 Red Hat Linux 及其衍生发行版&#xff08;如 CentOS、Fedora&#xff09;中用于管理软件包的系统。它允许用户安装、卸载、升级、查询和验证软件包。 一、安装软件包 &#xff08;1&#xff09;安装一个 RPM 软件包&a…

高并发下如何保证接口的幂等性?

前言 接口幂等性问题,对于开发人员来说,是一个跟语言无关的公共问题。本文分享了一些解决这类问题非常实用的办法,绝大部分内容我在项目中实践过的,给有需要的小伙伴一个参考。 不知道你有没有遇到过这些场景: 有时我们在填写某些form表单时,保存按钮不小心快速点了两次…

十二、【智能体】深入剖析:大模型节点的全面解读,举例说明,教你如何在扣子中嵌入代码

大模型节点 大模型节点主要分为5部分&#xff1a; 处理类型 单次批处理 模型类型&#xff1a;目前可以选择的模型有 豆包、通义千问、智谱、MinMax和Kimi输入:此时的参数可以被下面的提示词所用提示词&#xff1a;给大模型使用的提示词输出&#xff1a;经过此大模型处理后的输…

Vehicle Spy3.9如何新建工程—总览

1&#xff1a;写作目的 学习和精通SPY的使用&#xff0c;对于spy&#xff0c;目前主要是通用系用的比较多&#xff0c;本身spy的生产厂家英特佩斯也是美国的公司&#xff0c;除了软件自带教程。中文网上很少能找到相关的中文教程。 故写下这篇文章&#xff0c;帮助自己和大家…

Ubuntu(22.04)本地部署Appsmith

Ubuntu&#xff08;22.04&#xff09;安装Appsmith 简要介绍 Appsmith 是一个开源的低代码开发平台&#xff0c;旨在帮助开发者和非开发者快速构建定制化的内部应用程序和管理工具。通过直观的拖拽界面和丰富的预配置组件&#xff0c;Appsmith 让用户无需编写大量代码即可创建…

软件工程的学习之详细绪论

软件的定义 软件是程序和所有使程序正确运行所需要的相关文档和配置信息。 Software Program Data Document 一、软件危机&#xff1a; 软件开发和维护过程中遇到的一系列严重问题。 二、具体表现&#xff1a; 1、产品不符合用户的实际需要&#xff1b; 2、软件开发生产率…

Sigrity 共模电感的S-parameter仿真数据导入

下载S4P参数 https://ds.murata.co.jp/simsurfing/cmcc.html?partnumbers%5B%22DLW32MH101XT2%22%5D&oripartnumbers%5B%22DLW32MH101XT2L%22%5D&rgearjomoqke&rgearinfocom&md51729525489334# 下载S4P参数&#xff1b; DLW32MH101XT2.s4p Sigrity 使用-dif…

Mac电脑:资源库Library里找不到WebServer问题的解决

今天看到一本书里写到Windows电脑自带IIS Web服务器&#xff0c;好奇了一下下&#xff0c;mac电脑自带的又是什么服务器呢&#xff1f;经查询&#xff0c;原来是Apache服务器&#xff0c;这个名字我很熟悉。只是如何设置呢&#xff1f;我从来没用过&#xff0c;于是试验了一番。…

如何看待AI技术的应用前景?

人工智能&#xff1a;引领未来的变革力量 在当今快速变化的科技时代&#xff0c;人工智能&#xff08;AI&#xff09;作为一项前沿技术&#xff0c;已然成为推动全球各行各业变革的核心驱动力。随着人工智能技术的不断发展&#xff0c;其广泛的应用前景和深远的影响力&#xf…

Lua环境安装

软考鸭微信小程序 学软考,来软考鸭! 提供软考免费软考讲解视频、题库、软考试题、软考模考、软考查分、软考咨询等服务 Lua是一种轻量级、小巧且易于嵌入应用程序的脚本语言&#xff0c;广泛用于游戏开发、Web开发、自动化脚本等领域。本文将详细介绍如何在不同操作系统上安装L…

深度学习 基本函数01

np.dot 是 NumPy 库中的一个函数&#xff0c;用于计算两个数组的点积&#xff08;也称为内积或数量积&#xff09;。点积是两个向量的对应元素乘积之和。 np.random.normal 是 NumPy 库中的一个函数&#xff0c;用于生成符合正态分布&#xff08;也称为高斯分布&#xff09;的…