Axios+Gin跨域解决完整方案

Axios+Gin 跨域一条龙

前端使用 axios 请求,后端通过 gin 搭设,详解所有源码实现跨域自由!!!
前端部分 axios 配置是封装好的完整代码,可以直接拿去用


前端部分

安装 axios
npm install axios


首先创建文件 interceptor.js 用来配置 axios 拦截器以及初始化

特别特别注意! baseURL 必须标注请求协议 http ,否则必定报错!

const server = axios.create({
  // 千万不要落了 http://
  baseURL: "http://localhost:10086/",
  timeout: 300 * 1000,
  withCredentials: true, // 这里是为了让cookie通过

  // 配置通用头
  headers: {
    "Content-Type": "application/x-www-form-urlencoded",
  },
});

// 请求拦截器
server.interceptors.request.use(
  (config) => {
    // 如果请求方法为GET,则字符串化params
    if (config.method === "get") {
      config.paramsSerializer = (params) => {
        return qs.stringify(params, {
          arrayFormat: "comma",
        });
      };
    }

    // 获取用户token并附带在headers里传递给后端
    const token = localStorage.token;
    if (token) {
      config.headers["token"] = token;
    }
    return config;
  },
  (err) => {
    Promise.reject(err);
  }
);

// 响应拦截器
server.interceptors.response.use(
  (config) => {
    return config;
  },
  (err) => {
    // 如果错误的响应体存在的话
    if (err.response) {
      // 获取响应值message
      const msg =
        err.response.data === null
          ? "服务端出错,无法获取响应内容"
          : err.response.data.message;

      // 根据响应状态码来返回对应信息
      switch (err.response.status) {
        case STATUS.success.id:
          ElMessage(STATUS.success.msg);
          break;
        default:
          if (msg === "invalid token") {
            ElMessage("登录状态过期,请重新登陆");
          } else {
            ElMessage(msg);
          }
          break;
      }
    }
    return Promise.reject(err);
  }
);

export default server;

然后封装一个 http.js 用于后续 axios 请求使用

// 导入我们刚刚编写好的interceptor.js
import server from "@/api/interceptor.js";

const http = {
  // axios执行get请求
  get(url, params) {
    const config = {
      method: "get",
      url: url,
    };
    // 当存在params时,才会将其添加到config并发送给后端
    if (params) config.params = params;
    return server(config);
  },

  // axios执行post请求
  post(url, formdata) {
    const config = {
      method: "post",
      url: url,
    };
    if (formdata) config.data = formdata;
    return server(config);
  },
};

export default http;

后端部分

cors.go

编写跨域处理中间件 cors.go

注意到 Access-Control-Allow-Origin 这里不像是其余帖子一以贯之的都是写 * ,是因为当我们在前端自定义 cookie 时,发送给后端的 origin 是变化的,我们必须取得前端的 origin 然后对其进行放行才可以!

我们在 Access-Control-Allow-Headers 这一条里面添加了 token ,是因为前端的 axios 请求拦截器会自动插入一个名叫 token 的请求头,如果我们在后端没有允许的话,那么依然请求失败!!!

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

func Cors() gin.HandlerFunc {
	return func(context *gin.Context) {
		// 允许 Origin 字段中的域发送请求
		context.Writer.Header().Add("Access-Control-Allow-Origin", context.GetHeader("origin"))
		// 设置预验请求有效期为 70000 秒
		context.Writer.Header().Set("Access-Control-Max-Age", "70000")
		// 设置允许请求的方法
		context.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE, PATCH")
		// 设置允许请求的 Header
		context.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length,token")
		context.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Headers,token")
		// 配置是否可以带认证信息
		context.Writer.Header().Set("Access-Control-Allow-Credentials", "true")

		// OPTIONS请求返回200
		if context.Request.Method == "OPTIONS" {
			fmt.Println(context.Request.Header)
			context.AbortWithStatus(200)
		} else {
			context.Next()
		}

		fmt.Println("开始跨域拦截")
	}
}

main.go

最后在 router 初始化后直接使用 use 插入中间件即可!

func main()  {
	
	// 获取router实例
	Router := gin.Default()

	// 建议在总路由初始化后立即插入cors中间件
	// 最好不要在别的地方添加!
	Router.Use(middleware.Cors())

	...
}

愉悦的测试环节

万事俱备只欠东风!

前端使用封装好的 http 快速请求后端接口,成功拿到数据!没有任何跨域报错!

const axiosRequest = () => {
  http
    .get("/bk/test")
    .then((res) => {
      console.log(res);
    })
    .catch((err) => {
      console.log(err);
    });
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhillery

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值