aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2021-11-18 10:55:19 -0500
committerRuss Cox <rsc@golang.org>2021-11-22 16:43:07 +0000
commite77adb1f30f2761cc0e025c1f313b64ffe36a05e (patch)
tree548df37f9dce15d1906fd645fac2d68ae8bdfe5e /cmd
parentceabbb96f3ea960c06beccce4dc2ffacba2e7ec4 (diff)
downloadgo-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.go44
-rw-r--r--cmd/golangorg/server.go10
-rw-r--r--cmd/golangorg/testdata/tour.txt8
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<