mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
http refactor.
This commit is contained in:
parent
4fa11e6a2a
commit
5a7cdd31fe
@ -1,26 +1,66 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"demodesk/neko/internal/http/auth"
|
||||||
|
"demodesk/neko/internal/types"
|
||||||
|
"demodesk/neko/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Logger(next http.Handler) http.Handler {
|
type logEntryKey int
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
req := map[string]interface{}{}
|
|
||||||
|
|
||||||
// exclude healthcheck from logs
|
const logEntryKeyCtx logEntryKey = iota
|
||||||
if r.RequestURI == "/api/health" {
|
|
||||||
next.ServeHTTP(w, r)
|
func setLogEntry(r *http.Request, data logEntry) *http.Request {
|
||||||
return
|
ctx := context.WithValue(r.Context(), logEntryKeyCtx, data)
|
||||||
|
return r.WithContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLogEntry(r *http.Request) logEntry {
|
||||||
|
return r.Context().Value(logEntryKeyCtx).(logEntry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoggerMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
next.ServeHTTP(w, setLogEntry(r, newLogEntry(w, r)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type logEntry struct {
|
||||||
|
req struct {
|
||||||
|
time time.Time
|
||||||
|
id string
|
||||||
|
scheme string
|
||||||
|
proto string
|
||||||
|
method string
|
||||||
|
remote string
|
||||||
|
agent string
|
||||||
|
uri string
|
||||||
}
|
}
|
||||||
|
res struct {
|
||||||
|
time time.Time
|
||||||
|
code int
|
||||||
|
bytes int
|
||||||
|
}
|
||||||
|
err error
|
||||||
|
elapsed time.Duration
|
||||||
|
hasSession bool
|
||||||
|
session types.Session
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLogEntry(w http.ResponseWriter, r *http.Request) logEntry {
|
||||||
|
e := logEntry{}
|
||||||
|
e.req.time = time.Now()
|
||||||
|
|
||||||
if reqID := middleware.GetReqID(r.Context()); reqID != "" {
|
if reqID := middleware.GetReqID(r.Context()); reqID != "" {
|
||||||
req["id"] = reqID
|
e.req.id = reqID
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme := "http"
|
scheme := "http"
|
||||||
@ -28,59 +68,62 @@ func Logger(next http.Handler) http.Handler {
|
|||||||
scheme = "https"
|
scheme = "https"
|
||||||
}
|
}
|
||||||
|
|
||||||
req["scheme"] = scheme
|
e.req.scheme = scheme
|
||||||
req["proto"] = r.Proto
|
e.req.proto = r.Proto
|
||||||
req["method"] = r.Method
|
e.req.method = r.Method
|
||||||
req["remote"] = r.RemoteAddr
|
e.req.remote = r.RemoteAddr
|
||||||
req["agent"] = r.UserAgent()
|
e.req.agent = r.UserAgent()
|
||||||
req["uri"] = fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI)
|
e.req.uri = fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI)
|
||||||
|
return e
|
||||||
fields := map[string]interface{}{}
|
}
|
||||||
fields["req"] = req
|
|
||||||
|
|
||||||
entry := &entry{
|
|
||||||
fields: fields,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
func (e *logEntry) SetResponse(w http.ResponseWriter, r *http.Request) {
|
||||||
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
|
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
|
||||||
t1 := time.Now()
|
e.res.time = time.Now()
|
||||||
|
e.res.code = ww.Status()
|
||||||
|
e.res.bytes = ww.BytesWritten()
|
||||||
|
|
||||||
defer func() {
|
e.elapsed = e.res.time.Sub(e.req.time)
|
||||||
entry.Write(ww.Status(), ww.BytesWritten(), time.Since(t1))
|
e.session, e.hasSession = auth.GetSession(r)
|
||||||
}()
|
}
|
||||||
|
|
||||||
next.ServeHTTP(ww, r)
|
func (e *logEntry) SetError(err error) {
|
||||||
|
e.err = err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *logEntry) Write() {
|
||||||
|
logger := log.With().
|
||||||
|
Str("module", "http").
|
||||||
|
Float64("elapsed", float64(e.elapsed.Nanoseconds())/1000000.0).
|
||||||
|
Interface("req", e.req).
|
||||||
|
Interface("res", e.res).
|
||||||
|
Logger()
|
||||||
|
|
||||||
|
if e.hasSession {
|
||||||
|
logger = logger.With().Str("session_id", e.session.ID()).Logger()
|
||||||
}
|
}
|
||||||
return http.HandlerFunc(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
type entry struct {
|
if e.err != nil {
|
||||||
fields map[string]interface{}
|
httpErr, ok := e.err.(*utils.HTTPError)
|
||||||
errors []map[string]interface{}
|
if !ok {
|
||||||
}
|
logger.Err(e.err).Msgf("request failed (%d)", e.res.code)
|
||||||
|
return
|
||||||
func (e *entry) Write(status, bytes int, elapsed time.Duration) {
|
|
||||||
res := map[string]interface{}{}
|
|
||||||
res["time"] = time.Now().UTC().Format(time.RFC1123)
|
|
||||||
res["status"] = status
|
|
||||||
res["bytes"] = bytes
|
|
||||||
res["elapsed"] = float64(elapsed.Nanoseconds()) / 1000000.0
|
|
||||||
|
|
||||||
e.fields["res"] = res
|
|
||||||
e.fields["module"] = "http"
|
|
||||||
|
|
||||||
if len(e.errors) > 0 {
|
|
||||||
e.fields["errors"] = e.errors
|
|
||||||
log.Error().Fields(e.fields).Msgf("request failed (%d)", status)
|
|
||||||
} else {
|
|
||||||
log.Debug().Fields(e.fields).Msgf("request complete (%d)", status)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (e *entry) Panic(v interface{}, stack []byte) {
|
if httpErr.Message == "" {
|
||||||
err := map[string]interface{}{}
|
httpErr.Message = http.StatusText(httpErr.Code)
|
||||||
err["message"] = fmt.Sprintf("%+v", v)
|
}
|
||||||
err["stack"] = string(stack)
|
|
||||||
|
|
||||||
e.errors = append(e.errors, err)
|
logger := logger.Error().Err(httpErr.InternalErr)
|
||||||
|
|
||||||
|
message := httpErr.Message
|
||||||
|
if httpErr.InternalMsg != "" {
|
||||||
|
message = httpErr.InternalMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Msgf("request failed (%d): %s", e.res.code, message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug().Msgf("request complete (%d)", e.res.code)
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/go-chi/chi"
|
|
||||||
"github.com/go-chi/chi/middleware"
|
|
||||||
"github.com/go-chi/cors"
|
"github.com/go-chi/cors"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@ -18,16 +16,15 @@ import (
|
|||||||
type HttpManagerCtx struct {
|
type HttpManagerCtx struct {
|
||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
config *config.Server
|
config *config.Server
|
||||||
router *chi.Mux
|
router *RouterCtx
|
||||||
http *http.Server
|
http *http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(WebSocketManager types.WebSocketManager, ApiManager types.ApiManager, config *config.Server) *HttpManagerCtx {
|
func New(WebSocketManager types.WebSocketManager, ApiManager types.ApiManager, config *config.Server) *HttpManagerCtx {
|
||||||
logger := log.With().Str("module", "http").Logger()
|
logger := log.With().Str("module", "http").Logger()
|
||||||
|
|
||||||
router := chi.NewRouter()
|
router := newRouter()
|
||||||
router.Use(middleware.Recoverer) // Recover from panics without crashing server
|
router.UseBypass(cors.Handler(cors.Options{
|
||||||
router.Use(cors.Handler(cors.Options{
|
|
||||||
AllowOriginFunc: func(r *http.Request, origin string) bool {
|
AllowOriginFunc: func(r *http.Request, origin string) bool {
|
||||||
return config.AllowOrigin(origin)
|
return config.AllowOrigin(origin)
|
||||||
},
|
},
|
||||||
@ -37,31 +34,27 @@ func New(WebSocketManager types.WebSocketManager, ApiManager types.ApiManager, c
|
|||||||
AllowCredentials: true,
|
AllowCredentials: true,
|
||||||
MaxAge: 300, // Maximum value not ignored by any of major browsers
|
MaxAge: 300, // Maximum value not ignored by any of major browsers
|
||||||
}))
|
}))
|
||||||
router.Use(middleware.RequestID) // Create a request ID for each request
|
|
||||||
router.Use(Logger) // Log API request calls using custom logger function
|
|
||||||
|
|
||||||
router.Route("/api", ApiManager.Route)
|
router.Route("/api", ApiManager.Route)
|
||||||
|
|
||||||
router.Get("/api/ws", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/api/ws", func(w http.ResponseWriter, r *http.Request) error {
|
||||||
WebSocketManager.Upgrade(w, r, func(r *http.Request) bool {
|
return WebSocketManager.Upgrade(w, r, func(r *http.Request) bool {
|
||||||
return config.AllowOrigin(r.Header.Get("Origin"))
|
return config.AllowOrigin(r.Header.Get("Origin"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
if config.Static != "" {
|
if config.Static != "" {
|
||||||
fs := http.FileServer(http.Dir(config.Static))
|
fs := http.FileServer(http.Dir(config.Static))
|
||||||
router.Get("/*", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/*", func(w http.ResponseWriter, r *http.Request) error {
|
||||||
if _, err := os.Stat(config.Static + r.URL.Path); !os.IsNotExist(err) {
|
_, err := os.Stat(config.Static + r.URL.Path)
|
||||||
|
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
fs.ServeHTTP(w, r)
|
fs.ServeHTTP(w, r)
|
||||||
} else {
|
|
||||||
http.NotFound(w, r)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
router.NotFound(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return err
|
||||||
http.NotFound(w, r)
|
})
|
||||||
}))
|
}
|
||||||
|
|
||||||
return &HttpManagerCtx{
|
return &HttpManagerCtx{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
112
internal/http/router.go
Normal file
112
internal/http/router.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"demodesk/neko/internal/types"
|
||||||
|
"demodesk/neko/internal/utils"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi"
|
||||||
|
"github.com/go-chi/chi/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RouterCtx struct {
|
||||||
|
chi chi.Router
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRouter() *RouterCtx {
|
||||||
|
router := chi.NewRouter()
|
||||||
|
router.Use(middleware.Recoverer) // Recover from panics without crashing server
|
||||||
|
router.Use(middleware.RequestID) // Create a request ID for each request
|
||||||
|
router.Use(LoggerMiddleware)
|
||||||
|
return &RouterCtx{router}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RouterCtx) Group(fn func(types.Router)) {
|
||||||
|
r.chi.Group(func(c chi.Router) {
|
||||||
|
fn(&RouterCtx{c})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RouterCtx) Route(pattern string, fn func(types.Router)) {
|
||||||
|
r.chi.Route(pattern, func(c chi.Router) {
|
||||||
|
fn(&RouterCtx{c})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RouterCtx) Get(pattern string, fn types.RouterHandler) {
|
||||||
|
r.chi.Get(pattern, routeHandler(fn))
|
||||||
|
}
|
||||||
|
func (r *RouterCtx) Post(pattern string, fn types.RouterHandler) {
|
||||||
|
r.chi.Post(pattern, routeHandler(fn))
|
||||||
|
}
|
||||||
|
func (r *RouterCtx) Put(pattern string, fn types.RouterHandler) {
|
||||||
|
r.chi.Put(pattern, routeHandler(fn))
|
||||||
|
}
|
||||||
|
func (r *RouterCtx) Delete(pattern string, fn types.RouterHandler) {
|
||||||
|
r.chi.Delete(pattern, routeHandler(fn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RouterCtx) With(fn types.MiddlewareHandler) types.Router {
|
||||||
|
c := r.chi.With(middlewareHandler(fn))
|
||||||
|
return &RouterCtx{c}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RouterCtx) WithBypass(fn func(next http.Handler) http.Handler) types.Router {
|
||||||
|
c := r.chi.With(fn)
|
||||||
|
return &RouterCtx{c}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RouterCtx) Use(fn types.MiddlewareHandler) {
|
||||||
|
r.chi.Use(middlewareHandler(fn))
|
||||||
|
}
|
||||||
|
func (r *RouterCtx) UseBypass(fn func(next http.Handler) http.Handler) {
|
||||||
|
r.chi.Use(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RouterCtx) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
r.chi.ServeHTTP(w, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorHandler(err error, w http.ResponseWriter, r *http.Request) {
|
||||||
|
httpErr, ok := err.(*utils.HTTPError)
|
||||||
|
if !ok {
|
||||||
|
httpErr = utils.HttpInternalServerError().WithInternalErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.HttpJsonResponse(w, httpErr.Code, httpErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func routeHandler(fn types.RouterHandler) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
logEntry := getLogEntry(r)
|
||||||
|
|
||||||
|
if err := fn(w, r); err != nil {
|
||||||
|
logEntry.SetError(err)
|
||||||
|
errorHandler(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
logEntry.SetResponse(w, r)
|
||||||
|
logEntry.Write()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func middlewareHandler(fn types.MiddlewareHandler) func(http.Handler) http.Handler {
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
logEntry := getLogEntry(r)
|
||||||
|
|
||||||
|
ctx, err := fn(w, r)
|
||||||
|
if err != nil {
|
||||||
|
logEntry.SetError(err)
|
||||||
|
errorHandler(err, w, r)
|
||||||
|
logEntry.SetResponse(w, r)
|
||||||
|
logEntry.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ctx != nil {
|
||||||
|
r = r.WithContext(ctx)
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
28
internal/types/http.go
Normal file
28
internal/types/http.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RouterHandler func(w http.ResponseWriter, r *http.Request) error
|
||||||
|
type MiddlewareHandler func(w http.ResponseWriter, r *http.Request) (context.Context, error)
|
||||||
|
|
||||||
|
type Router interface {
|
||||||
|
Group(fn func(Router))
|
||||||
|
Route(pattern string, fn func(Router))
|
||||||
|
Get(pattern string, fn RouterHandler)
|
||||||
|
Post(pattern string, fn RouterHandler)
|
||||||
|
Put(pattern string, fn RouterHandler)
|
||||||
|
Delete(pattern string, fn RouterHandler)
|
||||||
|
With(fn MiddlewareHandler) Router
|
||||||
|
WithBypass(fn func(next http.Handler) http.Handler) Router
|
||||||
|
Use(fn MiddlewareHandler)
|
||||||
|
UseBypass(fn func(next http.Handler) http.Handler)
|
||||||
|
ServeHTTP(w http.ResponseWriter, req *http.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HttpManager interface {
|
||||||
|
Start()
|
||||||
|
Shutdown() error
|
||||||
|
}
|
@ -9,18 +9,18 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HttpJsonRequest(w http.ResponseWriter, r *http.Request, res interface{}) bool {
|
func HttpJsonRequest(w http.ResponseWriter, r *http.Request, res interface{}) error {
|
||||||
if err := json.NewDecoder(r.Body).Decode(res); err != nil {
|
err := json.NewDecoder(r.Body).Decode(res)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
HttpBadRequest(w).WithInternalErr(err).Msg("no data provided")
|
return HttpBadRequest("no data provided").WithInternalErr(err)
|
||||||
} else {
|
|
||||||
HttpBadRequest(w).WithInternalErr(err).Msg("unable to parse provided data")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return HttpBadRequest("unable to parse provided data").WithInternalErr(err)
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpJsonResponse(w http.ResponseWriter, code int, res interface{}) {
|
func HttpJsonResponse(w http.ResponseWriter, code int, res interface{}) {
|
||||||
@ -32,12 +32,14 @@ func HttpJsonResponse(w http.ResponseWriter, code int, res interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpSuccess(w http.ResponseWriter, res ...interface{}) {
|
func HttpSuccess(w http.ResponseWriter, res ...interface{}) error {
|
||||||
if len(res) == 0 {
|
if len(res) == 0 {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
} else {
|
} else {
|
||||||
HttpJsonResponse(w, http.StatusOK, res[0])
|
HttpJsonResponse(w, http.StatusOK, res[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPError is an error with a message and an HTTP status code.
|
// HTTPError is an error with a message and an HTTP status code.
|
||||||
@ -47,8 +49,6 @@ type HTTPError struct {
|
|||||||
|
|
||||||
InternalErr error `json:"-"`
|
InternalErr error `json:"-"`
|
||||||
InternalMsg string `json:"-"`
|
InternalMsg string `json:"-"`
|
||||||
|
|
||||||
w http.ResponseWriter `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HTTPError) Error() string {
|
func (e *HTTPError) Error() string {
|
||||||
@ -84,64 +84,50 @@ func (e *HTTPError) WithInternalMsgf(fmtStr string, args ...interface{}) *HTTPEr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sends error with custom formated message
|
// Sends error with custom formated message
|
||||||
func (e *HTTPError) Msgf(fmtSt string, args ...interface{}) {
|
func (e *HTTPError) Msgf(fmtSt string, args ...interface{}) *HTTPError {
|
||||||
e.Message = fmt.Sprintf(fmtSt, args...)
|
e.Message = fmt.Sprintf(fmtSt, args...)
|
||||||
e.Send()
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends error with custom message
|
// Sends error with custom message
|
||||||
func (e *HTTPError) Msg(str string) {
|
func (e *HTTPError) Msg(str string) *HTTPError {
|
||||||
e.Message = str
|
e.Message = str
|
||||||
e.Send()
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends error with default status text
|
func HttpError(code int, res ...string) *HTTPError {
|
||||||
func (e *HTTPError) Send() {
|
err := &HTTPError{
|
||||||
if e.Message == "" {
|
|
||||||
e.Message = http.StatusText(e.Code)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger := log.Error().
|
|
||||||
Err(e.InternalErr).
|
|
||||||
Str("module", "http").
|
|
||||||
Int("code", e.Code)
|
|
||||||
|
|
||||||
message := e.Message
|
|
||||||
if e.InternalMsg != "" {
|
|
||||||
message = e.InternalMsg
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Msg(message)
|
|
||||||
HttpJsonResponse(e.w, e.Code, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
func HttpError(w http.ResponseWriter, code int) *HTTPError {
|
|
||||||
return &HTTPError{
|
|
||||||
Code: code,
|
Code: code,
|
||||||
w: w,
|
Message: http.StatusText(code),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(res) == 1 {
|
||||||
|
err.Message = res[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpBadRequest(w http.ResponseWriter) *HTTPError {
|
func HttpBadRequest(res ...string) *HTTPError {
|
||||||
return HttpError(w, http.StatusBadRequest)
|
return HttpError(http.StatusBadRequest, res...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpUnauthorized(w http.ResponseWriter) *HTTPError {
|
func HttpUnauthorized(res ...string) *HTTPError {
|
||||||
return HttpError(w, http.StatusUnauthorized)
|
return HttpError(http.StatusUnauthorized, res...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpForbidden(w http.ResponseWriter) *HTTPError {
|
func HttpForbidden(res ...string) *HTTPError {
|
||||||
return HttpError(w, http.StatusForbidden)
|
return HttpError(http.StatusForbidden, res...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpNotFound(w http.ResponseWriter) *HTTPError {
|
func HttpNotFound(res ...string) *HTTPError {
|
||||||
return HttpError(w, http.StatusNotFound)
|
return HttpError(http.StatusNotFound, res...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpUnprocessableEntity(w http.ResponseWriter) *HTTPError {
|
func HttpUnprocessableEntity(res ...string) *HTTPError {
|
||||||
return HttpError(w, http.StatusUnprocessableEntity)
|
return HttpError(http.StatusUnprocessableEntity, res...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpInternalServerError(w http.ResponseWriter, err error) *HTTPError {
|
func HttpInternalServerError(res ...string) *HTTPError {
|
||||||
return HttpError(w, http.StatusInternalServerError).WithInternalErr(err)
|
return HttpError(http.StatusInternalServerError, res...)
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ func (manager *WebSocketManagerCtx) AddHandler(handler types.WebSocketHandler) {
|
|||||||
manager.handlers = append(manager.handlers, handler)
|
manager.handlers = append(manager.handlers, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Request, checkOrigin types.CheckOrigin) {
|
func (manager *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Request, checkOrigin types.CheckOrigin) error {
|
||||||
manager.logger.Debug().
|
manager.logger.Debug().
|
||||||
Str("address", r.RemoteAddr).
|
Str("address", r.RemoteAddr).
|
||||||
Str("agent", r.UserAgent()).
|
Str("agent", r.UserAgent()).
|
||||||
@ -157,8 +157,7 @@ func (manager *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Reque
|
|||||||
|
|
||||||
connection, err := upgrader.Upgrade(w, r, nil)
|
connection, err := upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
manager.logger.Err(err).Msg("failed to upgrade connection")
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new peer
|
// create new peer
|
||||||
@ -168,7 +167,7 @@ func (manager *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Reque
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
manager.logger.Warn().Err(err).Msg("authentication failed")
|
manager.logger.Warn().Err(err).Msg("authentication failed")
|
||||||
peer.Destroy(err.Error())
|
peer.Destroy(err.Error())
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// add session id to all log messages
|
// add session id to all log messages
|
||||||
@ -178,7 +177,7 @@ func (manager *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Reque
|
|||||||
if !session.Profile().CanConnect {
|
if !session.Profile().CanConnect {
|
||||||
logger.Warn().Msg("connection disabled")
|
logger.Warn().Msg("connection disabled")
|
||||||
peer.Destroy("connection disabled")
|
peer.Destroy("connection disabled")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.State().IsConnected {
|
if session.State().IsConnected {
|
||||||
@ -186,7 +185,7 @@ func (manager *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Reque
|
|||||||
|
|
||||||
if !manager.sessions.MercifulReconnect() {
|
if !manager.sessions.MercifulReconnect() {
|
||||||
peer.Destroy("already connected")
|
peer.Destroy("already connected")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info().Msg("replacing peer connection")
|
logger.Info().Msg("replacing peer connection")
|
||||||
@ -211,6 +210,7 @@ func (manager *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Reque
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
manager.handle(connection, session)
|
manager.handle(connection, session)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *WebSocketManagerCtx) handle(connection *websocket.Conn, session types.Session) {
|
func (manager *WebSocketManagerCtx) handle(connection *websocket.Conn, session types.Session) {
|
||||||
|
Loading…
Reference in New Issue
Block a user