Node.js |(四)HTTP协议 | 尚硅谷2023版Node.js零基础视频教程

学习视频:尚硅谷2023版Node.js零基础视频教程,nodejs新手到高手

文章目录

补充笔记

📚HTTP概念


📚窥探HTTP报文

  • Fiddler

  • 安装fiddler

  • 配置

    • ToolOptions里 ,找到HTTPS勾选Decrypt..,然后同意接下来的弹窗。记得点OK!然后重启!!

    • 设置Web Browsers
  • 使用

    • 双击某一条则会显示详细信息
    • 选择Raw会显示详细信息

📚请求报文的组成


🐇HTTP请求行

  • 请求方法

  • URLUniform Reaourse Locator,统一资源定位符,其本身也是一个字符串。

  • 版本号

🐇HTTP请求头

  • 格式:头名:头值

🐇HTTP的请求体

📚响应报文的组成



🐇响应行



🐇响应头和响应体

  • 响应体内容的类型是非常灵活的,常见的类型有 HTML、CSS、JS、图片、JSON。
  • 相应头请求头这些都是不需要记住的,在MDN可查。

  • IP的介绍
    • IP也称为【IP地址】,本身是一个数字标识。
    • IP用来标识网络设备,用来实现设备通信。
    • 端口:应用程序的数字标识,实现不同主机应用程序之间的通信。

📚使用node.js创建HTTP服务


  1. 命令行 ctrl + c停止服务
  2. 当服务启动后,更新代码必须重启服务才能生效
  3. 响应内容中文乱码的解决办法:response.setHeader('content-type','text/html;charset=utf-8');
  4. 端口号被占用:Error: listen EADDRINUSE: address already in use :::9000
    1)关闭当前正在运行监听端口的服务 ( 使用较多 )
    2)修改其他端口号
  5. HTTP 协议默认端口是 80 。HTTPS 协议的默认端口是 443, HTTP 服务开发常用端口有 3000,
    8080,8090,9000 等。
js 复制代码
//1. 导入 http 模块
const http = require('http');

//2. 创建服务对象
const server = http.createServer((request, response) => {
  //response.end('Hello HTTP'); //设置响应体
  //解决响应内容中文乱码的问题
  response.setHeader('content-type', 'text/html;charset=utf-8');
  response.end('你好'); //设置响应体
});

//3. 监听端口, 启动服务
//9000是端口号,以下在服务启动成功时运行
server.listen(9000, () => {
  console.log('服务已经启动....')
});

📚浏览器查看HTTP报文

尚硅谷教程





实操

  • 运行上边写的代码,打开对应网页,F12检查,查看网络。
  • 查看127.0.0.1细节
  • 运行表单页提交内容并查看请求体

  • 查看URL查询字符串
  • 查看响应体

📚获取HTTP请求报文

  • 想要获取请求的数据,需要通过request对象

  1. request.url只能获取路径以及查询字符串,无法获取 URL 中的域名以及协议的内容
  2. request.headers将请求信息转化成一个对象,并将属性名都转化成了『小写』
  3. 关于路径:如果访问网站的时候,只填写了 IP 地址或者是域名信息,此时请求的路径为『 / 』
  4. 关于 favicon.ico:这个请求是属于浏览器自动发送的请求------获取图标

🐇提取HTTP报文

js 复制代码
//1. 导入 http 模块
const http = require('http');

//2. 创建服务对象
const server = http.createServer((request, response) => {
  //获取请求的方法
  console.log(request.method);
  //获取请求的 url
  console.log(request.url);// 只包含 url 中的路径与查询字符串
  //获取 HTTP 协议的版本号
  console.log(request.httpVersion);
  //获取 HTTP 的请求头
  console.log(request.headers.host);
  response.end('http'); //设置响应体
});

//3. 监听端口, 启动服务
server.listen(9000, () => {
  console.log('服务已经启动....')
});

🐇提取HTTP报文的请求体(了解)

