HTTP模块(二)

HTTP

设置 HTTP 响应报文

HTTP报文常见属性:

const http = require('http');

const server = http.createServer((request, response) => {
    // 设置请求状态码 2xx 4xx 5xx
    response.statusCode = 200;
    // 设置请求描述 了解即可
    response.statusMessage = 'hello'
    // 指定响应体的MIME类型
    response.setHeader('Content-Type', 'text/html; charset=utf-8');
    // 指定响应内容的编码方式,如gzip或deflate,用于内容压缩。
    response.setHeader('Content-Encoding', 'gzip');
    // 用于实现跨源资源共享(CORS),指定哪些网站可以访问该资源。
    response.setHeader('Access-Control-Allow-Origin', '*'); // 允许所有来源,实际应用中可能需要指定具体来源
    // 指示浏览器如何缓存响应
    response.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); // 禁止缓存
    // 一个实体标签,用于验证资源是否有变化
    response.setHeader('ETag', 'W/"abcd1234"');
    // 表示资源最后一次修改的时间。
    response.setHeader('Last-Modified', new Date().toUTCString());
    // 指示服务器软件的信息
    response.setHeader('Server', 'MyCustomServer/1.0');
    // 设置Cookie,用于会话管理等。
    response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
    // 指定响应过期时间,之后浏览器将不再缓存此响应。
    response.setHeader('Expires', new Date(Date.now() + 86400000).toUTCString()); // 一天后过期

    response.end('Hello Http Server');
});

server.listen(9000, () => {
    console.log('服务已启动');
});

加载 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;
      }

      table tr:nth-child(odd) {
        background: pink;
      }

      table tr:nth-child(even) {
        background: red;
      }

      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>
    </table>
    <script>
      //获取所有的 td
      let tds = document.querySelectorAll("td");
      //遍历
      tds.forEach((item) => {
        item.onclick = function () {
          this.style.background = "#ffffff";
        };
      });
    </script>
  </body>
</html>

通过 FS 模块

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

const server = http.createServer((request, response) => {
    const table = fs.readFileSync(__dirname + `/table.html`);

    response.end(table);
});

server.listen(9000, () => {
    console.log('服务已启动');
});

response.end不仅可以接收字符串作为参数,发送文本数据给客户端,还能够接收 Buffer 对象来发送二进制数据,如图片、音频或视频文件等,需要注意的是使用 Buffer 时,确保你的内容类型(Content-Type)设置与实际数据类型相匹配,以便浏览器或客户端能够正确处理。

网页资源加载基本过程

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>标题</title>
    <link rel="stylesheet" href="./css/index.css" />
  </head>
  <body>
    <h1>这是一个HTML页面</h1>
    <hr />
    <img width="100%" src="./images/h5.png" alt="" />
    <script src="./js/index.js"></script>
  </body>
</html>
  1. 请求HTML文档 :浏览器首先向服务器发送请求以获取HTML文档。这一步通常通过URL完成。
  2. 解析HTML :浏览器开始解析收到的HTML文档,构建DOM(文档对象模型)。解析过程中,浏览器会遇到以下类型的资源:
  • CSS:当遇到link标签引用外部CSS文件或style标签包含内联样式时,浏览器会开始加载CSS(如果是外部链接,则发送CSS请求)。CSS的加载通常与HTML解析并行进行 ,但CSS的解析(构建CSSOM,即CSS对象模型)可能等待CSS文件完全加载后才进行,以确保正确应用样式。内联样式会立即被处理。
  • IMG 图片:遇到img标签时,浏览器会立即发送请求下载图片,但不会等待图片加载完成就继续解析HTML,以加快页面内容的显示。图片加载通常是异步的。
  • JavaScript:当浏览器遇到script标签时,一般分为同步脚本和异步脚本:
    • 同步脚本:默认情况下,JavaScript的加载和执行会阻塞HTML的解析。浏览器会暂停构建DOM,等待脚本下载并执行完毕。这是因为JavaScript有可能修改DOM结构或CSSOM
    • 异步脚本:如果script标签指定了async属性,脚本会在下载的同时允许HTML解析继续,且脚本下载完成后会异步执行,不保证执行顺序。如果使用defer属性(仅适用于外部脚本),脚本同样不会阻塞HTML解析,但所有带有defer的脚本会在HTML解析完成后,DOMContentLoaded事件触发之前,按照在HTML中出现的顺序执行。
  1. 渲染流程 :在解析HTML和加载CSS的过程中,浏览器开始构建渲染树,它是DOMCSSOM的合并产物,表示哪些节点需要如何显示。一旦渲染树构建完成,并且相关资源(如图片)准备就绪,浏览器会开始渲染页面。
  2. 重排与重绘 :在页面加载和JavaScript修改DOM/CSSOM时,可能会触发布局重排(Reflow)和样式重绘(Repaint),以反映页面结构或样式的改变。

