hotgo/server/internal/logic/middleware/response.go

123 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package middleware
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package middleware
import (
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/util/gmeta"
"hotgo/internal/consts"
"hotgo/internal/library/response"
"hotgo/utility/charset"
"hotgo/utility/simple"
)
// ResponseHandler HTTP响应预处理
func (s *sMiddleware) ResponseHandler(r *ghttp.Request) {
r.Middleware.Next()
// 错误状态码接管
switch r.Response.Status {
case 403:
r.Response.Writeln("403 - 网站拒绝显示此网页")
return
case 404:
r.Response.Writeln("404 - 你似乎来到了没有知识存在的荒原…")
return
}
contentType := getContentType(r)
// 已存在响应
if contentType != consts.HTTPContentTypeStream && r.Response.BufferLength() > 0 { // && contexts.Get(r.Context()).Response != nil
return
}
switch contentType {
case consts.HTTPContentTypeHtml:
s.responseHtml(r)
return
case consts.HTTPContentTypeXml:
s.responseXml(r)
return
case consts.HTTPContentTypeStream:
default:
responseJson(r)
}
}
// responseHtml html模板响应
func (s *sMiddleware) responseHtml(r *ghttp.Request) {
code, message, resp := parseResponse(r)
if code == gcode.CodeOK.Code() {
return
}
r.Response.ClearBuffer()
_ = r.Response.WriteTplContent(simple.DefaultErrorTplContent(r.Context()), g.Map{"code": code, "message": message, "stack": resp})
}
// responseXml xml响应
func (s *sMiddleware) responseXml(r *ghttp.Request) {
code, message, data := parseResponse(r)
response.RXml(r, code, message, data)
}
// responseJson json响应
func responseJson(r *ghttp.Request) {
code, message, data := parseResponse(r)
response.RJson(r, code, message, data)
}
// parseResponse 解析响应数据
func parseResponse(r *ghttp.Request) (code int, message string, resp interface{}) {
ctx := r.Context()
err := r.GetError()
if err == nil {
return gcode.CodeOK.Code(), "操作成功", r.GetHandlerResponse()
}
// 是否输出错误堆栈到页面
if simple.Debug(ctx) {
message = gerror.Current(err).Error()
if getContentType(r) == consts.HTTPContentTypeHtml {
resp = charset.SerializeStack(err)
} else {
resp = charset.ParseErrStack(err)
}
} else {
message = consts.ErrorMessage(gerror.Current(err))
}
code = gerror.Code(err).Code()
// 记录异常日志
// 如果你想对错误做不同的处理,可以通过定义不同的错误码来区分
// 默认-1为安全可控错误码只记录文件日志非-1为不可控错误记录文件日志+服务日志并打印堆栈
if code == gcode.CodeNil.Code() {
g.Log().Stdout(false).Infof(ctx, "exception:%v", err)
} else {
g.Log().Errorf(ctx, "exception:%v", err)
}
return
}
func getContentType(r *ghttp.Request) (contentType string) {
contentType = r.Response.Header().Get("Content-Type")
if contentType != "" {
return
}
mime := gmeta.Get(r.GetHandlerResponse(), "mime").String()
if mime == "" {
contentType = consts.HTTPContentTypeJson
} else {
contentType = mime
}
return
}