2018-11-14 10:18:03 +01:00
package stripprefix
import (
"context"
"net/http"
"strings"
"github.com/opentracing/opentracing-go/ext"
2020-09-16 15:46:04 +02: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 10:18:03 +01:00
)
const (
// ForwardedPrefixHeader is the default header to set prefix.
ForwardedPrefixHeader = "X-Forwarded-Prefix"
typeName = "StripPrefix"
)
// stripPrefix is a middleware used to strip prefix from an URL request.
type stripPrefix struct {
2019-11-14 10:32:05 +01:00
next http . Handler
prefixes [ ] string
forceSlash bool // TODO Must be removed (breaking), the default behavior must be forceSlash=false
name string
2018-11-14 10:18:03 +01:00
}
// New creates a new strip prefix middleware.
2019-07-10 09:26:04 +02:00
func New ( ctx context . Context , next http . Handler , config dynamic . StripPrefix , name string ) ( http . Handler , error ) {
2019-09-13 19:28:04 +02:00
log . FromContext ( middlewares . GetLoggerCtx ( ctx , name , typeName ) ) . Debug ( "Creating middleware" )
2018-11-14 10:18:03 +01:00
return & stripPrefix {
2019-11-14 10:32:05 +01:00
prefixes : config . Prefixes ,
forceSlash : config . ForceSlash ,
next : next ,
name : name ,
2018-11-14 10:18:03 +01:00
} , nil
}
func ( s * stripPrefix ) GetTracingInformation ( ) ( string , ext . SpanKindEnum ) {
return s . name , tracing . SpanKindNoneEnum
}
func ( s * stripPrefix ) ServeHTTP ( rw http . ResponseWriter , req * http . Request ) {
for _ , prefix := range s . prefixes {
if strings . HasPrefix ( req . URL . Path , prefix ) {
2019-11-14 10:32:05 +01:00
req . URL . Path = s . getPrefixStripped ( req . URL . Path , prefix )
2018-11-14 10:18:03 +01:00
if req . URL . RawPath != "" {
2019-11-14 10:32:05 +01:00
req . URL . RawPath = s . getPrefixStripped ( req . URL . RawPath , prefix )
2018-11-14 10:18:03 +01:00
}
s . serveRequest ( rw , req , strings . TrimSpace ( prefix ) )
return
}
}
2019-09-03 20:32:03 +02:00
s . next . ServeHTTP ( rw , req )
2018-11-14 10:18:03 +01:00
}
func ( s * stripPrefix ) serveRequest ( rw http . ResponseWriter , req * http . Request , prefix string ) {
req . Header . Add ( ForwardedPrefixHeader , prefix )
req . RequestURI = req . URL . RequestURI ( )
s . next . ServeHTTP ( rw , req )
}
2019-11-14 10:32:05 +01:00
func ( s * stripPrefix ) getPrefixStripped ( urlPath , prefix string ) string {
if s . forceSlash {
// Only for compatibility reason with the previous behavior,
// but the previous behavior is wrong.
// This needs to be removed in the next breaking version.
return "/" + strings . TrimPrefix ( strings . TrimPrefix ( urlPath , prefix ) , "/" )
}
return ensureLeadingSlash ( strings . TrimPrefix ( urlPath , prefix ) )
2018-11-14 10:18:03 +01:00
}
func ensureLeadingSlash ( str string ) string {
2019-11-14 10:32:05 +01:00
if str == "" {
return str
}
if str [ 0 ] == '/' {
return str
}
return "/" + str
2018-11-14 10:18:03 +01:00
}