Add support for Ratelimiting
continuous-integration/drone/tag Build is passing Details

master v0.3.5
René Jochum 2 years ago
parent 2d74bf6375
commit febbd416a1
Signed by: jochum
GPG Key ID: F7D906F5E51E8E5E

@ -85,7 +85,7 @@ import (
"jochum.dev/jo-micro/router"
"github.com/urfave/cli/v2"
"go-micro.dev/v4"
"wz2100.net/microlobby/shared/proto/authservicepb/v1"
"jochum.dev/jo-micro/auth2/internal/proto/authpb"
)
func main() {
@ -95,52 +95,59 @@ func main() {
micro.Action(func(c *cli.Context) error {
s := service.Server()
r := router.NewHandler(
config.RouterURI,
router.NewRoute(
router.Method(router.MethodGet),
router.Path("/"),
router.Endpoint(authservicepb.AuthV1Service.UserList),
router.Params("limit", "offset"),
router.AuthRequired(),
),
router.NewRoute(
router.Method(router.MethodPost),
router.Path("/login"),
router.Endpoint(authservicepb.AuthV1Service.Login),
),
router.NewRoute(
router.Method(router.MethodPost),
router.Path("/register"),
router.Endpoint(authservicepb.AuthV1Service.Register),
),
router.NewRoute(
router.Method(router.MethodPost),
router.Path("/refresh"),
router.Endpoint(authservicepb.AuthV1Service.Refresh),
),
router.NewRoute(
router.Method(router.MethodDelete),
router.Path("/:userId"),
router.Endpoint(authservicepb.AuthV1Service.UserDelete),
router.Params("userId"),
router.AuthRequired(),
),
router.NewRoute(
router.Method(router.MethodGet),
router.Path("/:userId"),
router.Endpoint(authservicepb.AuthV1Service.UserDetail),
router.Params("userId"),
router.AuthRequired(),
),
router.NewRoute(
router.Method(router.MethodPut),
router.Path("/:userId/roles"),
router.Endpoint(authservicepb.AuthV1Service.UserUpdateRoles),
router.Params("userId"),
router.AuthRequired(),
),
"api/auth/v1",
router.NewRoute(
router.Method(router.MethodGet),
router.Path("/"),
router.Endpoint(authpb.AuthService.List),
router.Params("limit", "offset"),
router.AuthRequired(),
router.RatelimitClientIP("1-M"),
),
router.NewRoute(
router.Method(router.MethodPost),
router.Path("/login"),
router.Endpoint(authpb.AuthService.Login),
router.RatelimitClientIP("10-M", "30-H", "100-D"),
),
router.NewRoute(
router.Method(router.MethodPost),
router.Path("/register"),
router.Endpoint(authpb.AuthService.Register),
router.RatelimitClientIP("1-M", "10-H", "50-D"),
),
router.NewRoute(
router.Method(router.MethodPost),
router.Path("/refresh"),
router.Endpoint(authpb.AuthService.Refresh),
router.RatelimitClientIP("1-M", "10-H", "50-D"),
),
router.NewRoute(
router.Method(router.MethodDelete),
router.Path("/:userId"),
router.Endpoint(authpb.AuthService.Delete),
router.Params("userId"),
router.AuthRequired(),
router.RatelimitClientIP("10-M"),
),
router.NewRoute(
router.Method(router.MethodGet),
router.Path("/:userId"),
router.Endpoint(authpb.AuthService.Detail),
router.Params("userId"),
router.AuthRequired(),
router.RatelimitClientIP("100-M"),
),
router.NewRoute(
router.Method(router.MethodPut),
router.Path("/:userId/roles"),
router.Endpoint(authpb.AuthService.UpdateRoles),
router.Params("userId"),
router.AuthRequired(),
router.RatelimitClientIP("1-M"),
),
)
r.RegisterWithServer(s)
r.RegisterWithServer(srv.Server())
}
)
}

@ -7,8 +7,14 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"time"
libredis "github.com/go-redis/redis/v8"
limiter "github.com/ulule/limiter/v3"
sredis "github.com/ulule/limiter/v3/drivers/store/redis"
"github.com/gin-gonic/gin"
"go-micro.dev/v4"
"go-micro.dev/v4/client"
@ -32,6 +38,7 @@ type Handler struct {
engine *gin.Engine
routerAuth auth2.RouterPlugin
routes map[string]*routerclientpb.RoutesReply_Route
rlStore limiter.Store
}
func NewHandler() (*Handler, error) {
@ -40,12 +47,31 @@ func NewHandler() (*Handler, error) {
}, nil
}
func (h *Handler) Init(service micro.Service, engine *gin.Engine, routerAuth auth2.RouterPlugin, refreshSeconds int) error {
func (h *Handler) Init(service micro.Service, engine *gin.Engine, routerAuth auth2.RouterPlugin, refreshSeconds int, rlStoreURL string) error {
h.service = service
h.engine = engine
h.routerAuth = routerAuth
globalGroup := h.engine.Group("")
if rlStoreURL != "" {
// Create a redis client.
option, err := libredis.ParseURL(rlStoreURL)
if err != nil {
return err
}
client := libredis.NewClient(option)
// Create a store with the redis client.
store, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{
Prefix: "rl",
MaxRetry: 10,
})
if err != nil {
return err
}
h.rlStore = store
}
// Refresh routes for the proxy every 10 seconds
go func() {
for {
@ -84,17 +110,54 @@ func (h *Handler) Init(service micro.Service, engine *gin.Engine, routerAuth aut
}
// Calculate the pathMethod of the route and register it if it's not registered yet
pathMethod := fmt.Sprintf("%s:%s%s", route.GetMethod(), g.BasePath(), route.GetPath())
path := fmt.Sprintf("%s%s", g.BasePath(), route.GetPath())
pathMethod := fmt.Sprintf("%s:%s%s", route.Method, g.BasePath(), route.Path)
path := fmt.Sprintf("%s%s", g.BasePath(), route.Path)
if _, ok := h.routes[pathMethod]; !ok {
ilogger.Logrus().
WithField("service", s.Name).
WithField("endpoint", route.GetEndpoint()).
WithField("method", route.GetMethod()).
WithField("endpoint", route.Endpoint).
WithField("method", route.Method).
WithField("path", path).
Debugf("Found route")
WithField("ratelimitClientIP", route.RatelimitClientIP).
Debug("found route")
clientIPRatelimiter := make([]*limiter.Limiter, len(route.RatelimitClientIP))
if len(route.RatelimitClientIP) > 0 {
if h.rlStore == nil {
ilogger.Logrus().
WithField("service", s.Name).
WithField("endpoint", route.Endpoint).
WithField("method", route.Method).
WithField("path", path).
WithField("ratelimitClientIP", route.RatelimitClientIP).
Error("found a route with a limiter but there is no limiter store")
continue
}
haveError := false
for idx, rate := range route.RatelimitClientIP {
rate, err := limiter.NewRateFromFormatted(rate)
if err != nil {
ilogger.Logrus().
WithField("service", s.Name).
WithField("endpoint", route.Endpoint).
WithField("method", route.Method).
WithField("path", path).
WithField("ratelimitClientIP", route.RatelimitClientIP).
Error(err)
haveError = true
break
}
clientIPRatelimiter[idx] = limiter.New(h.rlStore, rate)
}
if haveError {
continue
}
}
g.Handle(route.GetMethod(), route.GetPath(), h.proxy(s.Name, route, route.AuthRequired))
g.Handle(route.Method, route.Path, h.proxy(s.Name, route, route.AuthRequired, path, clientIPRatelimiter))
h.routes[pathMethod] = route
h.routes[pathMethod].Path = path
}
@ -112,8 +175,38 @@ func (h *Handler) Stop() error {
return nil
}
func (h *Handler) proxy(serviceName string, route *routerclientpb.RoutesReply_Route, authRequired bool) func(*gin.Context) {
func (h *Handler) proxy(serviceName string, route *routerclientpb.RoutesReply_Route, authRequired bool, path string, clientIPRatelimiter []*limiter.Limiter) func(*gin.Context) {
return func(c *gin.Context) {
if len(clientIPRatelimiter) > 0 {
for idx, l := range clientIPRatelimiter {
context, err := l.Get(c, fmt.Sprintf("%s-%s-%s", path, l.Rate.Formatted, c.ClientIP()))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"status": http.StatusInternalServerError,
"message": "Internal server error",
})
c.Abort()
return
}
if idx == 0 {
c.Header("X-RateLimit-Limit", strconv.FormatInt(context.Limit, 10))
c.Header("X-RateLimit-Remaining", strconv.FormatInt(context.Remaining, 10))
c.Header("X-RateLimit-Reset", strconv.FormatInt(context.Reset, 10))
}
if context.Reached {
c.JSON(http.StatusTooManyRequests, gin.H{
"status": http.StatusTooManyRequests,
"message": "To many requests",
})
c.Abort()
return
}
}
}
// Map query/path params
params := make(map[string]string)
for _, p := range route.Params {
@ -180,7 +273,7 @@ func (h *Handler) proxy(serviceName string, route *routerclientpb.RoutesReply_Ro
request[pn] = p
}
req := h.service.Client().NewRequest(serviceName, route.GetEndpoint(), request, client.WithContentType("application/json"))
req := h.service.Client().NewRequest(serviceName, route.Endpoint, request, client.WithContentType("application/json"))
// Auth
ctx, err := h.routerAuth.ForwardContext(c.Request, c)
@ -217,11 +310,12 @@ func (h *Handler) proxy(serviceName string, route *routerclientpb.RoutesReply_Ro
func (h *Handler) Routes(ctx context.Context, in *emptypb.Empty, out *routerserverpb.RoutesReply) error {
for _, route := range h.routes {
out.Routes = append(out.Routes, &routerserverpb.RoutesReply_Route{
Method: route.Method,
Path: route.Path,
Params: route.Params,
Endpoint: route.Endpoint,
AuthRequired: route.AuthRequired,
Method: route.Method,
Path: route.Path,
Params: route.Params,
Endpoint: route.Endpoint,
AuthRequired: route.AuthRequired,
RatelimitClientIP: route.RatelimitClientIP,
})
}

@ -54,6 +54,7 @@ func internalService(routerHandler *handler.Handler) {
router.Method(router.MethodGet),
router.Path("/routes"),
router.Endpoint(routerserverpb.RouterServerService.Routes),
router.RatelimitClientIP("1-S", "50-M", "1000-H"),
),
)
r.RegisterWithServer(srv.Server())
@ -113,6 +114,11 @@ func main() {
EnvVars: []string{"MICRO_ROUTER_LISTEN"},
Value: ":8080",
},
&cli.StringFlag{
Name: "router_ratelimiter_store_url",
Usage: "Ratelimiter store URL, for example redis://localhost:6379/0. No store = no Endpoints that require a ratelimiter",
EnvVars: []string{"MICRO_ROUTER_RATELIMITER_STORE_URL"},
},
})))
routerHandler, err := handler.NewHandler()
@ -144,9 +150,10 @@ func main() {
gin.SetMode(gin.ReleaseMode)
}
r := gin.New()
r.ForwardedByClientIP = true
// Initalize the Handler
if err := routerHandler.Init(srv, r, routerAuthReg.Plugin(), c.Int("router_refresh")); err != nil {
if err := routerHandler.Init(srv, r, routerAuthReg.Plugin(), c.Int("router_refresh"), c.String("router_ratelimiter_store_url")); err != nil {
ilogger.Logrus().Fatal(err)
}

@ -10,8 +10,10 @@ require (
github.com/go-micro/plugins/v4/server/http v1.1.0
github.com/go-micro/plugins/v4/transport/grpc v1.1.0
github.com/go-micro/plugins/v4/transport/nats v1.1.1-0.20220908125827-e0369dde429b
github.com/go-redis/redis/v8 v8.11.5
github.com/sirupsen/logrus v1.9.0
github.com/toorop/gin-logrus v0.0.0-20210225092905-2c785434f26f
github.com/ulule/limiter/v3 v3.10.0
github.com/urfave/cli/v2 v2.16.3
go-micro.dev/v4 v4.8.1
google.golang.org/protobuf v1.28.1
@ -24,8 +26,10 @@ require (
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/bitly/go-simplejson v0.5.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cloudflare/circl v1.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
@ -76,7 +80,6 @@ require (
golang.org/x/sync v0.0.0-20220907140024-f12130a52804 // indirect
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
golang.org/x/tools v0.1.12 // indirect
google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 // indirect
google.golang.org/grpc v1.49.0 // indirect

@ -18,6 +18,8 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/bwesterb/go-ristretto v1.2.1/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
github.com/cloudflare/circl v1.2.0 h1:NheeISPSUcYftKlfrLuOo4T62FkmD4t4jviLfFFYaec=
github.com/cloudflare/circl v1.2.0/go.mod h1:Ch2UgYr6ti2KTtlejELlROl0YIYj7SLjAC8M+INXlMk=
@ -27,6 +29,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
@ -77,6 +81,8 @@ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/j
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
@ -149,6 +155,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
@ -189,6 +197,8 @@ github.com/toorop/gin-logrus v0.0.0-20210225092905-2c785434f26f/go.mod h1:X3Dd1S
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ulule/limiter/v3 v3.10.0 h1:C9mx3tgxYnt4pUYKWktZf7aEOVPbRYxR+onNFjQTEp0=
github.com/ulule/limiter/v3 v3.10.0/go.mod h1:NqPA/r8QfP7O11iC+95X6gcWJPtRWjKrtOUw07BTvoo=
github.com/urfave/cli/v2 v2.16.3 h1:gHoFIwpPjoyIMbJp/VFd+/vuD0dAgFK4B6DpEMFJfQk=
github.com/urfave/cli/v2 v2.16.3/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
@ -262,7 +272,6 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@ -301,7 +310,5 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
jochum.dev/jo-micro/auth2 v0.2.0 h1:48fLUtVx2u5NDlO0Nzm8K8cHUPbOXNNuKG9gg4vVmFM=
jochum.dev/jo-micro/auth2 v0.2.0/go.mod h1:z2qub/2K5+C9bpoDImWWPpKFPxds6LQN1Qx6X8c1xEc=
jochum.dev/jo-micro/auth2 v0.3.0 h1:7r9Vo7/Wlc/tB8sBN4BGQFniOy2x1ekoWI5I4+xBUv0=
jochum.dev/jo-micro/auth2 v0.3.0/go.mod h1:fSWMvxDct/jhmP1CC5HQTSfklqZRmygO8Zv5qZVuUHg=

@ -25,12 +25,13 @@ func NewHandler(routerURI string, routes ...*Route) *Handler {
}
pbRoutes = append(pbRoutes, &routerclientpb.RoutesReply_Route{
IsGlobal: r.IsGlobal,
Method: r.Method,
Path: r.Path,
Endpoint: util.ReflectFunctionName(r.Endpoint),
Params: r.Params,
AuthRequired: r.AuthRequired,
IsGlobal: r.IsGlobal,
Method: r.Method,
Path: r.Path,
Endpoint: util.ReflectFunctionName(r.Endpoint),
Params: r.Params,
AuthRequired: r.AuthRequired,
RatelimitClientIP: r.RatelimitClientIP,
})
}

@ -82,12 +82,13 @@ type RoutesReply_Route struct {
unknownFields protoimpl.UnknownFields
// isGlobal=True == no prefix route
IsGlobal bool `protobuf:"varint,1,opt,name=isGlobal,proto3" json:"isGlobal,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
Endpoint string `protobuf:"bytes,4,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
Params []string `protobuf:"bytes,5,rep,name=params,proto3" json:"params,omitempty"`
AuthRequired bool `protobuf:"varint,6,opt,name=authRequired,proto3" json:"authRequired,omitempty"`
IsGlobal bool `protobuf:"varint,1,opt,name=isGlobal,proto3" json:"isGlobal,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
Endpoint string `protobuf:"bytes,4,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
Params []string `protobuf:"bytes,5,rep,name=params,proto3" json:"params,omitempty"`
AuthRequired bool `protobuf:"varint,6,opt,name=authRequired,proto3" json:"authRequired,omitempty"`
RatelimitClientIP []string `protobuf:"bytes,7,rep,name=ratelimitClientIP,proto3" json:"ratelimitClientIP,omitempty"`
}
func (x *RoutesReply_Route) Reset() {
@ -164,6 +165,13 @@ func (x *RoutesReply_Route) GetAuthRequired() bool {
return false
}
func (x *RoutesReply_Route) GetRatelimitClientIP() []string {
if x != nil {
return x.RatelimitClientIP
}
return nil
}
var File_routerclientpb_proto protoreflect.FileDescriptor
var file_routerclientpb_proto_rawDesc = []byte{
@ -171,13 +179,13 @@ var file_routerclientpb_proto_rawDesc = []byte{
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0x90, 0x02, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65,
0x6f, 0x74, 0x6f, 0x22, 0xbe, 0x02, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65,
0x70, 0x6c, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x55, 0x52, 0x49,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x55, 0x52,
0x49, 0x12, 0x39, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x21, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x2e, 0x52,
0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x1a, 0xa7, 0x01, 0x0a,
0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x1a, 0xd5, 0x01, 0x0a,
0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x73, 0x47, 0x6c, 0x6f, 0x62,
0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x47, 0x6c, 0x6f, 0x62,
0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01,
@ -188,17 +196,20 @@ var file_routerclientpb_proto_rawDesc = []byte{
0x72, 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61,
0x6d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72,
0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x52, 0x65,
0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x32, 0x56, 0x0a, 0x13, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72,
0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3f, 0x0a,
0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a,
0x1b, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62,
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x40,
0x5a, 0x3e, 0x6a, 0x6f, 0x63, 0x68, 0x75, 0x6d, 0x2e, 0x64, 0x65, 0x76, 0x2f, 0x6a, 0x6f, 0x2d,
0x6d, 0x69, 0x63, 0x72, 0x6f, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70,
0x62, 0x3b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69,
0x6d, 0x69, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x18, 0x07, 0x20, 0x03, 0x28,
0x09, 0x52, 0x11, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x43, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x49, 0x50, 0x32, 0x56, 0x0a, 0x13, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x52,
0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x52,
0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x40, 0x5a, 0x3e,
0x6a, 0x6f, 0x63, 0x68, 0x75, 0x6d, 0x2e, 0x64, 0x65, 0x76, 0x2f, 0x6a, 0x6f, 0x2d, 0x6d, 0x69,
0x63, 0x72, 0x6f, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x3b,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

@ -19,6 +19,7 @@ message RoutesReply {
string endpoint = 4;
repeated string params = 5;
bool authRequired = 6;
repeated string ratelimitClientIP = 7;
}
string routerURI = 1;

@ -73,11 +73,12 @@ type RoutesReply_Route struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
Params []string `protobuf:"bytes,3,rep,name=params,proto3" json:"params,omitempty"`
Endpoint string `protobuf:"bytes,4,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
AuthRequired bool `protobuf:"varint,5,opt,name=authRequired,proto3" json:"authRequired,omitempty"`
Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
Params []string `protobuf:"bytes,3,rep,name=params,proto3" json:"params,omitempty"`
Endpoint string `protobuf:"bytes,4,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
AuthRequired bool `protobuf:"varint,5,opt,name=authRequired,proto3" json:"authRequired,omitempty"`
RatelimitClientIP []string `protobuf:"bytes,6,rep,name=ratelimitClientIP,proto3" json:"ratelimitClientIP,omitempty"`
}
func (x *RoutesReply_Route) Reset() {
@ -147,6 +148,13 @@ func (x *RoutesReply_Route) GetAuthRequired() bool {
return false
}
func (x *RoutesReply_Route) GetRatelimitClientIP() []string {
if x != nil {
return x.RatelimitClientIP
}
return nil
}
var File_routerserverpb_proto protoreflect.FileDescriptor
var file_routerserverpb_proto_rawDesc = []byte{
@ -154,11 +162,11 @@ var file_routerserverpb_proto_rawDesc = []byte{
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x70, 0x62, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xd6, 0x01, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65,
0x6f, 0x74, 0x6f, 0x22, 0x84, 0x02, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65,
0x70, 0x6c, 0x79, 0x12, 0x39, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79,
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x8b,
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x1a, 0xb9,
0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68,
0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
@ -167,17 +175,20 @@ var file_routerserverpb_proto_rawDesc = []byte{
0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68,
0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c,
0x61, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x32, 0x56, 0x0a, 0x13,
0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x16, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x70,
0x6c, 0x79, 0x22, 0x00, 0x42, 0x40, 0x5a, 0x3e, 0x6a, 0x6f, 0x63, 0x68, 0x75, 0x6d, 0x2e, 0x64,
0x65, 0x76, 0x2f, 0x6a, 0x6f, 0x2d, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x2f, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x70, 0x62, 0x3b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x61, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x11,
0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49,
0x50, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d,
0x69, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x32, 0x56, 0x0a, 0x13, 0x52, 0x6f,
0x75, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x3f, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79,
0x22, 0x00, 0x42, 0x40, 0x5a, 0x3e, 0x6a, 0x6f, 0x63, 0x68, 0x75, 0x6d, 0x2e, 0x64, 0x65, 0x76,
0x2f, 0x6a, 0x6f, 0x2d, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x70, 0x62, 0x3b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

@ -17,6 +17,7 @@ message RoutesReply {
repeated string params = 3;
string endpoint = 4;
bool authRequired = 5;
repeated string ratelimitClientIP = 6;
}
repeated Route routes = 1;

@ -5,25 +5,27 @@ import (
)
type Route struct {
// isGlobal=True == no prefix route
IsGlobal bool
IsGlobal bool // isGlobal=True == no prefix route
Method string
Path string
Endpoint interface{}
Params []string
AuthRequired bool
AuthRequired bool // Default false
// https://github.com/ulule/limiter - default is no rate Limiter at all, put the strictes limit first
RatelimitClientIP []string
}
type Option func(*Route)
func NewRoute(opts ...Option) *Route {
route := &Route{
IsGlobal: false,
Method: MethodGet,
Path: "/",
Endpoint: nil,
Params: []string{},
AuthRequired: false,
IsGlobal: false,
Method: MethodGet,
Path: "/",
Endpoint: nil,
Params: []string{},
AuthRequired: false,
RatelimitClientIP: []string{},
}
for _, o := range opts {
@ -73,3 +75,9 @@ func AuthRequired() Option {
o.AuthRequired = true
}
}
func RatelimitClientIP(n ...string) Option {
return func(o *Route) {
o.RatelimitClientIP = n
}
}

Loading…
Cancel
Save