mirror of
https://github.com/labstack/echo.git
synced 2025-07-13 01:30:31 +02:00
* extend proxy middleware. closes #1202
This commit is contained in:
committed by
Vishal Rana
parent
af5c97715f
commit
fcdf096c2c
@ -38,6 +38,10 @@ type (
|
|||||||
// "/users/*/orders/*": "/user/$1/order/$2",
|
// "/users/*/orders/*": "/user/$1/order/$2",
|
||||||
Rewrite map[string]string
|
Rewrite map[string]string
|
||||||
|
|
||||||
|
// Context key to store selected ProxyTarget into context.
|
||||||
|
// Optional. Default value "target".
|
||||||
|
ContextKey string
|
||||||
|
|
||||||
rewriteRegex map[*regexp.Regexp]string
|
rewriteRegex map[*regexp.Regexp]string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,13 +49,14 @@ type (
|
|||||||
ProxyTarget struct {
|
ProxyTarget struct {
|
||||||
Name string
|
Name string
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
|
Meta echo.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProxyBalancer defines an interface to implement a load balancing technique.
|
// ProxyBalancer defines an interface to implement a load balancing technique.
|
||||||
ProxyBalancer interface {
|
ProxyBalancer interface {
|
||||||
AddTarget(*ProxyTarget) bool
|
AddTarget(*ProxyTarget) bool
|
||||||
RemoveTarget(string) bool
|
RemoveTarget(string) bool
|
||||||
Next() *ProxyTarget
|
Next(echo.Context) *ProxyTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
commonBalancer struct {
|
commonBalancer struct {
|
||||||
@ -76,6 +81,7 @@ var (
|
|||||||
// DefaultProxyConfig is the default Proxy middleware config.
|
// DefaultProxyConfig is the default Proxy middleware config.
|
||||||
DefaultProxyConfig = ProxyConfig{
|
DefaultProxyConfig = ProxyConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
|
ContextKey: "target",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -164,7 +170,7 @@ func (b *commonBalancer) RemoveTarget(name string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Next randomly returns an upstream target.
|
// Next randomly returns an upstream target.
|
||||||
func (b *randomBalancer) Next() *ProxyTarget {
|
func (b *randomBalancer) Next(c echo.Context) *ProxyTarget {
|
||||||
if b.random == nil {
|
if b.random == nil {
|
||||||
b.random = rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
|
b.random = rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
|
||||||
}
|
}
|
||||||
@ -174,7 +180,7 @@ func (b *randomBalancer) Next() *ProxyTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Next returns an upstream target using round-robin technique.
|
// Next returns an upstream target using round-robin technique.
|
||||||
func (b *roundRobinBalancer) Next() *ProxyTarget {
|
func (b *roundRobinBalancer) Next(c echo.Context) *ProxyTarget {
|
||||||
b.i = b.i % uint32(len(b.targets))
|
b.i = b.i % uint32(len(b.targets))
|
||||||
t := b.targets[b.i]
|
t := b.targets[b.i]
|
||||||
atomic.AddUint32(&b.i, 1)
|
atomic.AddUint32(&b.i, 1)
|
||||||
@ -216,7 +222,8 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
|
|||||||
|
|
||||||
req := c.Request()
|
req := c.Request()
|
||||||
res := c.Response()
|
res := c.Response()
|
||||||
tgt := config.Balancer.Next()
|
tgt := config.Balancer.Next(c)
|
||||||
|
c.Set(config.ContextKey, tgt)
|
||||||
|
|
||||||
// Rewrite
|
// Rewrite
|
||||||
for k, v := range config.rewriteRegex {
|
for k, v := range config.rewriteRegex {
|
||||||
|
@ -124,4 +124,19 @@ func TestProxy(t *testing.T) {
|
|||||||
req.URL.Path = "/users/jack/orders/1"
|
req.URL.Path = "/users/jack/orders/1"
|
||||||
e.ServeHTTP(rec, req)
|
e.ServeHTTP(rec, req)
|
||||||
assert.Equal(t, "/user/jack/order/1", req.URL.Path)
|
assert.Equal(t, "/user/jack/order/1", req.URL.Path)
|
||||||
|
|
||||||
|
// ProxyTarget is set in context
|
||||||
|
contextObserver := func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) (err error) {
|
||||||
|
next(c)
|
||||||
|
assert.Contains(t, targets, c.Get("target"), "target is not set in context")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rrb1 := NewRoundRobinBalancer(targets)
|
||||||
|
e = echo.New()
|
||||||
|
e.Use(contextObserver)
|
||||||
|
e.Use(Proxy(rrb1))
|
||||||
|
rec = newCloseNotifyRecorder()
|
||||||
|
e.ServeHTTP(rec, req)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user