node.js 解析post请求 方法一

news2024/11/16 7:35:45

前提:依旧以前面发的node.js服务器动态资源处理代码 具体见 http://t.csdnimg.cn/TSNW9为模板,在这基础上进行修改。与动态资源处理代码不同的是,这次的用户信息我们借用表单来实现。post请求解析来获取和展示用户表单填写信息

1》代码难点:

解析post请求方法一的重点在于——注册和登录表单在处理查询参数(query)时使用了不同的方法。这是因为这两种表单的处理方式在HTTP请求的结构上有所不同。注册表单使用的是post请求,登录表单使用的是get请求。

在POST请求中,数据位于请求体中,而在GET请求中,数据位于URL的查询字符串中。

2》具体要求:

完成注册、登录、已注册的用户表单展示功能(也就是表单填写的用户名、密码、性别这三个信息。此处文件上传功能方法一不能实现,如要实现文件上传请见方法二)

一、解析post请求方法一介绍

因为Node.js 没有提供直接解析POST请求提交的数据的模块;

 所以一般是通过request的data和end事件获取请求报文中请求正文的内容后再解析。

二、资源配置

(1)页面配置

我们将首页index.html、登录login.html、注册regist.html、用户表单注册信息users.html、错误提示模板页面404.html这五个html页面写在views这个大文件夹下。样式mian.css和图片和表单提交的图片分别放入public这个大文件夹下的css、images、head文件下。最后创建一个data大文件夹,data下面建一个user.json文件来专门存储用户数据。解析post请求方法一的服务器代码我写入serve.js下。后继写的解析post请求方法二的服务器代码我将写在serve2.js下。

用户列表渲染功能index.html就是可以将我的user.json里面注册成功的用户表单数据渲染到我的服务器用户列表页面

index.html页面、login.html页面、404.html页面与我动态资源处理代码里写的一致,此处略写。 见 http://t.csdnimg.cn/TSNW9 

regist.html页面:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>注册</title>
  <link rel="stylesheet" href="../public/css/main.css">
</head>
<body>
  <h1>注册</h1>
  <img src="../public/images/01.png" alt=""><br>
  <form method="post" action="/doRegist"> 
    <input type="text" name="username" placeholder="用户名"><br>
    <input type="password" name="password" placeholder="密码"><br>
    <input type="radio" name="gender" value="男" checked>男
    <input type="radio" name="gender" value="女">女<br>
    <input type="file" name="head" multiple><br>  
    <!-- multiple允许选择多个文件 -->
    <input type="submit" value="注册"><br> 
  </form>
</body>
</html>
users.html页面:
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>用户列表</title>
  <link rel="stylesheet" href="../public/css/main.css">
</head>

<body>
  <h1>用户列表</h1>
  <img src="../public/images/01.png" alt=""><br>
  <table>
    <thead>
      <tr>
        <td>用户名</td>
        <td>密码</td>
        <td>性别</td>
        <td>头像</td>
      </tr>
    </thead>
    <tbody>
      <!-- 遍历json里的数组 -->
      <% for(var user of users){ %>
      <tr>
        <td><%= user.username %></td>
        <td><%= user.password %></td>
        <td><%= user.gender %></td>
        <td><img src="../public/head/<%= user.head %>" width="50"></td>
      </tr>
      <% } %>
    </tbody>
  </table>
</body>

</html>
users.json页面:
[

]

(2)在我的测试代码的终端 npm install underscore -save安装underscore渲染模板引擎 、npm install querystring安装querystring查询模块

三、代码实现

(1) 测试代码serve.js如下:

