Http 模块

Http 模块

Web 服务器

  • 什么是Web服务器?

    • 当应用程序(客户端)需要某一个资源时,可以向一个台服务器,通过Http请求获取到这个资源;提供资源的这个服务器,就是一个Web服务器

      在这里插入图片描述

  • 目前有很多开源的Web服务器:Nginx、Apache(静态)、Apache Tomcat(静态、动态)、Node.js

Web 服务器初体验

// 导入 nodejs 内置的模块
const http = require("http");

// 创建服务器对象
const app = http.createServer((require, response) => {
  console.log("收到请求");
  response.end("hello");
});

// 监听端口
app.listen(8000, () => {
  console.log("http://localhost:8000");
});

创建服务器

  • 创建服务器对象,我们是通过createServer来完成的

    • http.createServer会返回服务器的对象;
    • 底层其实使用直接new Server对象。
  • 那么,当然,我们也可以自己来创建这个对象:

    // 导入 nodejs 内置的模块
    const http = require("http");
    
    // 创建服务器对象
    const app = new http.createServer((req, res) => {
      console.log("收到请求");
    });
    
    // 监听端口
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });
    
  • 上面我们已经看到,创建Server时会传入一个回调函数,这个回调函数在被调用时会传入两个参数:

    • req:request请求对象,包含请求相关的信息;
    • res:response响应对象,包含我们要发送给客户端的信息;

监听主机和端口号

  • Server通过listen方法来开启服务器,并且在某一个主机和端口上监听网络请求:

    • 也就是当我们通过ip:port的方式发送到我们监听的Web服务器上时;
    • 我们就可以对其进行相关的处理;
  • listen函数有三个参数:

  • 端口port: 可以不传, 系统会默认分配端口(通过server.address().port), 后续项目中我们会写入到环境变量中;

    const http = require("http");
    
    const app = http.createServer((req, res) => {
      res.end("hello");
    });
    
    // 监听端口
    // 省略端口号:随机开启 0-65535之间的端口号
    app.listen(() => {
      console.log(app.address().port);
    });
    

    在这里插入图片描述

  • 主机host: 通常可以传入localhostip地址127.0.0.1、或者ip地址0.0.0.0,默认是0.0.0.0

    • localhost:本质上是一个域名,通常情况下会被解析成127.0.0.1

      // 导入nodejs内置模块
      const http = require("http");
      
      // 创建服务器对象
      const app = http.createServer((req, res) => {
        res.end("hello world");
      });
      
      app.listen(8000, "localhost", () => {
        console.log("服务器开启成功");
      });
      

      在这里插入图片描述

      在这里插入图片描述

    • 127.0.0.1:回环地址(Loop Back Address),表达的意思其实是我们主机自己发出去的包,直接被自己接收;

      • 正常的数据库包经常 应用层 - 传输层 - 网络层 - 数据链路层 - 物理层 ;

      • 而回环地址,是在网络层直接就被获取到了,是不会经过数据链路层和物理层的;

      • 比如我们监听127.0.0.1时,在同一个网段下的主机中,通过ip地址是不能访问的;

        // 导入nodejs内置模块
        const http = require("http");
        
        // 创建服务器对象
        const app = http.createServer((req, res) => {
          res.end("hello world");
        });
        
        app.listen(8000, "127.0.0.1", () => {
          console.log("服务器开启成功");
        });
        
      • 注意这里通过浏览器127.0.0.1:8000或者localhost:8000都是可以访问的,但是ip地址是不可以的

    • 0.0.0.0:

      • 监听IPV4上所有的地址,再根据端口找到不同的应用程序;

      • 比如我们监听0.0.0.0时,在同一个网段下的主机中,通过ip地址是可以访问的;

        // 导入nodejs内置模块
        const http = require("http");
        
        // 创建服务器对象
        const app = http.createServer((req, res) => {
          res.end("hello world");
        });
        
        app.listen(8000, "0.0.0.0", () => {
          console.log("服务器开启成功");
        });
        
      • 这里是可以通过自己电脑的ip地址访问的(查询自己的ip地址,cmd输入ipconfig

        在这里插入图片描述

      • 浏览器访问结果展示(以下这三个都是可以访问的)

        在这里插入图片描述

        在这里插入图片描述

        在这里插入图片描述

    • 什么也不写

      // 导入nodejs内置模块
      const http = require("http");
      
      // 创建服务器对象
      const app = http.createServer((req, res) => {
        res.end("hello world");
      });
      
      app.listen(8000, () => {
        console.log("服务器开启成功");
      });
      
      • 首先通过本机ip地址访问

        在这里插入图片描述

      • 因此可以看出我们平常省略不写,省略默认的是0.0.0.0

    • 还有就是本机ip地址

      // 导入nodejs内置模块
      const http = require("http");
      
      // 创建服务器对象
      const app = http.createServer((req, res) => {
        res.end("hello world");
      });
      
      app.listen(8000, "192.168.0.100", () => {
        console.log("服务器开启成功");
      });
      
      • 这种情况就只能本地ip地址访问

        在这里插入图片描述

  • 回调函数:服务器启动成功时的回调函数;

request 对象

  • 在向服务器发送请求时,我们会携带很多信息,比如:

    • 本次请求的URL,服务器需要根据不同的URL进行不同的处理;

    • 本次请求的请求方式,比如GETPOST请求传入的参数和处理的方式是不同的;

    • 本次请求的headers中也会携带一些信息,比如客户端信息、接受数据的格式、支持的编码格式等;

    • 等等

      const http = require("http");
      
      const app = http.createServer((req, res) => {
        // 请求地址
        console.log(req.url);
        // 请求方式
        console.log(req.method);
        // 请求头
        console.log(req.headers);
      });
      
      app.listen(8000, () => {
        console.log("服务器开启成功");
      });
      
    • 发送请求打印结果展示

      在这里插入图片描述

  • 这些信息,Node会帮助我们封装到一个request的对象中,我们可以直接来处理这个request对象:

url

  • 代码实例

    const http = require("http");
    
    const app = http.createServer((req, res) => {
      // 请求地址
      console.log(req.url);
    });
    
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });	
    
  • 根据上面的代码展示我们可知道请求路径是/

  • 但是如果我们给请求路径改成这样的

    在这里插入图片描述

  • 这个时候console.log(req.url)打印出来的结果是

    在这里插入图片描述

  • 所以我们就可以通过url来判断操作

    const http = require("http");
    
    const app = http.createServer((req, res) => {
      // 请求地址
      // console.log(req.url);
      if (req.url === "/user") {
        console.log("查询用户");
      } else if (req.url === "/del") {
        console.log("删除用户");
      }
    });
    
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });
    
  • 比如:

    在这里插入图片描述

  • 输出打印结果

    在这里插入图片描述

