Go语学习笔记 - 跨域配置、全局异常捕获 | Web框架Gin(四)

学习笔记,写到哪是哪。

接着上一篇的文章构建的项目:Go语学习笔记 - 项目规范结构调整 | Web框架Gin(三)_剑客阿良_ALiang的博客-CSDN博客

项目结构进一步调整为mvc结构,但还是需要加一些配置,比如跨域配置和全局异常捕获。

在项目开发中,某些非业务类的异常通常都会使用全局异常捕获的方法,简化代码量,下面我来调整一下之前的项目。

项目地址:github地址 

跨域配置

在app/router文件夹下增加middlewares.go文件。

 

增加跨域支持方法,代码如下:

//跨域设置
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
		origin := c.Request.Header.Get("Origin") //请求头部
		if origin != "" {
			c.Header("Access-Control-Allow-Origin", "*") // 可将将 * 替换为指定的域名
			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
			c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
			c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
			c.Header("Access-Control-Allow-Credentials", "true")
		}
		//允许类型校验
		if method == "OPTIONS" {
			c.JSON(http.StatusOK, "ok!")
		}

		defer func() {
			if err := recover(); err != nil {
				log.Logger.Error("HttpError", zap.Any("HttpError", err))
			}
		}()

		c.Next()
	}
}

全局捕获

在app/router文件夹下middlewares.go文件,增加全局捕获方法Recovery,代码如下。

//全局捕获
func Recovery(c *gin.Context) {
	defer func() {
		if r := recover(); r != nil {
			log.Logger.Error("gin catch error: ", log.Any("gin catch error: ", r))
			c.JSON(http.StatusOK, rsp.FailMsg("系统内部错误"))
		}
	}()
	c.Next()
}

其中的rsp是返回结构体目录,在app/pojo下创建rsp目录,增加response_msg.go文件。

 

response_msg.go文件代码如下:

package rsp

type ResponseMsg struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

func SuccessMsg(data interface{}) *ResponseMsg {
	msg := &ResponseMsg{
		Code: 0,
		Msg:  "SUCCESS",
		Data: data,
	}
	return msg
}

func FailMsg(msg string) *ResponseMsg {
	msgObj := &ResponseMsg{
		Code: -1,
		Msg:  msg,
	}
	return msgObj
}

func FailCodeMsg(code int, msg string) *ResponseMsg {
	msgObj := &ResponseMsg{
		Code: code,
		Msg:  msg,
	}
	return msgObj
}

验证

app/router下的middlewares.go文件,完整代码如下:

package router

import (
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"learn-gin/app/pojo/rsp"
	"learn-gin/config/log"
	"net/http"
)

//跨域设置
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
		origin := c.Request.Header.Get("Origin") //请求头部
		if origin != "" {
			c.Header("Access-Control-Allow-Origin", "*") // 可将将 * 替换为指定的域名
			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
			c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
			c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
			c.Header("Access-Control-Allow-Credentials", "true")
		}
		//允许类型校验
		if method == "OPTIONS" {
			c.JSON(http.StatusOK, "ok!")
		}

		defer func() {
			if err := recover(); err != nil {
				log.Logger.Error("HttpError", zap.Any("HttpError", err))
			}
		}()

		c.Next()
	}
}

//全局捕获
func Recovery(c *gin.Context) {
	defer func() {
		if r := recover(); r != nil {
			log.Logger.Error("gin catch error: ", log.Any("gin catch error: ", r))
			c.JSON(http.StatusOK, rsp.FailMsg("系统内部错误"))
		}
	}()
	c.Next()
}

main.go文件调整,代码如下:

package main

import (
	"github.com/gin-gonic/gin"
	"learn-gin/app/router"
	"learn-gin/config/log"
	"learn-gin/config/toml"
	"net/http"
	"time"
)

func main() {
	log.InitLogger(toml.GetConfig().Log.Path, toml.GetConfig().Log.Level)
	log.Logger.Info("hahahah")
	log.Logger.Info("config", log.Any("config", toml.GetConfig()))

	r := gin.Default()
	r.Use(router.Cors())
	r.Use(router.Recovery)
	router.InitRouter(r)

	s := &http.Server{
		Addr:           ":8080",
		Handler:        r,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	err := s.ListenAndServe()
	if nil != err {
		log.Logger.Error("server error", log.Any("serverError", err))
	}
}

注意

1、在服务启动也调整了一下,不直接run。

2、通过r.Use方法,将跨域方法和全局异常监听加入启动项。

验证一下

在需要添加参数的请求,不添加后,会返回全局统一异常报文。

看一下日志

可以看到接口未处理的异常被全局捕获,返回统一的报文。

小结

现在项目看上去结构比较完整了,虽然一些常用的工具类还没有放进来,但是基本上可以作为开发样板服务。后面我想先把一些常用的工具类放进来,然后试着开始连接数据库,做一些基本业务功能。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

剑客阿良_ALiang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值