//serve.js 解析post请求 法一
// 通过request的data和end事件获取请求报文中请求正文的内容后再解析
const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');
// 导入查询参数的模块
const querystring = require('querystring');
// 声明一个专门存放所有用户的变量
var users;
// 导入underscore渲染模板
const _ = require('underscore');
//使用underscore渲染模板
function render(data){
  //读取模板内容
  let temp=fs.readFileSync(path.join(__dirname,'views/404.html'));
  // 获取渲染函数
  let compiled=_.template(temp.toString());
  //渲染模板
  return compiled(data);
}
//读取文件。读取users.json存放的用户数据文件
fs.readFile(path.join(__dirname,'data/users.json'),(err,data)=>{
  if(err){
     return;
  }else{
     //如果读取正确就将读到的内容转换为一个对象存到users里
     users=JSON.parse(data.toString());
  }
})
//创建服务器
const server=http.createSever();
//服务器做出请求响应
server.on('request',(req,res)=>{
  //将url转为一个对象才能获取到它的pathname
  let objurl=url.parse(req.url);
  let pathname = objurl.pathname;
       // 对pathname做处理
       // 首先解决静态资源处理  (判断方法:startWith、indexOf、search、includes)
       // startsWith方法  以什么开头
  if (pathname.startsWith('/public')) {
        // 找到当前项目文件夹,再将相对路径转为绝对路径
        let p = path.join(__dirname, pathname);
        fs.readFile(p, (err, data) => {
            if (err) {
                //可以使用中文,因为现在是html页面去显示的
                res.end(render({ msg: '访问的文件不存在' })); 
            } else {
                res.end(data);
            }
        })
    }else if(pathname == '/' || pathname == '/home'){
        let p = path.join(__dirname, 'views/index.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' }));
            } else {
                res.end(data);
            }
        })
    }else if(pathname == '/regist'){
        let p = path.join(__dirname, 'views/regist.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' }));
            } else {
                res.end(data);
            }
        })
    }else if(pathname == '/login'){
        let p = path.join(__dirname, 'views/login.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' }));
            } else {
                res.end(data);
            }
        })

    }else if(pathname == '/doLogin'){ //登录表单
        let query = querystring.parse(objurl.query); //登录表单通常使用GET请求。处理get请求方法一借助querystring模块。querystring.parse(req.url.query) 将字符串参数解析成对象
        let username = query.username;
        let password = query.password;
        // 声明一个变量result代表我的判断结果
        let result = false;
        for (let user of users) {
            if (user.username == username && user.password == password) {
                result = true;
                break;
            }
        }
        if (result) {
            res.end(render({ msg: '登录成功' }));
        } else {
            res.end(render({ msg: '用户名或密码错误,登录失败' }));
        }
    }else if(pathname == '/doRegist' && req.method.toLowerCase() == 'post'){ //注册表单 此处为post请求解析过程。最重要。注意
        let chunk = '';  //chunk是一个字符串对象,是为了收集或缓存从请求中传入的数据
        req.on('data', (data) => { //事件监听器,它监听req上的data事件。当HTTP请求体中有数据可读时,这个事件就会被触发
            chunk += data; //当data事件被触发时,它会执行这个函数。函数内部,它将传入的数据data追加到churk字符串上。这意味着,随着数据逐渐流入,churk将积累所有的数据。
        });
        req.on('end', () => {
            // 上面读取完毕开始注册操作
            let query=querystring.parse(chunk); // //使用POST请求时,请求体(req.body)包含要发送到服务器的数据,而不是URL的查询字符串(req.url). 因此,我们需要监听data和end事件来收集从请求体中传入的数据。在data事件中,我将传入的数据片段添加到chunk变量中,然后在end事件中,解析这个chunk(通常是一个Buffer或字符串),以获取查询参数
            let username=query.username;
            let password=query.password;
            let gender=query.gender;
            let user={
                username:username,
                password:password,
                gender:gender,
                head:''
            }
            users.push(user);
            fs.writeFile(path.join(__dirname,'data/users.json'),JSON.stringify(users),(err)=>{
                if(err){
                    res.end(render({msg:'注册失败'}));
                }else{
                    // 注册成功
                    // 重定向(服务器端主动发起一个请求)到登录页面
                    res.writeHead(302,{'Location':'/login'});
                    res.end();
                }
            })

        });
    }else if(pathname == '/list'){
let p = path.join(__dirname, 'views/users.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' }));
            } else {
                //获得渲染函数 
                let compiled = _.template(data.toString());
                // 调用渲染函数来生成html内容
                let html = compiled({ users: users }); //我们在模板里取的是users的属性, 
                所以不能简写成users,而是users:users
                res.end(html);

            }
        })
    }
});

//启动监听
server.listen(3000, '127.0.0.1', () => {
    console.log('Server is running at http://127.0.0.1:3000');
})

***重难点:

