Http

70 阅读7分钟

协议

双方必须共同尊从的一组约定

http 协议

是浏览器 与 服务器之间的通信协议 计算机中浏览器与服务器之间通信通过报文的形式进行传输信息

请求报文

分为几个部分: 1. 请求行 2. 请求头 3.请求体 请求头和请求体中间有个空行

  • 请求行

    一般包括几个部分, 1. 请求方法 2. 请求资源路径(URL, 定位服务器中的资源) 3. http协议版本

    • 请求方法: 1. GET 2. POST 3. HEAD 4. PUT 5. DELETE 6. CONNECT 7. OPTIONS 8. TRACE 但主要使用 get 和 post
    • URL: 第一部分协议名, 第二部分域名, 第三部分端口号, 第四部分资源路径, 第五部分查询参数
    • 版本号: 1.0 1996 年发布, 1.1 1999 年发布, 2 2015 年发布 , 3 2018 年发布
  • 请求头 以一个个键值对组成, 记录了浏览器的一些相关信息,可以查看 MDN 文档进行理解

  • 请求体 他的数据类型很灵活, 只要你和后端约定好,都可以传输

image.png

响应报文

基本和响应报文相似; 1. 响应行 2. 响应头 3. 响应体 响应头和响应体中间有个空行

  • 响应行 分为几个部分, 1. http协议版本 2. 状态码 3. 状态码描述

    • 状态码: 1XX(信息响应), 2XX(成功), 3XX(重定向), 4XX(客户端错误响应), 5XX(服务器端错误响应)
    • 状态码描述: 描述状态码的含义, 可以查看MDN文档,了解更多具体的内容
  • 响应头 记录了与服务器相关的信息,还记录了一些与响应体相关的信息(content-type), 还有响应体的大小(content-length), 可以查看MDN文档进行理解

  • 响应体 响应体的数据类型很灵活, 只要你和前端约定好,都可以传输

image.png

IP

本质是一个32位二进制数, 用来唯一标识网络中的设备, 实现设备间的通讯, 但是 32 bit 不利于使用, 于是对这 32 bit 的数据进行分组, 每 8 bit 组成一组,把这 8 位转换成 10 进制, 然后组合起来用 . 分隔

端口

端口是应用程序的数字标识 主要作用是实现了不同主机应用程序之间通讯

创建服务器

注意一个问题, 响应文本信息时, 要设置响应体的类型, res.setHeader('Content-Type', 'application/html;chartset=utf-8')

获取请求报文

 const http = require('http')

// req 是请求体的封装对象, 里面包含了请求体的各种信息
// res 是响应体的封装对象, 里面包含了响应体的各种信息, 这个回调函数在什么时候会被调用, 在服务器接收到请求的时候调用
const server = http.createServer((req, res) => {

    // 获取请求报文
    console.log(req.method);
    // 获取请求 url 
    console.log(req.url); // 注意只包括 路径和参数 
    // 获取请求头
    console.log(req.headers);

    res.setHeader('Content-Type', 'application/html;charset=utf-8') // 可以解决文本乱码的情况
    res.end('hello world') //设置响应体
})

server.listen(3000, () => {
    console.log('server is running at http://127.0.0.1:3000')
})

获取请求体的内容

本质是一个可读流, 可以使用 on 方法进行监听(data, end)

const http = require('http')

// req 是请求体的封装对象, 里面包含了请求体的各种信息
// res 是响应体的封装对象, 里面包含了响应体的各种信息, 这个回调函数在什么时候会被调用, 在服务器接收到请求的时候调用
const server = http.createServer((req, res) => {

    // 获取请求体的内容
    // 1. 声明一个变量
    let body = ''
    // 2. 绑定 data 事件
    req.on('data', chunk => {
        body += chunk
    })
    // 绑定 end 事件
    req.on('end', () => {
        console.log(body)
        // 响应
        res.end(body)
    })


})

server.listen(3000, () => {
    console.log('server is running at http://127.0.0.1:3000')
})

获取请求报文中的 URL 路径和参数

  1. 使用内置模块 url , 他能对 url 参数进行解析
  2. 也可以使用 new URL() 方法进行获取, 可以查看官方文档 nodejs.cn, URL 必须接受一个完整协议, 否则会报错
