2018-11-14 09:18:03 +00:00
|
|
|
// Package headers Middleware based on https://github.com/unrolled/secure.
|
|
|
|
package headers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"github.com/opentracing/opentracing-go/ext"
|
2020-09-16 13:46:04 +00:00
|
|
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/log"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/middlewares"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/tracing"
|
2018-11-14 09:18:03 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2019-07-12 09:46:04 +00:00
|
|
|
typeName = "Headers"
|
2018-11-14 09:18:03 +00:00
|
|
|
)
|
|
|
|
|
2020-03-05 07:18:04 +00:00
|
|
|
func handleDeprecation(ctx context.Context, cfg *dynamic.Headers) {
|
2021-05-28 06:50:09 +00:00
|
|
|
if cfg.SSLRedirect {
|
|
|
|
log.FromContext(ctx).Warn("SSLRedirect is deprecated, please use entrypoint redirection instead.")
|
|
|
|
}
|
|
|
|
if cfg.SSLTemporaryRedirect {
|
|
|
|
log.FromContext(ctx).Warn("SSLTemporaryRedirect is deprecated, please use entrypoint redirection instead.")
|
|
|
|
}
|
|
|
|
if cfg.SSLHost != "" {
|
|
|
|
log.FromContext(ctx).Warn("SSLHost is deprecated, please use RedirectRegex middleware instead.")
|
|
|
|
}
|
|
|
|
if cfg.SSLForceHost {
|
|
|
|
log.FromContext(ctx).Warn("SSLForceHost is deprecated, please use RedirectScheme middleware instead.")
|
|
|
|
}
|
2021-06-21 13:16:13 +00:00
|
|
|
if cfg.FeaturePolicy != "" {
|
|
|
|
log.FromContext(ctx).Warn("FeaturePolicy is deprecated, please use PermissionsPolicy header instead.")
|
|
|
|
}
|
2020-03-05 07:18:04 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 09:18:03 +00:00
|
|
|
type headers struct {
|
|
|
|
name string
|
|
|
|
handler http.Handler
|
|
|
|
}
|
|
|
|
|
|
|
|
// New creates a Headers middleware.
|
2020-03-05 07:18:04 +00:00
|
|
|
func New(ctx context.Context, next http.Handler, cfg dynamic.Headers, name string) (http.Handler, error) {
|
2018-11-14 09:18:03 +00:00
|
|
|
// HeaderMiddleware -> SecureMiddleWare -> next
|
2020-03-05 07:18:04 +00:00
|
|
|
mCtx := middlewares.GetLoggerCtx(ctx, name, typeName)
|
|
|
|
logger := log.FromContext(mCtx)
|
2018-11-14 09:18:03 +00:00
|
|
|
logger.Debug("Creating middleware")
|
2019-09-13 17:28:04 +00:00
|
|
|
|
2020-03-05 07:18:04 +00:00
|
|
|
handleDeprecation(mCtx, &cfg)
|
|
|
|
|
|
|
|
hasSecureHeaders := cfg.HasSecureHeadersDefined()
|
|
|
|
hasCustomHeaders := cfg.HasCustomHeadersDefined()
|
|
|
|
hasCorsHeaders := cfg.HasCorsHeadersDefined()
|
2019-04-02 08:40:04 +00:00
|
|
|
|
|
|
|
if !hasSecureHeaders && !hasCustomHeaders && !hasCorsHeaders {
|
2018-11-14 09:18:03 +00:00
|
|
|
return nil, errors.New("headers configuration not valid")
|
|
|
|
}
|
|
|
|
|
|
|
|
var handler http.Handler
|
|
|
|
nextHandler := next
|
|
|
|
|
2019-04-02 08:40:04 +00:00
|
|
|
if hasSecureHeaders {
|
2020-06-15 10:20:05 +00:00
|
|
|
logger.Debugf("Setting up secureHeaders from %v", cfg)
|
2020-09-01 16:16:04 +00:00
|
|
|
handler = newSecure(next, cfg, name)
|
2018-11-14 09:18:03 +00:00
|
|
|
nextHandler = handler
|
|
|
|
}
|
|
|
|
|
2019-04-02 08:40:04 +00:00
|
|
|
if hasCustomHeaders || hasCorsHeaders {
|
2020-06-15 10:20:05 +00:00
|
|
|
logger.Debugf("Setting up customHeaders/Cors from %v", cfg)
|
2024-09-16 09:10:04 +00:00
|
|
|
var err error
|
|
|
|
handler, err = NewHeader(nextHandler, cfg)
|
2020-10-29 09:52:03 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-11-14 09:18:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return &headers{
|
|
|
|
handler: handler,
|
|
|
|
name: name,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *headers) GetTracingInformation() (string, ext.SpanKindEnum) {
|
|
|
|
return h.name, tracing.SpanKindNoneEnum
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *headers) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
h.handler.ServeHTTP(rw, req)
|
|
|
|
}
|