加载 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>
  <link rel="stylesheet" href="../css/index.css">
</head>

<body>
  <table border="1">
    <tr>
      <td></td>
      <td></td>
      <td></td>
    </tr>
    <tr>
      <td></td>
      <td></td>
      <td></td>
    </tr>
  </table>
  <script src="../js/index.js"></script>
</body>
</html>

目录结构

├─css
├─html
├─js
└─服务.js

启动服务.js

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

const server = http.createServer((request, response) => {
    const table = fs.readFileSync(__dirname + `/html/table.html`);

    response.end(table);
});

server.listen(9000, () => {
    console.log('服务已启动');
});

会发现css样式和js点击功能失效。

这是由于响应报文均返回html所导致。

调整代码为以下即可:

//导入 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');
  console.log('pathname', pathname);
  if(pathname === '/'){
    let html = fs.readFileSync(__dirname + '/html/10_table.html');
    response.end(html); 
  }else if(pathname === '/css/index.css'){
    let css = fs.readFileSync(__dirname + '/css/index.css');
    response.end(css); 
  }else if(pathname === '/js/index.js'){
    let js = fs.readFileSync(__dirname + '/js/index.js');
    response.end(js);
  }else{
    response.statusCode = 404;
    response.end('<h1>404 Not Found</h1>')
  }
  
});

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

加载HTML文件内容(优化二)

//导入 http 模块
const http = require('http');
const fs = require('fs');
const path = require('path');

//创建服务对象
const server = http.createServer((request, response) => {
  //获取请求url的路径
  let { pathname } = new URL(request.url, 'http://127.0.0.1');
  const filePath = __dirname + pathname;
  fs.readFile(filePath, (err, data) => {
    if (err) {
      response.statusCode = 500;
      return;
    }
    console.log('data', data);
    response.end(data);
  })

加载HTML文件内容(优化三)

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) => {

    // 拼接路径
    let url = new URL(request.url, 'http://127.0.0.1');

    // 根目录
    let root = __dirname + '/page';

    // 拼接文件路径 css js html ...
    let filePath = root + url.pathname;

    // 读取文件
    fs.readFile(filePath, (err, data) => {
        if (err) {
            console.error(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) {
            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

  • 在地址栏直接输入url访问
  • 点击a链接
  • link标签引入css
  • script标签引入js
  • img标签引入脱
  • from标签中的method为get
  • ajax中的get请求

POST

  • form标签中的method为post
  • ajax的post请求
相关推荐
理想不理想v11 小时前
webpack最基础的配置
前端·webpack·node.js
南城巷陌14 小时前
JWT认证机制在Node.js中的详细阐述
node.js·jwt认证机制·前端安全认证
理想不理想v16 小时前
node.js的简单示例
node.js
yrldjsbk16 小时前
使用Node.js搭配express框架快速构建后端业务接口模块Demo
node.js·express
维李设论16 小时前
Node.js的Web服务在Nacos中的实践
前端·spring cloud·微服务·eureka·nacos·node.js·express
CodeChampion18 小时前
60.基于SSM的个人网站的设计与实现(项目 + 论文)
java·vue.js·mysql·spring·elementui·node.js·mybatis
Domain-zhuo18 小时前
如何利用webpack来优化前端性能?
前端·webpack·前端框架·node.js·ecmascript
理想不理想v18 小时前
webpack如何自定义插件?示例
前端·webpack·node.js
斜杠poven1 天前
为什么加try catch 不会 block 进程?
前端·javascript·node.js