rpi-relay/internal/middleware/middleware.go

97 lines
2.0 KiB
Go

package middleware
import (
"bytes"
"fmt"
"io"
cc "rpirelay/internal/context"
apierr "rpirelay/internal/errors"
"rpirelay/internal/response"
"runtime"
"strings"
"github.com/pkg/errors"
)
func Initialize(secret string) *Middleware {
return &Middleware{secret: secret}
}
type Middleware struct {
secret string
}
func (m *Middleware) APIPanicCatch() cc.CustomHandler {
return func(c *cc.C) {
defer func() {
if err := recover(); err != nil {
// build error
// *****
builder := new(strings.Builder)
builder.WriteString("[API Error Catch]\n")
pc := make([]uintptr, 10)
n := runtime.Callers(1, pc)
frames := runtime.CallersFrames(pc[:n])
builder.WriteString("\n[Stack]\n")
for {
frame, more := frames.Next()
builder.WriteString(fmt.Sprintf("%s\n\t%s:%d\n", frame.Func.Name(), frame.File, frame.Line))
if !more {
break
}
}
builder.WriteString("\n[Error]\n")
builder.WriteString(fmt.Sprintf("%v\n", err))
fmt.Printf("%s\n", builder.String())
// *****
var e *apierr.APIError
if converted, ok := err.(*apierr.APIError); ok {
e = converted
} else {
e = apierr.ErrInternalError
}
code := make([]response.MessageCode, 0)
if c := e.Code(); c != nil {
code = append(code, *c)
}
resp := response.Get(e.Status(), code...)
c.AbortWithStatusJSON(resp.Status, resp.Body)
}
}()
// 是json body 才做複製
if c.GetHeader("content-type") == "application/json" {
data, err := c.GetRawData()
if err != nil {
panic(apierr.ErrInternalError.SetErr(err))
}
c.Request.Body = io.NopCloser(bytes.NewBuffer(data))
c.Set("_RawBody", data)
}
c.Next()
}
}
func (m *Middleware) Authorization() cc.CustomHandler {
return func(c *cc.C) {
auth := c.GetHeader("x-lawsnote-key")
if auth == "" {
panic(apierr.ErrUnauthorized.SetErr(errors.New("no lawsnote header found")))
}
if auth != m.secret {
panic(apierr.ErrForbidden.SetErr(errors.New("secret not match")))
}
c.Next()
}
}