js 复制代码
//1. 导入 http 模块
const http = require('http');

//2. 创建服务对象
const server = http.createServer((request, response) => {
  //1. 声明一个变量
  let body = '';
  //2. 绑定 data 事件
  request.on('data', chunk => {
    body += chunk;
  })
  //3. 绑定 end 事件
  request.on('end', () => {
    console.log(body);
    //响应
    response.end('Hello HTTP');
  });
});

//3. 监听端口, 启动服务
server.listen(9000, () => {
  console.log('服务已经启动....')
});
  • 借助form表单

    html 复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <form action="http://127.0.0.1:9000/index.html" method="post" >
        <input type="text" name="username">
        <input type="text" name="password">
        <input type="submit" value="提交">
      </form>
    </body>
    </html>

🐇提取HTTP报文中URL路径与查询字符串

法一

js 复制代码
//导入 http 模块
const http = require('http');
//1. 导入 url 模块(node.js内置模块)
const url = require('url');

//创建服务对象
const server = http.createServer((request, response) => {
  //2. 解析 request.url ,parse:解析
  let res = url.parse(request.url, true);
  console.log(res);
  //路径
  let pathname = res.pathname;
  console.log(pathname);
  //查询字符串
  let keyword = res.query.keyword;
  console.log(keyword);
  response.end('url');
});

//监听端口, 启动服务
server.listen(9000, () => {
  console.log('服务已经启动....')
});

法二

小插曲本来以为是05没关,但ctrlC后还是报错🤔重开vs后OK😄记得CtrlC终止后再开新的终端⚠️
ps:nodejs端口号占用------解决办法

js 复制代码
//导入 http 模块
const http = require('http');

//创建服务对象
const server = http.createServer((request, response) => {
  //实例化 URL 的对象
  let url = new URL(request.url, 'http://127.0.0.1');
  //输出路径
  console.log(url.pathname);
  //输出 keyword 查询字符串
  console.log(url.searchParams.get('keyword'));
  response.end('url new');
});

//监听端口, 启动服务
server.listen(9000, () => {
  console.log('服务已经启动....')
});

🐇HTTP请求练习

js 复制代码
//1. 导入 http 模块
const http = require('http');

//2. 创建服务对象
const server = http.createServer((request, response) => {
  //获取请求的方法
  let {method} = request;
  //获取请求的 url 路径
  let {pathname} = new URL(request.url, 'http://127.0.0.1');
  response.setHeader('content-type','text/html;charset=utf-8');
  //判断
  if(method === 'GET' && pathname === '/login'){
    //登录的情形
    response.end('登录页面');
  }else if(method === 'GET' && pathname === '/reg'){ // register 注册
    response.end('注册页面');
  }else{
    response.end('Not Found');
  }
});

//3. 监听端口 启动服务
server.listen(9000, () => {
  console.log('服务已经启动.. 端口 9000 监听中....');
})



📚HTTP响应报文

🐇设置HTTP响应报文

js 复制代码
//导入 http 模块
const http = require('http');

//创建服务对象
const server = http.createServer((request, response) => {
  //1. 设置响应状态码
  response.statusCode = 203;
  //response.statusCode = 404;
  //2. 响应状态的描述 
  response.statusMessage = 'iloveyou';
  //3. 响应头
  response.setHeader('content-type', 'text/html;charset=utf-8');
  // response.setHeader('Server', 'Node.js');
  // response.setHeader('myHeader', 'test test test');
  // response.setHeader('test', ['a','b','c']);
  //4. 响应体的设置
  response.write('love');
  response.write('love');
  response.write('love');
  response.write('love');//write可以多次调用
  response.end('love'); //设置响应体
  //end不能不写也不能写多个,不然会报错
  //response.end('xxx'); //设置响应体
});

//监听端口, 启动服务
server.listen(9000, () => {
  console.log('服务已经启动....')
});