const ulr = require('url') 
// 获取请求报文中的 url 路径和参数
const server = http.createServer((req, res) => {
    // 解析 url
    const url = url.parse(req.url, true) // 第二个参数是可选的, 用与标识查询字符串, 返回是否为一个对象
    console.log(url.pathname); // 路径
    console.log(url.query); // 参数
   
})

server.listen(3000, () => {
    console.log('server is running at http://127.0.0.1:3000')
})

设置 Http 响应报文

  • 设置响应状态码 response.statusCode
  • 设置响应状态描述 response.statusMessage (用的很少)
  • 设置响应头信息 response.setHeader(头名, 头值)
  • 设置响应体 response.end(响应体) 或者 response..write(响应体)
    1. write 和 end 的结合使用, 响应体相对分散 response.write('hello') // 可以多次调用 response.end() // 每一个请求, 在处理的时候必须要执行 end 方法, 并且 end 方法只能执行一次
    2. 单独使用 end 方法, 响应体相对集中 response.end('hello')

// 获取请求报文中的 url 路径和参数
const server = http.createServer((req, res) => {
    // 设置状态码
    res.statusCode = 404
    // 设置状态码描述
    res.statusMessage = 'Not Found'
    // 设置响应头
    // res.setHeader('Content-Type', 'text/plain;charset=utf-8')
    // 响应头的设置可以自定义设置, 
    // res.setHeader('test', ['a', 'b', 'c']) // 这个方法设置多个自定义的同名响应头

    res.write('love') // 多次调用会拼接
    res.write('hate')
    res.end() // 结束响应, 一定要在 write 之后, 并且 write 之后的操作不能再 write, 否则会报错
   
})

server.listen(3000, () => {
    console.log('server is running at http://127.0.0.1:3000')
})

网页加载基本流程

  1. 浏览器向服务器发送请求
  2. 服务器返回响应报文
  3. 浏览器解析响应报文, 获取响应体
  4. 浏览器将响应体渲染到页面上 多个资源请求是并行下载的 举例: 当一个 html 结构中出现 link 或则 script 标签时, 浏览器会并行下载这些资源, 当这些资源下载完成时, 浏览器会按照顺序将这些资源加载到内存中, 然后再渲染页面

静态资源和动态资源

  • 静态资源: 内容长时间不发生改变的资源
  • 动态资源: 内容经常发生改变的资源

实践, 处理一个页面的响应

  1. 普通的一个 html 结构, 有 link 和 css 文件, 在处理响应时,需要分别处理, 查看 响应训练 文件

实践, 创建静态资源服务

将静态资源放在一个文件夹中, 这里面的路径都相同, 通过路径拼接可以获取对应的资源

image.png

静态资源目录和网站根目录

http 服务在哪个文件夹中寻找静态资源, 那个文件夹就是静态资源目录, 也称为网站根目录 这个根目录我们可以手动修改,在哪里找到静态资源, 那个文件夹就是根目录

网页中的 URL -- 绝对路径、

绝对路径可靠性强, 而且相对容易理解, 在项目中运用较多 image.png 最常用第三种, 因为 可能会换主机名域名等

网页 URL --- 相对路径

image.png

设置资源类型 (mime 类型)

称为媒体类型, 是一种标准, 用来表示文档、文字、字节流的性质和格式, 设置响应头的方式设置进去

mime 类型结构: [type]/[subtype] eg: text/html image/jpeg application/json

Http 服务可以设置响应头 Content-Type, 来表明响应体的 MIME 类型, 浏览器会根据该类型决定如何处理资源 常见的文件对应 mime 类型 image.png

mime 浏览器自己会计算返回一个(根据数据返回的类型), 我们也可以手动设置, 这样更规范

乱码问题解决

我们设置了 mime 类型后, 如果遇到中文会乱码, 怎么解决这个问题, 在后面拼接上 ;charset=utf-8, 另外,网页 html 文件会有一个 meta 标签, 用来声明编码格式, 也可以设置 charset 属性一般设置是 utf-8, 他的优先级低于 header 中设置的

res.setHeader('Content-Type', `text/${ext};charset=utf-8`)

一般处理的响应字符级会根据网页的字符级进行解码, 只要网页设置了 charset 属性, 后面请求会来的数据都会根据这个字符级进行解码