mirror of
https://github.com/umputun/reproxy.git
synced 2024-09-11 08:55:25 +03:00
add OverrideHeadersIn and OverrideHeadersOut support
This is an attempt to address #108 Instead of dedicated support of header`s removal it allows to return a flag indicating plugin's full control over headers. With this flag set, the conductor won't mix response headers with originals but rather will count on a plugin to provide all the headers.
This commit is contained in:
parent
506ded3ad4
commit
c7a2308267
@ -285,6 +285,11 @@ The core functionality of reproxy can be extended with external plugins. Each pl
|
|||||||
- `HeadersIn` - incoming headers. Those will be sent to the proxied url
|
- `HeadersIn` - incoming headers. Those will be sent to the proxied url
|
||||||
- `HeadersOut` - outgoing headers. Will be sent back to the client
|
- `HeadersOut` - outgoing headers. Will be sent back to the client
|
||||||
|
|
||||||
|
By default headers set by a plugin will be mixed with the original headers. In case if plugin need to control all the headers, for example drop some of them, `OverrideHeaders*` field can be set by a plugin indicating to the core reporxy process the need to overwrite all the headers instead of mixing them in.
|
||||||
|
|
||||||
|
- `OverrideHeadersIn` - indicates plugin responsible for all incoming headers.
|
||||||
|
- `OverrideHeadersOut` - indicates plugin responsible for all outgoing headers
|
||||||
|
|
||||||
To simplify the development process all the building blocks provided. It includes `lib.Plugin` handling registration, listening and dispatching calls as well as `lib.Request` and `lib.Response` defining input and output. Plugin's authors should implement concrete handlers satisfying `func(req lib.Request, res *lib.HandlerResponse) (err error)` signature. Each plugin may contain multiple handlers like this.
|
To simplify the development process all the building blocks provided. It includes `lib.Plugin` handling registration, listening and dispatching calls as well as `lib.Request` and `lib.Response` defining input and output. Plugin's authors should implement concrete handlers satisfying `func(req lib.Request, res *lib.HandlerResponse) (err error)` signature. Each plugin may contain multiple handlers like this.
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,6 +87,20 @@ func (c *Conductor) Run(ctx context.Context) error {
|
|||||||
// Failed plugin calls ignored. Status code from any plugin may stop the chain of calls if not 200. This is needed
|
// Failed plugin calls ignored. Status code from any plugin may stop the chain of calls if not 200. This is needed
|
||||||
// to allow plugins like auth which has to terminate request in some cases.
|
// to allow plugins like auth which has to terminate request in some cases.
|
||||||
func (c *Conductor) Middleware(next http.Handler) http.Handler {
|
func (c *Conductor) Middleware(next http.Handler) http.Handler {
|
||||||
|
|
||||||
|
setHeaders := func(src, alt http.Header, overrideHeaders bool) {
|
||||||
|
if overrideHeaders {
|
||||||
|
for k := range src {
|
||||||
|
src.Del(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k, vv := range alt {
|
||||||
|
for _, v := range vv {
|
||||||
|
src.Add(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
@ -101,16 +115,10 @@ func (c *Conductor) Middleware(next http.Handler) http.Handler {
|
|||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for k, vv := range reply.HeadersIn {
|
|
||||||
for _, v := range vv {
|
setHeaders(r.Header, reply.HeadersIn, reply.OverrideHeadersIn)
|
||||||
r.Header.Add(k, v)
|
setHeaders(w.Header(), reply.HeadersOut, reply.OverrideHeadersOut)
|
||||||
}
|
|
||||||
}
|
|
||||||
for k, vv := range reply.HeadersOut {
|
|
||||||
for _, v := range vv {
|
|
||||||
w.Header().Add(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if reply.StatusCode >= 400 {
|
if reply.StatusCode >= 400 {
|
||||||
c.lock.RUnlock()
|
c.lock.RUnlock()
|
||||||
http.Error(w, http.StatusText(reply.StatusCode), reply.StatusCode)
|
http.Error(w, http.StatusText(reply.StatusCode), reply.StatusCode)
|
||||||
|
@ -223,6 +223,7 @@ func TestConductor_Middleware(t *testing.T) {
|
|||||||
reply.(*lib.Response).StatusCode = 200
|
reply.(*lib.Response).StatusCode = 200
|
||||||
reply.(*lib.Response).HeadersOut = map[string][]string{}
|
reply.(*lib.Response).HeadersOut = map[string][]string{}
|
||||||
reply.(*lib.Response).HeadersOut.Set("k11", "v11")
|
reply.(*lib.Response).HeadersOut.Set("k11", "v11")
|
||||||
|
reply.(*lib.Response).OverrideHeadersOut = true
|
||||||
}
|
}
|
||||||
if serviceMethod == "Test1.Mw3" {
|
if serviceMethod == "Test1.Mw3" {
|
||||||
t.Fatal("shouldn't be called")
|
t.Fatal("shouldn't be called")
|
||||||
@ -285,9 +286,10 @@ func TestConductor_Middleware(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
h.ServeHTTP(w, rr)
|
h.ServeHTTP(w, rr)
|
||||||
assert.Equal(t, 200, w.Result().StatusCode)
|
assert.Equal(t, 200, w.Result().StatusCode)
|
||||||
assert.Equal(t, "v1", w.Result().Header.Get("k1"))
|
assert.Equal(t, "", w.Result().Header.Get("k1"))
|
||||||
assert.Equal(t, "v2", w.Result().Header.Get("k2"))
|
assert.Equal(t, "v2", w.Result().Header.Get("k2"))
|
||||||
assert.Equal(t, "v21", rr.Header.Get("k21"))
|
assert.Equal(t, "v21", rr.Header.Get("k21"))
|
||||||
|
assert.Equal(t, "v11", w.Result().Header.Get("k11"))
|
||||||
t.Logf("req: %+v", rr)
|
t.Logf("req: %+v", rr)
|
||||||
t.Logf("resp: %+v", w.Result())
|
t.Logf("resp: %+v", w.Result())
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,9 @@ type Request struct {
|
|||||||
|
|
||||||
// Response from plugin's handler call
|
// Response from plugin's handler call
|
||||||
type Response struct {
|
type Response struct {
|
||||||
StatusCode int
|
StatusCode int
|
||||||
HeadersIn http.Header
|
HeadersIn http.Header
|
||||||
HeadersOut http.Header
|
HeadersOut http.Header
|
||||||
|
OverrideHeadersIn bool // indicates plugin removing all the original incoming headers
|
||||||
|
OverrideHeadersOut bool // indicates plugin removing all the original outgoing headers
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user