(4)注意:解析post请求方法一的重点在于——注册和登录表单在处理查询参数(query)时使用了不同的方法。这是因为这两种表单的处理方式在HTTP请求的结构上有所不同。

  1. 注册表单(POST请求)

    • 当您提交注册表单时,通常使用POST请求,因为它涉及到向服务器发送数据(在这种情况下是注册信息)。
    • 当您使用POST请求时,请求体(req.body)包含要发送到服务器的数据,而不是URL的查询字符串(req.url)。
    • 因此,您需要监听dataend事件来收集从请求体中传入的数据。在data事件中,您将传入的数据片段添加到chunk变量中,然后在end事件中,您解析这个chunk(通常是一个Buffer或字符串),以获取查询参数。
  2. 登录表单(GET请求)

    • 登录表单通常使用GET请求,因为它不涉及向服务器发送大量数据。相反,它可能只是请求用户信息(如用户名和密码)来验证用户身份。
    • GET请求中,请求参数被附加到URL的末尾,并作为查询字符串出现。
    • 由于查询字符串是URL的一部分,您可以直接从req.url中获取它,并使用querystring.parse()来解析它。您使用的url.parse(req.url)方法会返回一个对象,其中包含URL的不同部分,包括查询字符串,然后您可以使用querystring.parse()来解析查询字符串。

总之,注册和登录表单在处理查询参数时使用不同的方法,因为它们使用了不同类型的HTTP请求(POSTGET),并且数据在请求中的位置不同。

POST请求中,数据位于请求体中,而在GET请求中,数据位于URL的查询字符串中。

(2)运行结果如图所示

 

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

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

相关文章

全彩屏负氧离子监测站的使用

TH-FZ5在繁忙的都市生活中&#xff0c;我们往往忽视了一个至关重要的问题——空气质量。随着工业化的进程加速&#xff0c;空气污染已成为影响人们健康的一大隐患。为了实时监测和了解身边的空气质量&#xff0c;全彩屏负氧离子监测站应运而生&#xff0c;成为了我们守护呼吸健…

企业集成平台建设方案(技术方案+功能设计)

企业集成平台建设方案及重点难点攻坚 基础支撑平台主要承担系统总体架构与各个应用子系统的交互&#xff0c;第三方系统与总体架构的交互。需要满足内部业务在该平台的基础上&#xff0c;实现平台对于子系统的可扩展性。基于以上分析对基础支撑平台&#xff0c;提出了以下要求&…

稀碎从零算法笔记Day59-LeetCode: 感染二叉树需要的总时间

题型&#xff1a;树、图、BFS、DFS 链接&#xff1a;2385. 感染二叉树需要的总时间 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给你一棵二叉树的根节点 root &#xff0c;二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟…

25计算机考研院校数据分析 | 北京航空航天大学

北京航空航天大学(Beihang University)&#xff0c;简称北航&#xff0c;由中华人民共和国工业和信息化部直属&#xff0c;中央直管副部级建制&#xff0c;位列“双一流”、"211工程”、"985工程”&#xff0c;入选“珠峰计划”、"2011计划”、“111计划”、&qu…

STM32标准库ADC和DMA知识点总结

目录 前言 一、ADC模数转换器 &#xff08;1&#xff09;AD单通道 &#xff08;2&#xff09;AD多通道 二、DMA原理和应用 &#xff08;1&#xff09;DMA数据转运&#xff08;内存到内存&#xff09; &#xff08;2&#xff09;DMAAD多同道&#xff08;外设到内存&#x…

debian和ubuntu的核心系统和系统命令的区别

Debian和Ubuntu虽然有很深的渊源&#xff0c;都是基于Debian的发行版&#xff0c;但它们在核心系统和系统命令上还是有一些差别的。以下是一些主要的不同之处&#xff1a; 1. 发布周期&#xff1a; - Debian&#xff1a; Debian项目采用滚动发布模型&#xff0c;持续更新&a…

SpringCloud Alibaba--nacos配置中心

目录 一.基础介绍 1.1概念 1.2 功能 二.实现 2.1 依赖 2.2 新建配置文件 2.3 克隆 2.4 配置bootstap.yml文件 三.测试 一.基础介绍 1.1概念 在微服务架构中&#xff0c;配置中心就是统一管理各个微服务配置文件的服务。把传统的单体jar包拆分成多个微服务后&#xf…

到底什么是认证

认证和授权 什么是认证 认证 (Authentication) 是根据凭据验明访问者身份的流程。即验证“你是你所说的那个人”的过程。 身份认证&#xff0c;通常通过用户名/邮箱/手机号以及密码匹配来完成&#xff0c;也可以通过手机/邮箱验证码或者生物特征&#xff08;如&#xff1a;指纹…

LangChain的核心模块和实战

主要模型 LLM:对话模型, 输入和输出都是文本Chat Model: 输入输出都是数据结构 模型IO设计 Format: 将提示词模版格式化Predict: langchain就是通过predict的方式调用不同的模型, 两个模型的区别不大, Chat Model 是以LLM为基础的.Parese: langchain还可以对结果进行干预, 得…