🐇HTTP响应练习

  • 需求:搭建 HTTP 服务,响应一个 4 行 3 列的表格,并且要求表格有隔行换色效果 ,且 点击单元格能高亮显示

  • 采用html和js分离+导入实现。

  • html完成表格样式

    html 复制代码
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        td {
          padding: 20px 40px;
        }
        /* odd even交替实现隔行换色 */
        table tr:nth-child(odd) {
          background: rgb(202, 219, 255);
        }
    
        table tr:nth-child(even) {
          background: #fcb;
        }
    
        table,
        td {
          border-collapse: collapse;
        }
      </style>
    </head>
    
    <body>
      <table border="1">
        <tr>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
        </tr>
      </table>
      <script>
        //实现点击换色
        //获取所有的 td
        let tds = document.querySelectorAll('td');
        //遍历
        tds.forEach(item => {
          item.onclick = function () {
            this.style.background = 'yellow';
          }
        })
      </script>
    </body>
    
    </html>
  • js设置响应

    js 复制代码
    //导入 http 模块
    const http = require('http');
    const fs = require('fs');
    
    //创建服务对象
    const server = http.createServer((request, response) => {
      //读取文件内容
      let html = fs.readFileSync(__dirname + '/10_table.html');
      response.end(html); //设置响应体
    });
    
    //监听端口, 启动服务
    server.listen(9000, () => {
      console.log('服务已经启动....')
    });


📚网页资源的基本加载过程

  • 网页资源的加载 都是循序渐进的,首先获取 HTML 的内容, 然后解析 HTML 在发送其他资源的请求,如CSS,Javascript,图片等。
  • 理解了这个内容对于后续的学习与成长有非常大的帮助。

🐇实现网页引入外部资源

  • 这里使用的是上边那个表格的练习例子,但把html、css、js都单独拆开,关注外部资源引入问题!

    js 复制代码
    //导入 http 模块
    const http = require('http');
    const fs = require('fs');
    
    //创建服务对象
    const server = http.createServer((request, response) => {
      //获取请求url的路径
      let {pathname} = new URL(request.url, 'http://127.0.0.1');
      if(pathname === '/'){
        //读取文件内容
        let html = fs.readFileSync(__dirname + '/10_table.html');
        response.end(html); //设置响应体
      }
      else if(pathname === '/index.css'){
        //读取文件内容
        let css = fs.readFileSync(__dirname + '/index.css');
        response.end(css); //设置响应体
      }
      else if(pathname === '/index.js'){
        //读取文件内容
        let js = fs.readFileSync(__dirname + '/index.js');
        response.end(js); //设置响应体
      }
      else{
        response.statusCode = 404;
        response.end('<h1>404 Not Found</h1>')
      }
    });
    
    //监听端口, 启动服务
    server.listen(9000, () => {
      console.log('服务已经启动....')
    });

以上写法可行但很麻烦,于是接下来看静态资源服务👇

📚静态资源服务

  • 静态资源是指内容长时间不发生改变的资源 ,例如图片,视频,CSS 文件,JS文件,HTML文件,字体文件等。
  • 动态资源是指内容经常更新的资源 ,例如百度首页,网易首页,京东搜索列表页面等。
  • HTTP 服务在哪个文件夹中寻找静态资源,那个文件夹就是静态资源目录,也称之为网站根目录

🐇网页中的URL

喔------又是绝对路径相对路径喏------

  • 绝对路径

  • 相对路径

  • 关注运行后的URL拼接方式!

    html 复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>URL</title>
    </head>
    <body>
      <!-- 绝对路径 -->
      <a href="https://www.baidu.com">百度</a>
      <a href="//jd.com">京东</a>
      <a href="/search">搜索</a>
      <hr>
      <!-- 相对路径 -->
      <a href="./css/app.css">访问CSS</a>
      <a href="js/app.js">访问JS</a>
      <a href="../img/logo.png">访问图片</a>
      <a href="../../img/logo.png">访问图片</a>
    </body>
    </html>

🐇设置资源类型(mime类型)

