协议
双方必须共同尊从的一组约定
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 文档进行理解
-
请求体 他的数据类型很灵活, 只要你和后端约定好,都可以传输
响应报文
基本和响应报文相似; 1. 响应行 2. 响应头 3. 响应体 响应头和响应体中间有个空行
-
响应行 分为几个部分, 1. http协议版本 2. 状态码 3. 状态码描述
- 状态码: 1XX(信息响应), 2XX(成功), 3XX(重定向), 4XX(客户端错误响应), 5XX(服务器端错误响应)
- 状态码描述: 描述状态码的含义, 可以查看MDN文档,了解更多具体的内容
-
响应头 记录了与服务器相关的信息,还记录了一些与响应体相关的信息(content-type), 还有响应体的大小(content-length), 可以查看MDN文档进行理解
-
响应体 响应体的数据类型很灵活, 只要你和前端约定好,都可以传输
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 路径和参数
- 使用内置模块 url , 他能对 url 参数进行解析
- 也可以使用 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(响应体)
- write 和 end 的结合使用, 响应体相对分散 response.write('hello') // 可以多次调用 response.end() // 每一个请求, 在处理的时候必须要执行 end 方法, 并且 end 方法只能执行一次
- 单独使用 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')
})
网页加载基本流程
- 浏览器向服务器发送请求
- 服务器返回响应报文
- 浏览器解析响应报文, 获取响应体
- 浏览器将响应体渲染到页面上 多个资源请求是并行下载的 举例: 当一个 html 结构中出现 link 或则 script 标签时, 浏览器会并行下载这些资源, 当这些资源下载完成时, 浏览器会按照顺序将这些资源加载到内存中, 然后再渲染页面
静态资源和动态资源
- 静态资源: 内容长时间不发生改变的资源
- 动态资源: 内容经常发生改变的资源
实践, 处理一个页面的响应
- 普通的一个 html 结构, 有 link 和 css 文件, 在处理响应时,需要分别处理, 查看 响应训练 文件
实践, 创建静态资源服务
将静态资源放在一个文件夹中, 这里面的路径都相同, 通过路径拼接可以获取对应的资源
静态资源目录和网站根目录
http 服务在哪个文件夹中寻找静态资源, 那个文件夹就是静态资源目录, 也称为网站根目录 这个根目录我们可以手动修改,在哪里找到静态资源, 那个文件夹就是根目录
网页中的 URL -- 绝对路径、
绝对路径可靠性强, 而且相对容易理解, 在项目中运用较多
最常用第三种, 因为 可能会换主机名域名等
网页 URL --- 相对路径
设置资源类型 (mime 类型)
称为媒体类型, 是一种标准, 用来表示文档、文字、字节流的性质和格式, 设置响应头的方式设置进去
mime 类型结构: [type]/[subtype] eg: text/html image/jpeg application/json
Http 服务可以设置响应头 Content-Type, 来表明响应体的 MIME 类型, 浏览器会根据该类型决定如何处理资源
常见的文件对应 mime 类型
mime 浏览器自己会计算返回一个(根据数据返回的类型), 我们也可以手动设置, 这样更规范
乱码问题解决
我们设置了 mime 类型后, 如果遇到中文会乱码, 怎么解决这个问题, 在后面拼接上 ;charset=utf-8, 另外,网页 html 文件会有一个 meta 标签, 用来声明编码格式, 也可以设置 charset 属性一般设置是 utf-8, 他的优先级低于 header 中设置的
res.setHeader('Content-Type', `text/${ext};charset=utf-8`)
一般处理的响应字符级会根据网页的字符级进行解码, 只要网页设置了 charset 属性, 后面请求会来的数据都会根据这个字符级进行解码