url 的处理

  • 代码实例

    const http = require("http");
    
    const app = http.createServer((req, res) => {
      console.log(req.url);
      if (req.url === "/user") {
        console.log("查询用户");
      }
    });
    
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });
    
  • 当我们给url带一些参数的时候(这里换成了Postman接口测试工具:https://blog.csdn.net/HTML_Z/article/details/125140256

    在这里插入图片描述

  • 发送请求,这个时候你就会发现console.log("查询用户")打印不出来了,路径不匹配了

    在这里插入图片描述

URL的解析

  • 我们如何对它进行解析呢?使用内置模块url

    const http = require("http");
    const url = require("url");
    
    const app = http.createServer((req, res) => {
      // console.log(req.url);
      const obj = url.parse(req.url);
      console.log(obj);
      // if (req.url === "/user") {
      //   console.log("查询用户");
      // }
    });
    
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });
    
  • 打印结果展示

    在这里插入图片描述

  • 这个时候我们就可以结构obj在进行判断

    const http = require("http");
    const url = require("url");
    
    const app = http.createServer((req, res) => {
      const { pathname } = url.parse(req.url);
      if (pathname === "/user") {
        console.log("查询用户");
      }
    });
    
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });
    
  • 发送请求,结果验证

    在这里插入图片描述

  • 这个问题解决了,但是我们打印出来的的参数query如何使用呢

    • 这里我们需要引入一个内置模块querystring

      const http = require("http");
      const url = require("url");
      const qs = require("querystring");
      
      const app = http.createServer((req, res) => {
        const { pathname, query } = url.parse(req.url);
        const obj = qs.parse(query);
        if (pathname === "/user") {
          console.log("查询用户");
          console.log(obj);
        }
      });
      
      app.listen(8000, () => {
        console.log("服务器开启成功");
      });
      
    • 打印结果展示

      在这里插入图片描述

method的处理

  • Restful规范(设计风格)中,我们对于数据的增删改查应该通过不同的请求方式:

    • GET:查询数据;

    • POST:新建数据;

    • PATCH:更新数据;

    • DELETE:删除数据;

      const http = require("http");
      
      const app = http.createServer((req, res) => {
        if (req.method === "GET") {
          console.log("查询");
        } else if (req.method == "POST") {
          console.log("修改");
        } else if (req.method == "DELETE") {
          console.log("删除");
        } else if (req.method == "PUT") {
          console.log("新增");
        }
      });
      
      app.listen(8000, () => {
        console.log("服务器开启成功");
      });
      
  • 所以,我们可以通过判断不同的请求方式进行不同的处理。

    • 比如创建一个用户:
    • 请求接口为/users
    • 请求方式为POST请求;
    • 携带数据usernamepassword