js 复制代码
/**
 * 创建一个 HTTP 服务,端口为 9000,满足如下需求
 * GET  /index.html        响应  page/index.html 的文件内容
 * GET  /css/app.css       响应  page/css/app.css 的文件内容
 * GET  /images/logo.png   响应  page/images/logo.png 的文件内容
 */
//导入 http 模块
const http = require('http');
const fs = require('fs');
const path = require('path');
//声明一个变量
let mimes = {
  html: 'text/html',
  css: 'text/css',
  js: 'text/javascript',
  png: 'image/png',
  jpg: 'image/jpeg',
  gif: 'image/gif',
  mp4: 'video/mp4',
  mp3: 'audio/mpeg',
  json: 'application/json'
}

//创建服务对象
const server = http.createServer((request, response) => {
  if(request.method !== 'GET'){
    response.statusCode = 405;
    response.end('<h1>405 Method Not Allowed</h1>');
    return;
  }
  //获取请求url的路径
  let {pathname} = new URL(request.url, 'http://127.0.0.1');
  //声明一个变量
  let root = __dirname + '/page';
  // let root = __dirname + '/../';
  //拼接文件路径
  let filePath = root + pathname;
  //读取文件 fs 异步 API
  fs.readFile(filePath, (err, data) => {
    if(err){
      console.log(err);
      //设置字符集
      response.setHeader('content-type','text/html;charset=utf-8');
      //判断错误的代号
      switch(err.code){
        case 'ENOENT':
          response.statusCode = 404;
          response.end('<h1>404 Not Found</h1>');
        case 'EPERM':
          response.statusCode = 403;
          response.end('<h1>403 Forbidden</h1>');
        default:
          response.statusCode = 500;
          response.end('<h1>Internal Server Error</h1>');
      }
      
      return;
    }
    //获取文件的后缀名
    let ext = path.extname(filePath).slice(1);
    //获取对应的类型
    let type = mimes[ext];
    if(type){
      //匹配到了 text/html;charset=utf-8
      if(ext === 'html'){
        //解决乱码问题
        response.setHeader('content-type', type + ';charset=utf-8');
      }else{
        response.setHeader('content-type', type);
      }
    }else{
      //没有匹配到
      response.setHeader('content-type', 'application/octet-stream');
    }
    //响应文件内容
    response.end(data);
  })
  
});

//监听端口, 启动服务
server.listen(9000, () => {
  console.log('服务已经启动....')
});

🐇GET和POST请求场景小结

🐇GET和POST请求的区别

  • GET POST 是 HTTP 协议请求的两种方式。
    • GET主要用来获取数据,POST主要用来提交数据
    • GET 带参数请求是将参数缀到 URL 之后,在地址栏中输入 url 访问网站就是 GET 请求,
    • POST 带参数请求是将参数放到请求体中。
    • POST 请求相对 GET安全一些,因为在浏览器中参数会暴露在地址栏。
    • GET请求大小有限制,一般为 2K,而POST请求则没有大小限制。
相关推荐
甜瓜看代码3 小时前
1.
react.js·node.js·angular.js
伍哥的传说4 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
古希腊数通小白(ip在学)4 小时前
stp拓扑变化分类
运维·服务器·网络·智能路由器
01传说5 小时前
vue3 配置安装 pnpm 报错 已解决
java·前端·vue.js·前端框架·npm·node.js
摘星小杨8 小时前
如何卸载本机的node.js
node.js
程序小武10 小时前
网络请求的基本概念、原理及生活化解析
网络协议
hrrrrb11 小时前
【TCP/IP】11. IP 组播
服务器·网络·tcp/ip
甘露寺11 小时前
HTTP 请求体类型详解:选择最适合的数据提交格式
网络·网络协议·http
七仔あ11 小时前
小皮面板搭建pikachu靶场
网络·渗透
傻啦嘿哟11 小时前
长效住宅代理IP:反爬虫战场上的隐形盾牌
爬虫·网络协议·tcp/ip