summaryrefslogtreecommitdiff
path: root/contrib/sharedhost/replacement.go
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sharedhost/replacement.go')
-rw-r--r--contrib/sharedhost/replacement.go46
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
+}