HTTP封装与实用场景|青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第9天。今天主讲HTTP和Node.js相关知识,HTTP是Web中最基础的信息交互协议,前端工程师对HTTP熟练掌握,分析请求协议,熟悉应用场景与开发实例。优秀的前端工程师不仅是一名UI设计师、还是一位网络工程师。
一、本节课重点内容:
本节课重点包括:HTTP协议、node协议、三次握手和报文原理等。
二、课堂知识点纪要:
- HTTP协议:
- HTTP是一种超文本传输协议,是处于应用层的协议,基于TCP协议。
- 包括请求和响应两部分。
- HTTP是一种可扩展的协议。
- 同时是一种无状态协议。
- HTTP发展协议:
- HTTP0.9只能Get 只能HTML
- HTTP1.0增加请求头Header 可以带状态码 支持多种文档
- HTTP1.1 标准化协议 链接可复用 可缓存 内容可协商
- HTTP2 二进制协议 压缩了请求头 服务器推送
- HTTP报文
- GET 只用于获取数据
- POST 用于提交指定资源,导致服务器状态变化
- PUT 用请求载荷替换当前内容
- DELETE 删除请求资源
- HEAD 请求一个没有响应体的GET
- CONNECT 建立到服务器的隧道
- OPTIONS 描述目标资源的通信选项卡
- TRACE 沿着目标值元执行消息换回测试
- PATCH 用于对资源应用部分修改
- 协议报文
- 状态码
- 1XX 请求已接收
- 2XX 请求接受成功
- 3XX 重定向到新的请求 请求未结束
- 4XX 客户端页面请求错误
- 5XX 服务器响应错误
- RESTful API
- 每个URL表示一种资源
- 客户端与服务器传递资源的表现层
- 客户端通过HTTP method,对服务端资源操作时,实现“表现层状态转化”
- 请求头
- ACCEPT 接收类型
- Content-Type 客户端发送去实体内容
- Cache-Control 指定请求响应缓存机制
- If-Modified-Since 对应服务端的Last-Modified
- Expires 缓存控制,时间段内不做请求,直接使用缓存,服务端时间
- Max-age 代表资源在本地缓存的上限
- If-None-Match 对应服务端的ETag 用于匹配文件内容
- Cookie 在同源访问时会带上返回的Cookie
- Referer 请求源的URL,精确到地址
- Origin Origin比Referer更尊重隐私 也是返回一个隐私
- User-Agent 用户客户端的必要信息
- 响应头
- Content-Type 服务端返回的实体内容
- Cache-Control 指定请求内容响应缓存机制
- Last-Modified 返回请求资源的最后修改时间
- Expires 文件过期的时间阈
- Set-Cookie 设置、关联Cookie 服务器把Cookie传给客户端
- Server 服务器信息
- Access-Control-Allow-Origin 允许请求Origin头部
- HTTP/2概述
- HTTP/2链接是用急救的
- 由服务器推送 并带有流控制
- HTTPS协议
- HTTPS是经过TSL/SSL加密的HTTP协议
- 加密形式包括对称加密与非对称加密
- 状态码
- 场景分析
- 静态资源
- 缓存+CDN+文件名Hash
- 登录
- 表单登录、扫码登录
- SSO
- 跨域登录 可能会出现OPTIONS 预检
- CORS安全策略
- 代理服务器
- iframe
- 鉴权登录
- Session+Cookie
- JWT (JSON web Token)
- SSO 单点登录
- 静态资源
三、实践练习案例:
使用AJAX和Promise封装一个axios实例库
//Authored by iiru
//powerby styled.js
//基础样式
import styled from "styled-components";
export const MainContain =styled.div`
width:1440px;
height:666px;
margin:2%;
padding:1% 1% 1% 2.5%;
background-image: radial-gradient(#B86D1E,#7B4914);
.blackboard{
width:98%;
height:98%;
background-image:radial-gradient(#536E4F,#415E40,#20381E);
}
`
export const MainContent =styled.div`
margin:4% 45%;
width:200px;
float:right;
font-size:32px;
color:#efefef;
`
//请求参数
interface normalPost {
url:string;
data:any;
}
//请求体封装
interface XHR {
method:string;
url:string;
data:any;
resMethod:any;
}
//请求api域名Url
const baseConfig:any = {
baseUrl:"http://www.domain.com/api",
contentType: 'application/json;charset=utf-8'
}
//Ajax Post封装
export const Post=(props:normalPost)=>{
const post = async (params:any)=>{
try{
let res:any = await httpReq({
method:"post",
url:params.url,
data:(typeof params.data === "string")?params.data:JSON.stringify(params.data),
resMethod:''})
return (typeof res === "object")?res:JSON.parse(res);
}catch{
console.log("请求返回出错!")
}
}
return post(props)
}
//Ajax Get异步封装
export const Get=(props:normalPost)=>{
const get = async (params:any)=>{
try{
let res:any = await httpReq({
method:"get",
url:params.url,
data:params.data,
resMethod:''})
return (typeof res === "object")?res:JSON.parse(res);
}catch{
console.log("请求返回出错!")
}
}
return get(props)
}
//Ajax Put异步封装
export const Put=(props:normalPost)=>{
const put = async (params:any)=>{
try{
let res:any = await httpReq({
method:"put",
url:params.url,
data:params.data,
resMethod:''})
return (typeof res === "object")?res:JSON.parse(res);
}catch{
console.log("请求返回出错!")
}
}
return put(props)
}
//Ajax Delete异步封装
export const Delete=(props:normalPost)=>{
const del = async (params:any)=>{
try{
let res:any = await httpReq({
method:"delete",
url:params.url,
data:params.data,
resMethod:''})
return (typeof res === "object")?res:JSON.parse(res);
}catch{
console.log("请求返回出错!")
}
}
return del(props)
}
export const httpReq = function (props:XHR){
const promise=(e:any)=>new Promise((resolve, reject)=> {
const callBack=(e:any)=>{
if (e.readyState !== 4 ) return;
if (e.status === 200) resolve(e.response)
else reject(new Error(e.statusCode))
return Promise
}
//请求函数封装
const req =(props:XHR)=>{
//实例化XMLHttpRequest对象
const request = new XMLHttpRequest();
request.withCredentials = true;
request.open(props.method,
baseConfig.baseUrl+props.url,
true)
request.responseType = props.resMethod;
if (props.method === 'get') {
request.send(props.data);
} else {
request.setRequestHeader("Content-Type", baseConfig.contentType);
request.send(props.data)
}
request.onreadystatechange =()=> callBack(request);
}
req(e);
})
return promise(props)
}
- 在React调用封装好的HTTP实现异步登录请求:
//Authored by iiru
//powerby styled.js
import React from "react";
import { MainContain,MainContent} from "./axios";
import {Post} from "./axios"
import {Input,Button,InputRef,message} from "antd";
interface Login {
mail: string|InputRef|null;
password: string|InputRef|null;
}
//页面组件
export function Async(){
//封装请求参数:
const loginData:Login = {
mail:"xxxx@163.com",
password:"xxxxx"
}
//请求二次封装
const loginPost= (e:any) => Post({url:"/login",data:e})
//登录按钮函数
const Submit=(e:any)=>{
//封装请求参数
const loginParmas ={
mail:e.mail.input.value,
password:e.password.input.value}
const tips=(data:any,e:any)=>{
if(e.code === 200) message.success("Hello!"+data.mail.input.value)
else if(e.Code === 400) message.error("Sorry,Please Input Create Mail Account!")
else message.error("Sorry,Login Failed!")
}
Promise.resolve(
//异步执行请求并取得返回体
loginPost(loginParmas))
.then(
(res)=>{
tips(e,res)
}
)
}
return (
<>
<MainContain>
<MainContain>
<MainContent>
<Input className={"Inputy"} placeholder="input account" ref={input => loginData.mail = input} />
<Input.Password className={"Inputy"} placeholder="input password" ref={input => loginData.password = input} />
<Button className ={"submitbtn"} onClick={()=>Submit(loginData)}>登录</Button>
</MainContent>
</MainContain>
</MainContain>
</>
);
}
四、参考文献:
五、心得体会:
学习了今天的课程,了解了HTTP的进阶知识,对HTTP状态码 跨域、策略都有新的认识.
尝试封装了ajax请求,对ajax的原理也基本掌握,理解了HTTPS加密协议原理,对HTTP应用场景
也深入了解。