mirror of
https://github.com/kemko/reproxy.git
synced 2026-01-04 17:25:49 +03:00
add ability to drop incoming headers #108
In some cases proxy should sanitize incoming headers. --drop-header and $DROP_HEADERS set list of headers (keys) and those headers removed from the request.
This commit is contained in:
@@ -33,7 +33,8 @@ var opts struct {
|
||||
Listen string `short:"l" long:"listen" env:"LISTEN" description:"listen on host:port (default: 0.0.0.0:8080/8443 under docker, 127.0.0.1:80/443 without)"`
|
||||
MaxSize string `short:"m" long:"max" env:"MAX_SIZE" default:"64K" description:"max request size"`
|
||||
GzipEnabled bool `short:"g" long:"gzip" env:"GZIP" description:"enable gz compression"`
|
||||
ProxyHeaders []string `short:"x" long:"header" description:"proxy headers"` // env HEADER split in code to allow , inside ""
|
||||
ProxyHeaders []string `short:"x" long:"header" description:"outgoing proxy headers to add"` // env HEADER split in code to allow , inside ""
|
||||
DropHeaders []string `long:"drop-header" env:"DROP_HEADERS" description:"incoming headers to drop" env-delim:","`
|
||||
|
||||
LBType string `long:"lb-type" env:"LB_TYPE" description:"load balancer type" choice:"random" choice:"failover" default:"random"` //nolint
|
||||
|
||||
@@ -239,6 +240,7 @@ func run() error {
|
||||
GzEnabled: opts.GzipEnabled,
|
||||
SSLConfig: sslConfig,
|
||||
ProxyHeaders: proxyHeaders,
|
||||
DropHeader: opts.DropHeaders,
|
||||
AccessLog: accessLog,
|
||||
StdOutEnabled: opts.Logger.StdOut,
|
||||
Signature: opts.Signature,
|
||||
@@ -258,7 +260,7 @@ func run() error {
|
||||
Reporter: errReporter,
|
||||
PluginConductor: makePluginConductor(ctx),
|
||||
ThrottleSystem: opts.Throttle.System * 3,
|
||||
ThottleUser: opts.Throttle.User,
|
||||
ThrottleUser: opts.Throttle.User,
|
||||
}
|
||||
|
||||
err = px.Run(ctx)
|
||||
|
||||
@@ -45,7 +45,7 @@ func NewMetrics() *Metrics {
|
||||
Buckets: []float64{0.01, 0.1, 0.5, 1, 2, 3, 5},
|
||||
}, []string{"path"})
|
||||
|
||||
prometheus.Unregister(prometheus.NewGoCollector())
|
||||
prometheus.Unregister(prometheus.NewGoCollector()) //nolint
|
||||
|
||||
if err := prometheus.Register(res.totalRequests); err != nil {
|
||||
log.Printf("[WARN] can't register prometheus totalRequests, %v", err)
|
||||
|
||||
@@ -14,21 +14,28 @@ import (
|
||||
"github.com/umputun/reproxy/app/discovery"
|
||||
)
|
||||
|
||||
func headersHandler(headers []string) func(next http.Handler) http.Handler {
|
||||
func headersHandler(addHeaders, dropHeaders []string) func(next http.Handler) http.Handler {
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if len(headers) == 0 {
|
||||
if len(addHeaders) == 0 && len(dropHeaders) == 0 {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
for _, h := range headers {
|
||||
// add headers to response
|
||||
for _, h := range addHeaders {
|
||||
elems := strings.Split(h, ":")
|
||||
if len(elems) != 2 {
|
||||
continue
|
||||
}
|
||||
w.Header().Set(strings.TrimSpace(elems[0]), strings.TrimSpace(elems[1]))
|
||||
}
|
||||
|
||||
// drop headers from request
|
||||
for _, h := range dropHeaders {
|
||||
r.Header.Del(h)
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,11 +18,17 @@ import (
|
||||
|
||||
func Test_headersHandler(t *testing.T) {
|
||||
wr := httptest.NewRecorder()
|
||||
handler := headersHandler([]string{"k1:v1", "k2:v2"})(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
handler := headersHandler([]string{"k1:v1", "k2:v2"}, []string{"r1", "r2"})(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Logf("req: %v", r)
|
||||
assert.Equal(t, "", r.Header.Get("r1"), "r1 header dropped")
|
||||
assert.Equal(t, "", r.Header.Get("r2"), "r2 header dropped")
|
||||
assert.Equal(t, "rv3", r.Header.Get("r3"), "r3 kept")
|
||||
}))
|
||||
req, err := http.NewRequest("GET", "http://example.com", nil)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("r1", "rv1")
|
||||
req.Header.Set("r2", "rv2")
|
||||
req.Header.Set("r3", "rv3")
|
||||
handler.ServeHTTP(wr, req)
|
||||
assert.Equal(t, "v1", wr.Result().Header.Get("k1"))
|
||||
assert.Equal(t, "v2", wr.Result().Header.Get("k2"))
|
||||
|
||||
@@ -32,6 +32,7 @@ type Http struct { // nolint golint
|
||||
MaxBodySize int64
|
||||
GzEnabled bool
|
||||
ProxyHeaders []string
|
||||
DropHeader []string
|
||||
SSLConfig SSLConfig
|
||||
Version string
|
||||
AccessLog io.Writer
|
||||
@@ -45,7 +46,7 @@ type Http struct { // nolint golint
|
||||
LBSelector func(len int) int
|
||||
|
||||
ThrottleSystem int
|
||||
ThottleUser int
|
||||
ThrottleUser int
|
||||
}
|
||||
|
||||
// Matcher source info (server and route) to the destination url
|
||||
@@ -110,17 +111,17 @@ func (h *Http) Run(ctx context.Context) error {
|
||||
}()
|
||||
|
||||
handler := R.Wrap(h.proxyHandler(),
|
||||
R.Recoverer(log.Default()), // recover on errors
|
||||
signatureHandler(h.Signature, h.Version), // send app signature
|
||||
h.pingHandler, // respond to /ping
|
||||
h.healthMiddleware, // respond to /health
|
||||
h.matchHandler, // set matched routes to context
|
||||
limiterSystemHandler(h.ThrottleSystem), // limit total requests/sec
|
||||
limiterUserHandler(h.ThottleUser), // req/seq per user/route match
|
||||
h.mgmtHandler(), // handles /metrics and /routes for prometheus
|
||||
h.pluginHandler(), // prc to external plugins
|
||||
headersHandler(h.ProxyHeaders), // set response headers
|
||||
accessLogHandler(h.AccessLog), // apache-format log file
|
||||
R.Recoverer(log.Default()), // recover on errors
|
||||
signatureHandler(h.Signature, h.Version), // send app signature
|
||||
h.pingHandler, // respond to /ping
|
||||
h.healthMiddleware, // respond to /health
|
||||
h.matchHandler, // set matched routes to context
|
||||
limiterSystemHandler(h.ThrottleSystem), // limit total requests/sec
|
||||
limiterUserHandler(h.ThrottleUser), // req/seq per user/route match
|
||||
h.mgmtHandler(), // handles /metrics and /routes for prometheus
|
||||
h.pluginHandler(), // prc to external plugins
|
||||
headersHandler(h.ProxyHeaders, h.DropHeader), // add response headers and delete some request headers
|
||||
accessLogHandler(h.AccessLog), // apache-format log file
|
||||
stdoutLogHandler(h.StdOutEnabled, logger.New(logger.Log(log.Default()), logger.Prefix("[INFO]")).Handler),
|
||||
maxReqSizeHandler(h.MaxBodySize), // limit request max size
|
||||
gzipHandler(h.GzEnabled), // gzip response
|
||||
|
||||
Reference in New Issue
Block a user