Repository navigation
Expand file tree
/
Copy pathmain.go
More file actions
91 lines (75 loc) · 2.57 KB
/
Copy pathmain.go
File metadata and controls
91 lines (75 loc) · 2.57 KB
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package main
import (
_ "embed"
"fmt"
"html/template"
"log"
"net/http"
"net/url"
"os"
"sort"
"strings"
)
//go:embed page.html
var pageHTML string
//go:embed bg.webp
var bg []byte
var tmpl = template.Must(template.New("page").Parse(pageHTML))
// identityHeaders are the headers Tinyauth sets on authenticated requests.
var identityHeaders = []string{"Remote-User", "Remote-Name", "Remote-Email", "Remote-Groups"}
type row struct{ Key, Value string }
type page struct {
Protected bool // false on the public landing page, true on /protected
Identity []row // the four Tinyauth headers, in display order
Groups []string // Remote-Groups split into individual badges
Headers []row // every request header, sorted by name
LogoutURL string
}
func render(w http.ResponseWriter, r *http.Request, protected bool, logoutURL string) {
p := page{Protected: protected, LogoutURL: logoutURL}
for _, h := range identityHeaders {
p.Identity = append(p.Identity, row{h, r.Header.Get(h)})
}
for g := range strings.SplitSeq(r.Header.Get("Remote-Groups"), ",") {
if g = strings.TrimSpace(g); g != "" {
p.Groups = append(p.Groups, g)
}
}
keys := make([]string, 0, len(r.Header))
for k := range r.Header {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
p.Headers = append(p.Headers, row{k, strings.Join(r.Header[k], ", ")})
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Cache-Control", "no-store")
if err := tmpl.Execute(w, p); err != nil {
log.Printf("render: %v", err)
}
}
func handleBg(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "image/webp")
w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", 60*60*24*30)) // 30 days
w.WriteHeader(http.StatusOK)
if _, err := w.Write(bg); err != nil {
log.Printf("handleBg: %v", err)
}
}
func main() {
tinyauthURL := os.Getenv("TINYAUTH_URL")
demoURL := os.Getenv("DEMO_URL")
logoutURL := ""
if tinyauthURL != "" && demoURL != "" {
encodedDemoURL := url.QueryEscape(strings.TrimSuffix(demoURL, "/") + "/protected")
logoutURL = strings.TrimSuffix(tinyauthURL, "/") + "/logout?login_for=app&redirect_uri=" + encodedDemoURL
}
mux := http.NewServeMux()
mux.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) { render(w, r, false, logoutURL) })
mux.HandleFunc("GET /protected", func(w http.ResponseWriter, r *http.Request) { render(w, r, true, logoutURL) })
mux.HandleFunc("GET /bg.webp", handleBg)
addr := ":3000"
log.Printf("tinyauth demo listening on %s", addr)
log.Fatal(http.ListenAndServe(addr, mux))
}