创建用户接口

  • 在我们程序中如何进行判断以及获取对应的数据呢?

    • 这里我们需要判断接口是/users,并且请求方式是POST方法去获取传入的数据;

    • 获取这种body携带的数据,我们需要通过监听reqdata事件来获取;

      在这里插入图片描述

    • 代码实例展示

      const http = require("http");
      
      const app = http.createServer((req, res) => {
        if (req.method === "POST") {
          // 获取参数
          req.on("data", (data) => {
            console.log(data);
          });
        }
      });
      
      app.listen(8000, () => {
        console.log("服务器开启成功");
      });
      
    • 发送请求打印结果(Buffer类型)

      在这里插入图片描述

  • JSON字符串格式转成对象类型,通过JSON.parse方法即可。

    const http = require("http");
    
    const app = http.createServer((req, res) => {
      if (req.method === "POST") {
        let buffer = "";
        let obj = {};
        req.on("data", (data) => {
          buffer += data;
        });
        req.on("end", () => {
          const str = buffer.toString();
          obj = JSON.parse(str);
          console.log(obj);
        });
      }
    });
    
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });
    
    const http = require("http");
    
    const app = http.createServer((req, res) => {
      if (req.method === "POST") {
        let buffer = "";
        // 设置字符集 utf8
        req.setEncoding = "utf8";
        req.on("data", (data) => {
          buffer += data;
        });
        req.on("end", () => {
          console.log(JSON.parse(buffer));
        });
      }
    });
    
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });
    
    • 发送请求,结果显示

      在这里插入图片描述

headers属性

  • request对象的header中也包含很多有用的信息,客户端会默认传递过来一些信息:

    const http = require("http");
    
    const app = http.createServer((req, res) => {
      console.log(req.headers);
    });
    
    app.listen(8000, () => {
      console.log("服务器开启成功");
    });
    

    在这里插入图片描述

    • 控制台打印结果

      在这里插入图片描述

  • content-type是这次请求携带的数据的类型:

    • application/json表示是一个json类型;

    • text/plain表示是文本类型;

    • application/xml表示是xml类型;

    • multipart/form-data表示是上传文件;

    • x-www-form-urlencoded表单数据,不能上传文件

      const http = require("http");
      
      const app = http.createServer((req, res) => {
        console.log(req.headers["content-type"]);
      });
      
      app.listen(8000, () => {
        console.log("服务器开启成功");
      });
      
  • content-length:文件的大小和长度

  • keep-alive:(保持会话的时间)

    • http是基于TCP协议的,但是通常在进行一次请求和响应结束后会立刻中断;
    • http1.0中,如果想要继续保持连接:
      • 浏览器需要在请求头中添加connection: keep-alive
      • 服务器需要在响应头中添加connection:keey-alive
      • 当客户端再次放请求时,就会使用同一个连接,直接一方中断连接;
    • http1.1中,所有连接默认是connection: keep-alive的;
      • 不同的Web服务器会有不同的保持keep-alive的时间;
      • Node中默认是5s中;
  • accept-encoding:告知服务器,客户端支持的文件压缩格式,比如js文件可以使用gzip编码,对应.gz文件;

  • accept:告知服务器,客户端可接受文件的格式类型;

  • user-agent:客户端相关的信息;

返回响应结果

  • 如果我们希望给客户端响应的结果数据,可以通过两种方式:

    • Write方法:这种方式是直接写出数据,但是并没有关闭流;

      const http = require("http");
      
      const app = http.createServer((req, res) => {
        // 响应方式一
        res.write("你好");
        // 结束会话 完整的请求
        res.end("在干吗");
      });
      
      app.listen(8000, () => {
        console.log("服务器开启成功");
      });
      

      在这里插入图片描述

    • end方法:这种方式是写出最后的数据,并且写出后会关闭流;

      const http = require("http");
      
      const app = http.createServer((req, res) => {
        // 响应方式二
        res.end("hello");
      });
      
      app.listen(8000, () => {
        console.log("服务器开启成功");
      });
      

      在这里插入图片描述

    • 上面我们响应的是一个字符串,那假如是对象或者数组呢?

      • 对象

        const http = require("http");
        
        const app = http.createServer((req, res) => {
          const user = {
            id: 1,
            username: "张三",
            age: 20,
          };
          res.end(JSON.stringify(user));
        });
        
        app.listen(8000, () => {
          console.log("服务器开启成功");
        });
        

        在这里插入图片描述

      • 数组

        const http = require("http");
        
        const app = http.createServer((req, res) => {
          const users = [
            {
              id: 1,
              username: "张三",
              age: 20,
            },
            {
              id: 2,
              username: "李四",
              age: 18,
            },
          ];
          res.end(JSON.stringify(users));
        });
        
        app.listen(8000, () => {
          console.log("服务器开启成功");
        });
        
        

        在这里插入图片描述

  • 如果我们没有调用endclose,客户端将会一直等待结果:\

    • 所以客户端在发送网络请求时,都会设置超时时间。

