contracts/support/response.go
2024-05-09 13:15:24 +08:00

194 lines
5.0 KiB
Go

package support
import (
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/req"
"github.com/gorilla/websocket"
"github.com/samber/lo"
)
type RawResponse struct {
raw []byte
}
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 RawResponse) Get(path ...string) req.GlobalParams {
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(this.raw), nil), req.NewGlobalParam(string(this.raw), nil).Get(strings.Join(path, ".")))
}
func (this RawResponse) 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.Write(this.raw)
}
}
func (this JsonResponse) Get(path ...string) req.GlobalParams {
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(this.raw), nil), req.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) req.GlobalParams {
if resp, err := json.Marshal(map[string]any{
"code": this.code,
"msg": this.msg,
}); err == nil {
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(resp), nil), req.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) req.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, req.NewGlobalParam(string(resp), nil), req.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) req.GlobalParams {
if resp, err := json.Marshal(map[string]any{
"name": this.name,
"disposition": this.disposition,
}); err == nil {
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(resp), nil), req.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 NewRawResponse(b []byte) req.HttpResponse {
return &RawResponse{raw: b}
}
func NewJsonResponse(b []byte) req.HttpResponse {
return &JsonResponse{raw: b}
}
func NewFileResponse(name string, disposition string) req.HttpResponse {
return &FileResponse{name: name, disposition: disposition}
}
func NewMsgResponse(msg string, code int) req.HttpResponse {
return &MsgResponse{msg: msg, code: code}
}
func NewErrResponse(err *contracts.Err) req.HttpResponse {
return NewJsonResponse([]byte(fmt.Sprintf(`{"code": %d, "msg": %q}`, err.Code, err.Error())))
}
func HttpResponse(data any) req.HttpResponse {
var err error
// fmt.Printf("%#v \n", data)
switch v := data.(type) {
case req.HttpResponse:
return v
case contracts.Errno:
return NewMsgResponse(v.Error(), v.Code)
case *contracts.Errno:
return NewMsgResponse(v.Error(), v.Code)
case contracts.Err:
return NewErrResponse(&v)
case *contracts.Err:
return NewErrResponse(v)
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 NewErrResponse(contracts.NewErr(contracts.InternalServerError, err))
}