diff options
| author | Russ Cox <rsc@golang.org> | 2021-11-18 10:55:19 -0500 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2021-11-22 16:43:07 +0000 |
| commit | e77adb1f30f2761cc0e025c1f313b64ffe36a05e (patch) | |
| tree | 548df37f9dce15d1906fd645fac2d68ae8bdfe5e /cmd | |
| parent | ceabbb96f3ea960c06beccce4dc2ffacba2e7ec4 (diff) | |
| download | go-x-website-e77adb1f30f2761cc0e025c1f313b64ffe36a05e.tar.xz | |
tour: serve from cmd/golangorg as go.dev/tour
tour.golang.org is the last independent server in this repository
and almost the last golang.org domain with user-facing content.
(talks.golang.org remains.)
We need to keep golang.org/x/website/tour as a runnable binary,
but move the logic into internal/tour so it can be used from both
the tour binary and cmd/golangorg.
After this is deployed, we will need to delete the current tour app
from the golang-org project, and then requests for tour.golang.org
will default to the main server (cmd/golangorg).
This will make the tour available in China for the first time,
at golang.google.cn/tour.
Change-Id: I0f025d8ae89e12489d26bb3bc380a833eeb57bcc
Reviewed-on: https://go-review.googlesource.com/c/website/+/365100
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/golangorg/csp.go | 44 | ||||
| -rw-r--r-- | cmd/golangorg/server.go | 10 | ||||
| -rw-r--r-- | cmd/golangorg/testdata/tour.txt | 8 |
3 files changed, 46 insertions, 16 deletions
diff --git a/cmd/golangorg/csp.go b/cmd/golangorg/csp.go index b1c02575..73505225 100644 --- a/cmd/golangorg/csp.go +++ b/cmd/golangorg/csp.go @@ -10,26 +10,39 @@ import ( "strings" ) +// buildCSP builds the CSP header. +func buildCSP(kind string) string { + var ks []string + for k := range csp { + ks = append(ks, k) + } + sort.Strings(ks) + if kind == "tour" { + csp["script-src"] = append(csp["script-src"], unsafeEval) + } + + var sb strings.Builder + for _, k := range ks { + sb.WriteString(k) + sb.WriteString(" ") + sb.WriteString(strings.Join(csp[k], " ")) + sb.WriteString("; ") + } + return sb.String() +} + // addCSP returns a handler that adds the appropriate Content-Security-Policy header // to the response and then invokes h. func addCSP(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var ks []string - for k := range csp { - ks = append(ks, k) - } - sort.Strings(ks) + std := buildCSP("") + tour := buildCSP("tour") - var sb strings.Builder - for _, k := range ks { - sb.WriteString(k) - sb.WriteString(" ") - sb.WriteString(strings.Join(csp[k], " ")) - sb.WriteString("; ") + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + csp := std + if strings.HasPrefix(r.URL.Path, "/tour/") { + csp = tour } - - w.Header().Set("Content-Security-Policy", sb.String()) - + w.Header().Set("Content-Security-Policy", csp) h.ServeHTTP(w, r) }) } @@ -38,6 +51,7 @@ const ( self = "'self'" none = "'none'" unsafeInline = "'unsafe-inline'" + unsafeEval = "'unsafe-eval'" ) var csp = map[string][]string{ diff --git a/cmd/golangorg/server.go b/cmd/golangorg/server.go index 86876da5..de5c0a4d 100644 --- a/cmd/golangorg/server.go +++ b/cmd/golangorg/server.go @@ -43,6 +43,7 @@ import ( "golang.org/x/website/internal/proxy" "golang.org/x/website/internal/redirect" "golang.org/x/website/internal/short" + "golang.org/x/website/internal/tour" "golang.org/x/website/internal/web" "golang.org/x/website/internal/webtest" ) @@ -139,7 +140,7 @@ func NewHandler(contentDir, goroot string) http.Handler { if contentDir != "" { contentFS = os.DirFS(contentDir) } else { - contentFS = website.Content + contentFS = website.Content() } var gorootFS fs.FS @@ -171,6 +172,7 @@ func NewHandler(contentDir, goroot string) http.Handler { mux.Handle("golang.org/", redirectPrefix("https://go.dev/")) mux.Handle("blog.golang.org/", redirectPrefix("https://go.dev/blog/")) mux.Handle("learn.go.dev/", redirectPrefix("https://go.dev/learn/")) + mux.Handle("tour.golang.org/", redirectPrefix("https://go.dev/tour/")) // m.golang.org is an old shortcut for golang.org mail. // Gmail itself can serve this redirect, but only on HTTP (not HTTPS). @@ -215,6 +217,10 @@ func NewHandler(contentDir, goroot string) http.Handler { // Note: Registers for golang.org, go.dev/_, and golang.google.cn. proxy.RegisterHandlers(mux) + if err := tour.RegisterHandlers(mux); err != nil { + log.Fatalf("tour: %v", err) + } + var h http.Handler = mux h = addCSP(mux) h = hostEnforcerHandler(h) @@ -386,6 +392,7 @@ var validHosts = map[string]bool{ "blog.golang.org": true, "m.golang.org": true, "tip.golang.org": true, + "tour.golang.org": true, "go.dev": true, "learn.go.dev": true, @@ -469,6 +476,7 @@ type linkRewriter struct { func (r *linkRewriter) WriteHeader(code int) { loc := r.Header().Get("Location") + delete(r.Header(), "Content-Length") // we might change the content if strings.HasPrefix(loc, "/") { r.Header().Set("Location", "/"+r.host+loc) } else if u, _ := url.Parse(loc); u != nil && validHosts[u.Host] { diff --git a/cmd/golangorg/testdata/tour.txt b/cmd/golangorg/testdata/tour.txt new file mode 100644 index 00000000..84ea95e8 --- /dev/null +++ b/cmd/golangorg/testdata/tour.txt @@ -0,0 +1,8 @@ +GET https://tour.golang.org/ +redirect == https://go.dev/tour/ + +GET https://go.dev/tour/ +body contains >A Tour of Go< + +GET https://golang.google.cn/tour/ +body contains >A Tour of Go< |