返回状态码

  • Http状态码(Http Status Code)是用来表示Http响应状态的数字代码:

    • Http状态码非常多,可以根据不同的情况,给客户端返回不同的状态码;

    • 常见的状态码是下面这些(后续项目中,也会用到其中的状态码);

      状态代码状态描述说明
      200OK客户端请求成功
      400Bad Request由于客户端请求 有语法错误,不能被服务器所理解
      401Unauthorized请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用
      403Forbidden服务器收到请求,但是拒绝提供服务,服务器通常会在响应正文中给出不提供服务的原因
      404Not Found请求的资源不存在,例如:输入了错误的URL
      500Internal Server Error服务器发生不可预期的错误,导致无法完成客户端的请求
      503Service Unavaliable服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常
  • 设置状态码常见的有两种方式:

    • 第一种

      // 导入 nodejs 内置的模块
      const http = require("http");
      
      // 创建服务器对象
      const app = http.createServer((req, res) => {
        // 响应状态码设置
        res.statusCode = 400;
        res.end("123");
      });
      
      // 监听端口
      app.listen(8000, () => {
        console.log("http://localhost:8000");
      });
      

      在这里插入图片描述

    • 第二种

      // 导入 nodejs 内置的模块
      const http = require("http");
      
      // 创建服务器对象
      const app = http.createServer((req, res) => {
        // 响应状态码设置
        res.writeHead(400);
        res.end("123");
      });
      
      // 监听端口
      app.listen(8000, () => {
        console.log("http://localhost:8000");
      });
      

      在这里插入图片描述

响应头文件

  • 返回头部信息,主要有两种方式:

    • res.setHeader:一次写入一个头部信息;

      // 导入 nodejs 内置的模块
      const http = require("http");
      
      // 创建服务器对象
      const app = http.createServer((req, res) => {
        res.setHeader("content-type", "application/json;charset=utf8");
        const user = {
          id: 1,
          name: "admin",
          nickName: "张三",
        };
        res.end(JSON.stringify(user));
      });
      
      // 监听端口
      app.listen(8000, () => {
        console.log("http://localhost:8000");
      });
      

      在这里插入图片描述

    • res.writeHead:同时写入headerstatus

      // 导入 nodejs 内置的模块
      const http = require("http");
      
      // 创建服务器对象
      const app = http.createServer((req, res) => {
        res.writeHead(200, {
          "content-type": "text/html",
        });
        const user = {
          id: 1,
          name: "admin",
          nickName: "张三",
        };
        res.end("<h2>hello world</h2>");
      });
      
      // 监听端口
      app.listen(8000, () => {
        console.log("http://localhost:8000");
      });
      

      在这里插入图片描述

  • Header设置Content-Type有什么作用呢?

    • 默认客户端接收到的是字符串,客户端会按照自己默认的方式进行处理;

http 请求

  • axios库可以在浏览器中使用,也可以在Node中使用:

    • 在浏览器中,axios使用的是封装xhr

    • Node中,使用的是http内置模块;

      // 导入 nodejs 内置的模块
      const http = require("http");
      
      // 创建服务器对象
      const app = http.createServer((req, res) => {
        const user = [
          {
            id: 1,
            username: "admin",
            nickname: "张三",
            gender: 1,
          },
          {
            id: 2,
            username: "admin",
            nickname: "王五",
            gender: 1,
          },
          {
            id: 3,
            username: "admin",
            nickname: "李四",
            gender: 0,
          },
          {
            id: 4,
            username: "admin",
            nickname: "大大",
            gender: 1,
          },
        ];
        res.end(JSON.stringify(user));
      });
      
      // 监听端口
      app.listen(8000, () => {
        console.log("http://localhost:8000");
      });
      
      const http = require("http");
      
      const app = http.createServer((req, res) => {
        // http.get("http://localhost:8000", (res) => {
        //   res.on("data", (data) => {
        //     console.log(data.toString());
        //     console.log(JSON.parse(data.toString()));
        //   });
        // });
        http
          .request(
            {
              hostname: "localhost",
              port: 8000,
              method: "POST",
            },
            (res) => {
              res.on("data", (data) => {
                console.log(JSON.parse(data.toString()));
              });
            }
          )
          .end();
        res.end();
      });
      
      app.listen(9999, () => {
        console.log("9999开启成功");
      });
      
      • 终端打印结果

        在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值