HTTP封装与实用场景|青训营笔记

140 阅读5分钟

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应用场景
也深入了解。