css盒子设置圆角边框的方法

前言 欢迎来到我的博客 个人主页&#xff1a;北岭敲键盘的荒漠猫-CSDN博客 本文为我整理的设置圆角边框的方法 需求描述 我们在设置盒子边框时&#xff0c;他总是方方正正的。 我们想让这个直直的边框委婉一点该怎么办呢。这个就提到了我们这篇文章讲的东西&#xff1a; bord…

二分查找知识点及练习题

知识点讲解 一、没有相同元素查找 请在一个有序递增数组中&#xff08;不存在相同元素&#xff09;&#xff0c;采用二分查找&#xff0c;找出值x的位置&#xff0c;如果x在数组中不存在&#xff0c;请输出-1&#xff01; 输入格式 第一行&#xff0c;一个整数n&#xff0c;代…

DevOps(十二)Jenkins实战之Web发布到远程服务器

前面两篇博文介绍了怎么将django开发的web应用推送到gitlab源码仓库&#xff0c;然后jenkins服务器从gitlab仓库拉下来&#xff0c;布署到jenkins服务器上&#xff0c;并用supervisor进行进程管理&#xff0c;保证web应用一直能正常运行&#xff0c;今天我们继续优化&#xff0…

政安晨:【深度学习神经网络基础】(十三)—— 卷积神经网络

目录 概述 LeNet-5 卷积层 最大池层 稠密层 针对MNIST数据集的卷积神经网络 总之 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎…

绿色便携方式安装apache+mysql+tomcat+php集成环境并提供控制面板

绿色便携方式安装带控制面板的ApacheMariaDBTomcatPHP集成环境 目录 绿色便携方式安装带控制面板的ApacheMariaDBTomcatPHP集成环境[TOC](目录) 前言一、XAMPP二、安装和使用1.安装2.使用 三、可能的错误1、检查端口占用2、修改端口 前言 安装集成环境往往配置复杂&#xff0c…

Gradio 最快创建Web 界面部署到服务器并演示机器学习模型,本文提供教学案例以及部署方法,避免使用繁琐的django

最近学习hugging face里面的物体检测模型&#xff0c;发现一个方便快捷的工具&#xff01; Gradio 是通过友好的 Web 界面演示机器学习模型的最快方式&#xff0c;以便任何人都可以在任何地方使用它&#xff01; 一、核心优势&#xff1a; 使用这个开发这种演示机器学习模型的…

leetcode-比较版本号-88

题目要求 思路 1.因为字符串比较大小不方便&#xff0c;并且因为需要去掉前导的0&#xff0c;这个0我们并不知道有几个&#xff0c;将字符串转换为数字刚好能避免。 2.当判断到符号位的时候加加&#xff0c;跳过符号位。 3.判断数字大小&#xff0c;来决定版本号大小 4.核心代…

LabVIEW和MES系统的智能化车间数据对接

LabVIEW和MES系统的智能化车间数据对接 随着工业4.0时代的到来&#xff0c;智能制造成为推动制造业高质量发展的重要手段。其中&#xff0c;数字化车间作为智能制造的重要组成部分&#xff0c;其设计与实现至关重要。在数字化车间环境下&#xff0c;如何利用LabVIEW软件与MES系…

2024 年 Rust 开发者路线图

Rust 近年来因其对性能、安全性和并发性的关注而广受欢迎。作为一名开发人员&#xff0c;掌握 Rust 可以为各种机会打开大门&#xff0c;包括 Web 开发。 在 github 上发现了这个优秀的路线图&#xff0c;由 Anshul Goyal 创建&#xff0c;它提供了一条全面的路径&#xff0c;概…

第十五届蓝桥杯省赛第二场C/C++B组A题【进制】题解

解题思路 按照题意进行模拟&#xff0c;计算 x x x 的 b b b 进制过程中&#xff0c;若出现余数大于 9 9 9&#xff0c;则说明 x x x 的 b b b 进制一定要用字母进行表示。 #include <iostream> #include <cstring> #include <algorithm> #include &l…

大数据Hive中的UDF:自定义数据处理的利器(上)

文章目录 1. 前言2. UDF与宏及静态表的对比3. 深入理解UDF4. 实现自定义UDF 1. 前言 在大数据技术栈中&#xff0c;Apache Hive 扮演着数据仓库的关键角色&#xff0c;它提供了丰富的数据操作功能&#xff0c;并通过类似于 SQL 的 HiveQL 语言简化了对 Hadoop 数据的处理。然而…