206 lines
4.9 KiB
Go
206 lines
4.9 KiB
Go
|
package support
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
"runtime"
|
||
|
"strings"
|
||
|
|
||
|
"git.fsdpf.net/go/contracts"
|
||
|
"github.com/gorilla/websocket"
|
||
|
"github.com/samber/lo"
|
||
|
)
|
||
|
|
||
|
type JsonResponse struct {
|
||
|
raw []byte
|
||
|
}
|
||
|
|
||
|
type MsgResponse struct {
|
||
|
code int
|
||
|
msg string
|
||
|
}
|
||
|
|
||
|
type ErrResponse struct {
|
||
|
*MsgResponse
|
||
|
stack []byte
|
||
|
}
|
||
|
|
||
|
type FileResponse struct {
|
||
|
disposition string
|
||
|
name string
|
||
|
}
|
||
|
|
||
|
var wsUpgrader = websocket.Upgrader{
|
||
|
CheckOrigin: func(r *http.Request) bool {
|
||
|
return true
|
||
|
},
|
||
|
}
|
||
|
|
||
|
func (this JsonResponse) Get(path ...string) contracts.GlobalParams {
|
||
|
return lo.Ternary(len(path) == 0, NewGlobalParam(string(this.raw), nil), NewGlobalParam(string(this.raw), nil).Get(strings.Join(path, ".")))
|
||
|
}
|
||
|
|
||
|
func (this JsonResponse) Send(w http.ResponseWriter, r *http.Request) {
|
||
|
if r.Header.Get("Upgrade") != "" && strings.ToLower(r.Header.Get("Upgrade")) == "websocket" {
|
||
|
c, _ := wsUpgrader.Upgrade(w, r, nil)
|
||
|
c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, string(this.raw)))
|
||
|
c.Close()
|
||
|
} else {
|
||
|
w.Header().Set("Content-Type", "application/json")
|
||
|
w.Write(this.raw)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (this MsgResponse) Get(path ...string) contracts.GlobalParams {
|
||
|
if resp, err := json.Marshal(map[string]any{
|
||
|
"code": this.code,
|
||
|
"msg": this.msg,
|
||
|
}); err == nil {
|
||
|
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (this MsgResponse) Send(w http.ResponseWriter, r *http.Request) {
|
||
|
if resp, err := json.Marshal(this.Get().Value()); err == nil {
|
||
|
(&JsonResponse{raw: resp}).Send(w, r)
|
||
|
} else {
|
||
|
HttpResponse(err).Send(w, r)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (this ErrResponse) Get(path ...string) contracts.GlobalParams {
|
||
|
if resp, err := json.Marshal(map[string]any{
|
||
|
"code": this.code,
|
||
|
"msg": this.msg,
|
||
|
"error": string(this.stack),
|
||
|
}); err == nil {
|
||
|
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (this ErrResponse) Send(w http.ResponseWriter, r *http.Request) {
|
||
|
if resp, err := json.Marshal(this.Get().Value()); err == nil {
|
||
|
(&JsonResponse{raw: resp}).Send(w, r)
|
||
|
} else {
|
||
|
HttpResponse(err).Send(w, r)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (this FileResponse) Get(path ...string) contracts.GlobalParams {
|
||
|
if resp, err := json.Marshal(map[string]any{
|
||
|
"name": this.name,
|
||
|
"disposition": this.disposition,
|
||
|
}); err == nil {
|
||
|
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (this FileResponse) Send(w http.ResponseWriter, r *http.Request) {
|
||
|
if this.Get("disposition").String() != "" {
|
||
|
w.Header().Set("Content-Disposition", `attachment; filename="`+this.Get("disposition").String()+`"`)
|
||
|
}
|
||
|
if _, err := os.Stat(this.Get("name").String()); err != nil && os.IsNotExist(err) {
|
||
|
w.WriteHeader(http.StatusNotFound)
|
||
|
} else {
|
||
|
http.ServeFile(w, r, this.Get("name").String())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func NewJsonResponse(b []byte) contracts.HttpResponse {
|
||
|
return &JsonResponse{raw: b}
|
||
|
}
|
||
|
|
||
|
func NewFileResponse(name string, disposition string) contracts.HttpResponse {
|
||
|
return &FileResponse{name: name, disposition: disposition}
|
||
|
}
|
||
|
|
||
|
func NewMsgResponse(msg string, code int) contracts.HttpResponse {
|
||
|
return &MsgResponse{msg: msg, code: code}
|
||
|
}
|
||
|
|
||
|
func NewErrResponse(p ...any) contracts.HttpResponse {
|
||
|
code := contracts.InternalServerError.Code
|
||
|
msg := contracts.InternalServerError.Error()
|
||
|
data := any(nil)
|
||
|
|
||
|
for i := 0; i < len(p); i++ {
|
||
|
switch v := p[i].(type) {
|
||
|
case error:
|
||
|
msg = v.Error()
|
||
|
case string:
|
||
|
msg = v
|
||
|
case int:
|
||
|
code = v
|
||
|
case contracts.Errno:
|
||
|
msg = v.Error()
|
||
|
code = v.Code
|
||
|
case *contracts.Errno:
|
||
|
msg = v.Error()
|
||
|
code = v.Code
|
||
|
default:
|
||
|
data = v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
stackBuf := make([]byte, 1024)
|
||
|
n := runtime.Stack(stackBuf[:], false)
|
||
|
|
||
|
b, _ := json.Marshal(struct {
|
||
|
Code int `json:"code"`
|
||
|
Msg string `json:"msg"`
|
||
|
Data any `json:"data,omitempty"`
|
||
|
Stack string `json:"stack"`
|
||
|
}{
|
||
|
Code: code,
|
||
|
Msg: msg,
|
||
|
Data: data,
|
||
|
Stack: string(stackBuf[:n]),
|
||
|
})
|
||
|
|
||
|
return NewJsonResponse(b)
|
||
|
}
|
||
|
|
||
|
func HttpResponse(data any) contracts.HttpResponse {
|
||
|
var err error = contracts.InternalServerError
|
||
|
|
||
|
switch v := data.(type) {
|
||
|
case contracts.HttpResponse:
|
||
|
return v
|
||
|
case contracts.Errno:
|
||
|
return NewMsgResponse(v.Error(), v.Code)
|
||
|
case *contracts.Errno:
|
||
|
return NewMsgResponse(v.Error(), v.Code)
|
||
|
case error:
|
||
|
err = v
|
||
|
case []byte:
|
||
|
if b, e := json.Marshal(map[string]any{
|
||
|
"code": contracts.OK.Code,
|
||
|
"msg": contracts.OK.Msg,
|
||
|
"data": json.RawMessage(v),
|
||
|
}); e == nil {
|
||
|
return &JsonResponse{raw: b}
|
||
|
} else {
|
||
|
err = e
|
||
|
}
|
||
|
default:
|
||
|
if b, e := json.Marshal(map[string]any{
|
||
|
"code": contracts.OK.Code,
|
||
|
"msg": contracts.OK.Msg,
|
||
|
"data": v,
|
||
|
}); e == nil {
|
||
|
return &JsonResponse{raw: b}
|
||
|
} else {
|
||
|
err = e
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NewMsgResponse(err.Error(), contracts.InternalServerError.Code)
|
||
|
}
|