diff options
Diffstat (limited to 'contrib/sharedhost/replacement.go')
-rw-r--r-- | contrib/sharedhost/replacement.go | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/contrib/sharedhost/replacement.go b/contrib/sharedhost/replacement.go new file mode 100644 index 0000000..1fb2a0d --- /dev/null +++ b/contrib/sharedhost/replacement.go @@ -0,0 +1,46 @@ +package sharedhost + +import ( + "context" + "crypto/tls" + "net/url" + + "tildegit.org/tjp/gus" +) + +// ReplaceTilde builds a middleware which substitutes a leading '~' in the request path. +// +// It makes the alteration to a copy of the request which is then passed into the +// wrapped Handler. This way middlewares outside of this one inspecting the request +// afterwards will see the original URL. +// +// Typically the replacement should end with a "/", so that the ~ ends up mapping to a +// particular directory on the filesystem. For instance with a replacement string of +// "users/", "domain.com/~jim/index.gmi" maps to "domain.com/users/jim/index.gmi". +func ReplaceTilde(replacement string) gus.Middleware { + return func(inner gus.Handler) gus.Handler { + return func(ctx context.Context, request *gus.Request) *gus.Response { + if len(request.Path) > 1 && request.Path[0] == '/' && request.Path[1] == '~' { + request = cloneRequest(request) + request.Path = "/" + replacement + request.Path[2:] + } + + return inner(ctx, request) + } + } +} + +func cloneRequest(start *gus.Request) *gus.Request { + next := &gus.Request{} + *next = *start + + next.URL = &url.URL{} + *next.URL = *start.URL + + if start.TLSState != nil { + next.TLSState = &tls.ConnectionState{} + *next.TLSState = *start.TLSState + } + + return next +} |