initial commit 2
This commit is contained in:
25
server/serverconfig/auth.go
Normal file
25
server/serverconfig/auth.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/auth"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
func setJWTMiddleware(e *echo.Echo, cfg *config.Config) error {
|
||||
key, err := auth.GetCertPublicKey(cfg.HTTP.Auth.CertificatePath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
|
||||
e.Pre(middlewareErrorWrapper(middleware.JWTWithConfig(middleware.JWTConfig{
|
||||
TokenLookup: "header:" + auth.AppTokenHeaderName,
|
||||
Skipper: authSkipper,
|
||||
SigningKey: key,
|
||||
SigningMethod: auth.TokenSigningMethod.Name,
|
||||
})))
|
||||
|
||||
return nil
|
||||
}
|
||||
93
server/serverconfig/authorization.go
Normal file
93
server/serverconfig/authorization.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
|
||||
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/auth"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/logger"
|
||||
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
||||
"github.com/casbin/casbin"
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
// Config defines the config for CasbinAuth middleware.
|
||||
Config struct {
|
||||
// Skipper defines a function to skip middleware.
|
||||
Skipper middleware.Skipper
|
||||
|
||||
// Enforcer CasbinAuth main rule.
|
||||
// Required.
|
||||
Enforcer *casbin.Enforcer
|
||||
|
||||
Application *config.Config
|
||||
|
||||
Svc *applicationservice.Service
|
||||
Logger *logger.Logger
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultConfig is the default CasbinAuth middleware config.
|
||||
DefaultConfig = Config{
|
||||
Skipper: middleware.DefaultSkipper,
|
||||
}
|
||||
)
|
||||
|
||||
// MiddlewareWithConfig returns a CasbinAuth middleware with config.
|
||||
// See `Middleware()`.
|
||||
func MiddlewareWithConfig(cfg *config.Config, svc *applicationservice.Service, log *logger.Logger) echo.MiddlewareFunc {
|
||||
|
||||
config := &DefaultConfig
|
||||
|
||||
config.Svc = svc
|
||||
config.Logger = log
|
||||
config.Application = cfg
|
||||
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
if config.Skipper(c) || config.CheckPermission(c) {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
return routeutils.HandleHTMLError(c, echo.ErrForbidden)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setAuthorizationMiddleware(e *echo.Echo, log *logger.Logger, cfg *config.Config, svc *applicationservice.Service) {
|
||||
e.Use(MiddlewareWithConfig(cfg, svc, log))
|
||||
}
|
||||
|
||||
// CheckPermission checks the user/method/path combination from the request.
|
||||
// Returns true (permission granted) or false (permission forbidden)
|
||||
func (a *Config) CheckPermission(c echo.Context) bool {
|
||||
user, err := auth.GetUserDetail(c, a.Application)
|
||||
if err != nil {
|
||||
a.Logger.Warningf("Cannot get user details. %v ", err)
|
||||
}
|
||||
method := c.Request().Method
|
||||
path := c.Request().URL.Path
|
||||
//objectOrganization := a.organizationGoverningObject(c, user)
|
||||
|
||||
return a.Enforcer.Enforce(user, path, method)
|
||||
}
|
||||
|
||||
func (a *Config) organizationGoverningObject(c echo.Context, userDetails viewmodel.User) (result viewmodel.Organization) {
|
||||
|
||||
existingUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) > 0
|
||||
newUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) <= 0
|
||||
|
||||
switch {
|
||||
case existingUser:
|
||||
user, _ := a.Svc.Users.GetByUUID(c.ParamValues()[0], "")
|
||||
result = user.Organizations[0]
|
||||
case newUser:
|
||||
result = userDetails.Organizations[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
11
server/serverconfig/authorization_model.conf
Normal file
11
server/serverconfig/authorization_model.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
[request_definition]
|
||||
r = role, obj, act
|
||||
|
||||
[policy_definition]
|
||||
p = role, obj, act
|
||||
|
||||
[policy_effect]
|
||||
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
|
||||
|
||||
[matchers]
|
||||
m = keymatch(r.role, p.role) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")
|
||||
10
server/serverconfig/bodylimit.go
Normal file
10
server/serverconfig/bodylimit.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
func setBodyLimitMiddleware(e *echo.Echo) {
|
||||
e.Use(middleware.BodyLimit("4M"))
|
||||
}
|
||||
204
server/serverconfig/cache.go
Normal file
204
server/serverconfig/cache.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"time"
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/cache"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
// bodyResponseWriter implements the http.ResponseWriter interface
|
||||
type bodyResponseWriter struct {
|
||||
io.Writer
|
||||
http.ResponseWriter
|
||||
}
|
||||
|
||||
func (w *bodyResponseWriter) WriteHeader(code int) {
|
||||
w.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
func (w *bodyResponseWriter) Write(b []byte) (int, error) {
|
||||
return w.Writer.Write(b)
|
||||
}
|
||||
|
||||
func (w *bodyResponseWriter) Flush() {
|
||||
w.ResponseWriter.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
func (w *bodyResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
return w.ResponseWriter.(http.Hijacker).Hijack()
|
||||
}
|
||||
|
||||
func (w *bodyResponseWriter) CloseNotify() <-chan bool {
|
||||
return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
|
||||
}
|
||||
|
||||
// CacheConfig defines the config for Cache middleware.
|
||||
type CacheConfig struct {
|
||||
// Skipper determines if the request should skip this middleware
|
||||
Skipper middleware.Skipper
|
||||
// Cache expiration/lifetime
|
||||
Expiration time.Duration
|
||||
// VaryByQuery contains a list of query parameters to include in cache key
|
||||
VaryByQuery []string
|
||||
}
|
||||
|
||||
// DefaultCacheConfig is the default Cache middleware config.
|
||||
var DefaultCacheConfig = CacheConfig{
|
||||
Skipper: middleware.DefaultSkipper,
|
||||
}
|
||||
|
||||
// CacheMiddleware returns a middleware that protects requests agains Cache attacks.
|
||||
func CacheMiddleware(cfg *config.Config) echo.MiddlewareFunc {
|
||||
config := DefaultCacheConfig
|
||||
config.Expiration = cfg.Cache.DefaultExpiration
|
||||
|
||||
return CacheMiddlewareWithConfig(cfg, config)
|
||||
}
|
||||
|
||||
// CacheMiddlewareWithConfig returns a Cache middleware with config.
|
||||
// See: `CacheMiddleware()`.
|
||||
func CacheMiddlewareWithConfig(cfg *config.Config, config CacheConfig) echo.MiddlewareFunc {
|
||||
if config.Skipper == nil {
|
||||
config.Skipper = DefaultCacheConfig.Skipper
|
||||
}
|
||||
|
||||
if config.Expiration < 0 {
|
||||
config.Expiration = cfg.Cache.DefaultExpiration
|
||||
}
|
||||
|
||||
cache := cache.Instance(cfg)
|
||||
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
req := c.Request()
|
||||
|
||||
skip := config.Skipper(c) || req.Method != echo.GET
|
||||
|
||||
if !skip {
|
||||
for _, val := range req.Header["Cache-Control"] {
|
||||
if val == "no-cache" {
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if skip {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
res := c.Response()
|
||||
|
||||
var cacheKey = getCacheKey(c, config)
|
||||
var contentTypeCacheKey = fmt.Sprintf("%s-content-type", cacheKey)
|
||||
var contentType = "application/json"
|
||||
|
||||
output, err := cache.GetItem(cacheKey)
|
||||
if err == nil {
|
||||
var responseStatus = http.StatusOK
|
||||
|
||||
if len(output) == 0 {
|
||||
responseStatus = http.StatusNoContent
|
||||
}
|
||||
|
||||
contentType, err = cache.GetString(contentTypeCacheKey)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(c, err)
|
||||
}
|
||||
|
||||
expiration, err := cache.GetExpiration(cacheKey)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(c, err)
|
||||
}
|
||||
|
||||
if expiration > 0 {
|
||||
res.Header()["Cache-Control"] = []string{fmt.Sprintf("max-age=%v", expiration.Seconds())}
|
||||
}
|
||||
|
||||
return c.Blob(responseStatus, contentType, []byte(output))
|
||||
} else if err == domain.ErrCacheMiss {
|
||||
resBody := new(bytes.Buffer)
|
||||
|
||||
mw := io.MultiWriter(res.Writer, resBody)
|
||||
|
||||
writer := &bodyResponseWriter{Writer: mw, ResponseWriter: res.Writer}
|
||||
|
||||
res.Writer = writer
|
||||
|
||||
err = next(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headers := writer.Header()
|
||||
|
||||
cache.SetExpiration(cacheKey, config.Expiration)
|
||||
|
||||
if config.Expiration != 0 {
|
||||
res.Header()["Cache-Control"] = []string{fmt.Sprintf("max-age=%v", config.Expiration.Seconds())}
|
||||
}
|
||||
|
||||
contentTypeHeader, ok := headers[echo.HeaderContentType]
|
||||
if ok {
|
||||
contentType = contentTypeHeader[0]
|
||||
}
|
||||
|
||||
err = cache.SetItem(cacheKey, resBody.Bytes())
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(c, err)
|
||||
}
|
||||
err = cache.SetString(contentTypeCacheKey, contentType)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(c, err)
|
||||
}
|
||||
} else if err != nil {
|
||||
return routeutils.HandleAPIError(c, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getCacheKey(c echo.Context, config CacheConfig) string {
|
||||
var req = c.Request()
|
||||
|
||||
var re = regexp.MustCompile("(?i)[^a-z0-9_]+")
|
||||
|
||||
var key = req.URL.Path
|
||||
|
||||
if len(config.VaryByQuery) > 0 {
|
||||
var query = "q"
|
||||
|
||||
for _, queryKey := range config.VaryByQuery {
|
||||
for k, v := range req.URL.Query() {
|
||||
if k == queryKey {
|
||||
query = fmt.Sprintf("%s-%s-%s", query, k, v)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query = strings.Trim(re.ReplaceAllString(query, "-"), "-")
|
||||
|
||||
if strings.TrimSpace(query) != "" {
|
||||
key = fmt.Sprintf("%s-%v", key, query)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Trim(re.ReplaceAllString(key, "-"), "-")
|
||||
}
|
||||
17
server/serverconfig/cors.go
Normal file
17
server/serverconfig/cors.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
func setCORSMiddleware(e *echo.Echo, cfg *config.Config) {
|
||||
middlewareConfig := middleware.DefaultCORSConfig
|
||||
|
||||
if !cfg.App.Debug {
|
||||
middlewareConfig.AllowOrigins = cfg.HTTP.Auth.FrontendURLs
|
||||
}
|
||||
|
||||
e.Pre(middleware.CORSWithConfig(middlewareConfig))
|
||||
}
|
||||
10
server/serverconfig/gzip.go
Normal file
10
server/serverconfig/gzip.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
func setGZIPMiddleware(e *echo.Echo) {
|
||||
e.Use(middleware.Gzip())
|
||||
}
|
||||
151
server/serverconfig/log.go
Normal file
151
server/serverconfig/log.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/logger"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/gommon/log"
|
||||
)
|
||||
|
||||
type echoLogger struct {
|
||||
*logger.Logger
|
||||
}
|
||||
|
||||
// Printj prints a message in json format
|
||||
func (l *echoLogger) Printj(data log.JSON) {
|
||||
bytes, _ := json.Marshal(data)
|
||||
l.Logger.Print(string(bytes))
|
||||
}
|
||||
|
||||
// Debugj logs a debug message in json format
|
||||
func (l *echoLogger) Debugj(data log.JSON) {
|
||||
bytes, _ := json.Marshal(data)
|
||||
l.Logger.Debug(string(bytes))
|
||||
}
|
||||
|
||||
// Infoj logs an info message in json format
|
||||
func (l *echoLogger) Infoj(data log.JSON) {
|
||||
bytes, _ := json.Marshal(data)
|
||||
l.Logger.Info(string(bytes))
|
||||
}
|
||||
|
||||
// Warnj logs a warning message in json format
|
||||
func (l *echoLogger) Warnj(data log.JSON) {
|
||||
bytes, _ := json.Marshal(data)
|
||||
l.Logger.Warn(string(bytes))
|
||||
}
|
||||
|
||||
// Errorj logs an error message in json format
|
||||
func (l *echoLogger) Errorj(data log.JSON) {
|
||||
bytes, _ := json.Marshal(data)
|
||||
l.Logger.Error(string(bytes))
|
||||
}
|
||||
|
||||
// Panicj logs a panic message in json format
|
||||
func (l *echoLogger) Panicj(data log.JSON) {
|
||||
bytes, _ := json.Marshal(data)
|
||||
l.Logger.Panic(string(bytes))
|
||||
}
|
||||
|
||||
// Fatalj logs a fatal message in json format
|
||||
func (l *echoLogger) Fatalj(data log.JSON) {
|
||||
bytes, _ := json.Marshal(data)
|
||||
l.Logger.Fatal(string(bytes))
|
||||
}
|
||||
|
||||
// Level returns the echo logging level
|
||||
func (l *echoLogger) Level() log.Lvl {
|
||||
return log.Lvl(l.Logger.Level)
|
||||
}
|
||||
|
||||
// SetLevel sets the echo logging level
|
||||
func (l *echoLogger) SetLevel(level log.Lvl) {
|
||||
l.Logger.Level = logrus.Level(level)
|
||||
}
|
||||
|
||||
// Output returns the echo logging output
|
||||
func (l *echoLogger) Output() io.Writer {
|
||||
return l.Writer()
|
||||
}
|
||||
|
||||
// SetOutput sets the echo logging output
|
||||
func (l *echoLogger) SetOutput(output io.Writer) {
|
||||
l.Logger.Logger.Out = output
|
||||
}
|
||||
|
||||
// Prefix returns the echo logging output
|
||||
func (l *echoLogger) Prefix() string {
|
||||
return l.Logger.Data["app"].(string)
|
||||
}
|
||||
|
||||
// SetPrefix returns the echo logging output
|
||||
func (l *echoLogger) SetPrefix(prefix string) {
|
||||
l.Logger.Data["app"] = prefix
|
||||
}
|
||||
|
||||
func loggerMiddlewareHandler(c echo.Context, next echo.HandlerFunc, log *logger.Logger) error {
|
||||
req := c.Request()
|
||||
res := c.Response()
|
||||
start := time.Now()
|
||||
|
||||
err := next(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stop := time.Now()
|
||||
|
||||
p := req.URL.Path
|
||||
if p == "" {
|
||||
p = "/"
|
||||
}
|
||||
|
||||
bytesIn := req.Header.Get(echo.HeaderContentLength)
|
||||
if bytesIn == "" {
|
||||
bytesIn = "0"
|
||||
}
|
||||
|
||||
requestID := req.Header.Get(echo.HeaderXRequestID)
|
||||
|
||||
if requestID == "" {
|
||||
requestID = res.Header().Get(echo.HeaderXRequestID)
|
||||
}
|
||||
|
||||
log.WithFields(map[string]interface{}{
|
||||
"id": requestID,
|
||||
"time_rfc3339": time.Now().Format(time.RFC3339),
|
||||
"remote_ip": c.RealIP(),
|
||||
"host": req.Host,
|
||||
"uri": req.RequestURI,
|
||||
"method": req.Method,
|
||||
"path": p,
|
||||
"referer": req.Referer(),
|
||||
"user_agent": req.UserAgent(),
|
||||
"status": res.Status,
|
||||
"latency": strconv.FormatInt(stop.Sub(start).Nanoseconds()/1000, 10),
|
||||
"latency_human": stop.Sub(start).String(),
|
||||
"bytes_in": bytesIn,
|
||||
"bytes_out": strconv.FormatInt(res.Size, 10),
|
||||
"headers": req.Header,
|
||||
"query": req.URL.Query(),
|
||||
}).Info("Handled request")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loggerMiddleware(log *logger.Logger) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
return loggerMiddlewareHandler(c, next, log)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setLogMiddleware(e *echo.Echo, log *logger.Logger) {
|
||||
e.Logger = &echoLogger{log}
|
||||
e.Pre(loggerMiddleware(log))
|
||||
}
|
||||
73
server/serverconfig/ratelimit.go
Normal file
73
server/serverconfig/ratelimit.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
// RateLimitMiddlewareConfig defines the config for RateLimit middleware.
|
||||
type RateLimitMiddlewareConfig struct {
|
||||
Skipper middleware.Skipper
|
||||
// Max number of allowed requests on a timeframe
|
||||
MaxRequests int64
|
||||
// The timeframe duration for the requests count
|
||||
BucketDuration time.Duration
|
||||
// Error response message
|
||||
ResponseMessage string
|
||||
// Error response
|
||||
ResponseStatus int
|
||||
}
|
||||
|
||||
// DefaultRateLimitMiddlewareConfig is the default RateLimit middleware config.
|
||||
var DefaultRateLimitMiddlewareConfig = RateLimitMiddlewareConfig{
|
||||
Skipper: middleware.DefaultSkipper,
|
||||
MaxRequests: 10,
|
||||
BucketDuration: time.Second,
|
||||
ResponseMessage: "Too Many Requests",
|
||||
ResponseStatus: http.StatusServiceUnavailable,
|
||||
}
|
||||
|
||||
// RateLimitMiddleware returns a middleware that protects the API agains massive requests.
|
||||
func RateLimitMiddleware() echo.MiddlewareFunc {
|
||||
return RateLimitMiddlewareWithConfig(DefaultRateLimitMiddlewareConfig)
|
||||
}
|
||||
|
||||
// RateLimitMiddlewareWithConfig returns a RateLimitMiddleware with configuration parameters.
|
||||
// See: `RateLimitMiddleware()`.
|
||||
func RateLimitMiddlewareWithConfig(config RateLimitMiddlewareConfig) echo.MiddlewareFunc {
|
||||
if config.MaxRequests == 0 {
|
||||
config.MaxRequests = DefaultRateLimitMiddlewareConfig.MaxRequests
|
||||
}
|
||||
|
||||
if config.BucketDuration == 0 {
|
||||
config.BucketDuration = DefaultRateLimitMiddlewareConfig.BucketDuration
|
||||
}
|
||||
|
||||
// limiter := tollbooth.NewLimiterExpiringBuckets(config.MaxRequests, config.BucketDuration, time.Hour, time.Second*0)
|
||||
// limiter.Message = config.ResponseMessage
|
||||
// limiter.StatusCode = config.ResponseStatus
|
||||
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
if config.Skipper(c) {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
// err := tollbooth.LimitByRequest(limiter, c.Request())
|
||||
// if err != nil {
|
||||
// tollbooth.SetResponseHeaders(limiter, c.Response().Writer)
|
||||
// return errors.NewHTTPError(limiter.StatusCode, limiter.Message)
|
||||
// }
|
||||
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setRateLimitMiddleware(e *echo.Echo) {
|
||||
e.Pre(RateLimitMiddleware())
|
||||
}
|
||||
10
server/serverconfig/recover.go
Normal file
10
server/serverconfig/recover.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
func setRecoverMiddleware(e *echo.Echo) {
|
||||
e.Use(middleware.Recover())
|
||||
}
|
||||
10
server/serverconfig/requestid.go
Normal file
10
server/serverconfig/requestid.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
func setRequestIDMiddleware(e *echo.Echo) {
|
||||
e.Use(middleware.RequestID())
|
||||
}
|
||||
15
server/serverconfig/route.go
Normal file
15
server/serverconfig/route.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
func setRouteMiddleware(e *echo.Echo) {
|
||||
middlewareConfig := middleware.DefaultTrailingSlashConfig
|
||||
middlewareConfig.RedirectCode = http.StatusPermanentRedirect
|
||||
|
||||
e.Use(middleware.AddTrailingSlashWithConfig(middlewareConfig))
|
||||
}
|
||||
28
server/serverconfig/serverconfig.go
Normal file
28
server/serverconfig/serverconfig.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/logger"
|
||||
"github.com/labstack/echo"
|
||||
)
|
||||
|
||||
// SetMiddlewares attaches middlewares to server
|
||||
func SetMiddlewares(server *echo.Echo, cfg *config.Config, log *logger.Logger, svc *service.Service) error {
|
||||
setRecoverMiddleware(server)
|
||||
setGZIPMiddleware(server)
|
||||
setRequestIDMiddleware(server)
|
||||
setLogMiddleware(server, log)
|
||||
setCORSMiddleware(server, cfg)
|
||||
setBodyLimitMiddleware(server)
|
||||
setRateLimitMiddleware(server)
|
||||
//setAuthorizationMiddleware(server, log, svc)
|
||||
|
||||
err := setJWTMiddleware(server, cfg)
|
||||
if err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
50
server/serverconfig/util.go
Normal file
50
server/serverconfig/util.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package serverconfig
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
||||
"github.com/labstack/echo"
|
||||
)
|
||||
|
||||
// authSkipper is the default skipper for authentication and authorization
|
||||
func authSkipper(ctx echo.Context) bool {
|
||||
path := ctx.Request().URL.Path
|
||||
return (strings.HasPrefix(path, "/health") ||
|
||||
strings.HasPrefix(path, "/v1/authenticate") ||
|
||||
strings.HasPrefix(path, "/v1/docs") ||
|
||||
strings.HasPrefix(path, "/v1/twilio") ||
|
||||
strings.HasPrefix(path, "/v1/twilio/ws") ||
|
||||
strings.Contains(path, "/v1/ext") ||
|
||||
strings.Contains(path, "/v1/notification/ws") ||
|
||||
strings.HasPrefix(path, "/v1/lyfthook") ||
|
||||
strings.HasPrefix(path, "/v1/docs"))
|
||||
}
|
||||
|
||||
// appSkipper is the default skipper for the application routes
|
||||
func appSkipper(ctx echo.Context) bool {
|
||||
path := ctx.Request().URL.Path
|
||||
return strings.HasPrefix(path, "/v1/twilio")
|
||||
}
|
||||
|
||||
// docsSkipper is the default skipper for documentation
|
||||
func docsSkipper(ctx echo.Context) bool {
|
||||
path := ctx.Request().URL.Path
|
||||
return strings.HasPrefix(path, "/v1/docs")
|
||||
}
|
||||
|
||||
// middlewareErrorWrapper wraps a middleware and applies the default error handling to response
|
||||
func middlewareErrorWrapper(middleware echo.MiddlewareFunc) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
handlerFunc := middleware(next)
|
||||
|
||||
return func(c echo.Context) error {
|
||||
err := handlerFunc(c)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(c, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user