...
1 package handlers
2
3 import (
4 "net/http"
5 "net/url"
6 "strings"
7 )
8
9 type canonical struct {
10 h http.Handler
11 domain string
12 code int
13 }
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 func CanonicalHost(domain string, code int) func(h http.Handler) http.Handler {
31 fn := func(h http.Handler) http.Handler {
32 return canonical{h, domain, code}
33 }
34
35 return fn
36 }
37
38 func (c canonical) ServeHTTP(w http.ResponseWriter, r *http.Request) {
39 dest, err := url.Parse(c.domain)
40 if err != nil {
41
42 c.h.ServeHTTP(w, r)
43 return
44 }
45
46 if dest.Scheme == "" || dest.Host == "" {
47
48
49 c.h.ServeHTTP(w, r)
50 return
51 }
52
53 if !strings.EqualFold(cleanHost(r.Host), dest.Host) {
54
55 dest := dest.Scheme + "://" + dest.Host + r.URL.Path
56 if r.URL.RawQuery != "" {
57 dest += "?" + r.URL.RawQuery
58 }
59 http.Redirect(w, r, dest, c.code)
60 return
61 }
62
63 c.h.ServeHTTP(w, r)
64 }
65
66
67
68
69 func cleanHost(in string) string {
70 if i := strings.IndexAny(in, " /"); i != -1 {
71 return in[:i]
72 }
73 return in
74 }
75
View as plain text