1
0
Fork 0
dwelling-upload/pkg/server/http.go

98 lines
2.3 KiB
Go

package server
import (
"context"
"crypto/subtle"
"encoding/json"
"log"
"net"
"net/http"
"time"
"github.com/julienschmidt/httprouter"
)
type HttpServer struct {
server *http.Server
router *httprouter.Router
}
func NewHttpServer() *HttpServer {
r := httprouter.New()
return &HttpServer{
server: &http.Server{
ReadTimeout: 3 * time.Second,
WriteTimeout: 3 * time.Second,
Handler: r,
},
router: r,
}
}
func (s *HttpServer) GET(path string, handler http.HandlerFunc) {
s.router.Handler(http.MethodGet, path, handler)
}
func (s *HttpServer) POST(path string, handler http.HandlerFunc) {
s.router.Handler(http.MethodPost, path, handler)
}
func (s *HttpServer) PATCH(path string, handler http.HandlerFunc) {
s.router.Handler(http.MethodPatch, path, handler)
}
func (s *HttpServer) PUT(path string, handler http.HandlerFunc) {
s.router.Handler(http.MethodPut, path, handler)
}
func (s *HttpServer) DELETE(path string, handler http.HandlerFunc) {
s.router.Handler(http.MethodDelete, path, handler)
}
// GetURLParams wrapper around underlying router for getting URL parameters.
func GetURLParams(r *http.Request) httprouter.Params {
return httprouter.ParamsFromContext(r.Context())
}
func (s *HttpServer) Start(network, address string) error {
listener, err := net.Listen(network, address)
if err != nil {
return err
}
go func() {
if err = s.server.Serve(listener); err != nil && err != http.ErrServerClosed {
log.Fatalln(err)
}
}()
return nil
}
func (s *HttpServer) Stop() error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := s.server.Shutdown(ctx); err != nil {
return err
}
return nil
}
// AuthWithToken middleware that authenticates user by token (that is effectively just a password)
// supplied in an 'Authentication-Token' HTTP header.
func AuthWithToken(handler http.HandlerFunc, token string) http.HandlerFunc {
return func(rw http.ResponseWriter, r *http.Request) {
if subtle.ConstantTimeCompare([]byte(r.Header.Get("Authentication-Token")), []byte(token)) == 1 {
handler(rw, r)
} else {
rw.WriteHeader(http.StatusUnauthorized)
rw.Header().Add("Content-Type", "application/json")
response := make(map[string]string)
response["message"] = "Unauthorized"
json.NewEncoder(rw).Encode(response)
}
}
}