summaryrefslogtreecommitdiff
path: root/contrib/sharedhost/replacement.go
blob: 9dc3a1ee83fde4dec59482b14250f5e859139757 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package sharedhost

import (
	"context"
	"crypto/tls"
	"net/url"

	sr "tildegit.org/tjp/sliderule"
)

// 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) sr.Middleware {
	return func(inner sr.Handler) sr.Handler {
		return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response {
			if len(request.Path) > 1 && request.Path[0] == '/' && request.Path[1] == '~' {
				request = cloneRequest(request)
				request.Path = "/" + replacement + request.Path[2:]
			}

			return inner.Handle(ctx, request)
		})
	}
}

func cloneRequest(start *sr.Request) *sr.Request {
	next := &sr.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
}