From 508e25b6d6e9a81edb6ddf8738450b79898b446a Mon Sep 17 00:00:00 2001 From: Adin Scannell Date: Mon, 27 Apr 2020 22:24:58 -0700 Subject: Adapt website to use g3doc sources and bazel. This adapts the merged website repository to use the image and bazel build framework. It explicitly avoids the container_image rules provided by bazel, opting instead to build with direct docker commands when necessary. The relevant build commands are incorporated into the top-level Makefile. --- website/cmd/server/main.go | 210 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 website/cmd/server/main.go (limited to 'website/cmd/server/main.go') diff --git a/website/cmd/server/main.go b/website/cmd/server/main.go new file mode 100644 index 000000000..18cd525d2 --- /dev/null +++ b/website/cmd/server/main.go @@ -0,0 +1,210 @@ +// Copyright 2019 The gVisor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "fmt" + "log" + "net/http" + "os" + "regexp" + "strings" +) + +var redirects = map[string]string{ + // GitHub redirects. + "/change": "https://github.com/google/gvisor", + "/issue": "https://github.com/google/gvisor/issues", + "/issue/new": "https://github.com/google/gvisor/issues/new", + "/pr": "https://github.com/google/gvisor/pulls", + + // For links. + "/faq": "/docs/user_guide/faq/", + + // Redirects to compatibility docs. + "/c": "/docs/user_guide/compatibility/", + "/c/linux/amd64": "/docs/user_guide/compatibility/linux/amd64/", + + // Redirect for old URLs. + "/docs/user_guide/compatibility/amd64/": "/docs/user_guide/compatibility/linux/amd64/", + "/docs/user_guide/compatibility/amd64": "/docs/user_guide/compatibility/linux/amd64/", + "/docs/user_guide/kubernetes/": "/docs/user_guide/quick_start/kubernetes/", + "/docs/user_guide/kubernetes": "/docs/user_guide/quick_start/kubernetes/", + "/docs/user_guide/oci/": "/docs/user_guide/quick_start/oci/", + "/docs/user_guide/oci": "/docs/user_guide/quick_start/oci/", + "/docs/user_guide/docker/": "/docs/user_guide/quick_start/docker/", + "/docs/user_guide/docker": "/docs/user_guide/quick_start/docker/", + + // Deprecated, but links continue to work. + "/cl": "https://gvisor-review.googlesource.com", +} + +var prefixHelpers = map[string]string{ + "change": "https://github.com/google/gvisor/commit/%s", + "issue": "https://github.com/google/gvisor/issues/%s", + "pr": "https://github.com/google/gvisor/pull/%s", + + // Redirects to compatibility docs. + "c/linux/amd64": "/docs/user_guide/compatibility/linux/amd64/#%s", + + // Deprecated, but links continue to work. + "cl": "https://gvisor-review.googlesource.com/c/gvisor/+/%s", +} + +var ( + validId = regexp.MustCompile(`^[A-Za-z0-9-]*/?$`) + goGetHTML5 = ` + + +Go-get` +) + +// cronHandler wraps an http.Handler to check that the request is from the App +// Engine Cron service. +// See: https://cloud.google.com/appengine/docs/standard/go112/scheduling-jobs-with-cron-yaml#validating_cron_requests +func cronHandler(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("X-Appengine-Cron") != "true" { + http.NotFound(w, r) + return + } + // Fallthrough. + h.ServeHTTP(w, r) + }) +} + +// wrappedHandler wraps an http.Handler. +// +// If the query parameters include go-get=1, then we redirect to a single +// static page that allows us to serve arbitrary Go packages. +func wrappedHandler(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + gg, ok := r.URL.Query()["go-get"] + if ok && len(gg) == 1 && gg[0] == "1" { + // Serve a trivial html page. + w.Write([]byte(goGetHTML5)) + return + } + // Fallthrough. + h.ServeHTTP(w, r) + }) +} + +// redirectWithQuery redirects to the given target url preserving query parameters. +func redirectWithQuery(w http.ResponseWriter, r *http.Request, target string) { + url := target + if qs := r.URL.RawQuery; qs != "" { + url += "?" + qs + } + http.Redirect(w, r, url, http.StatusFound) +} + +// hostRedirectHandler redirects the www. domain to the naked domain. +func hostRedirectHandler(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.HasPrefix(r.Host, "www.") { + // Redirect to the naked domain. + r.URL.Scheme = "https" // Assume https. + r.URL.Host = r.Host[4:] // Remove the 'www.' + http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently) + return + } + + if *projectId != "" && r.Host == *projectId+".appspot.com" && *customHost != "" { + // Redirect to the custom domain. + r.URL.Scheme = "https" // Assume https. + r.URL.Host = *customHost + http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently) + return + } + h.ServeHTTP(w, r) + }) +} + +// prefixRedirectHandler returns a handler that redirects to the given formated url. +func prefixRedirectHandler(prefix, baseURL string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if p := r.URL.Path; p == prefix { + // Redirect /prefix/ to /prefix. + http.Redirect(w, r, p[:len(p)-1], http.StatusFound) + return + } + id := r.URL.Path[len(prefix):] + if !validId.MatchString(id) { + http.Error(w, "Not found", http.StatusNotFound) + return + } + target := fmt.Sprintf(baseURL, id) + redirectWithQuery(w, r, target) + }) +} + +// redirectHandler returns a handler that redirects to the given url. +func redirectHandler(target string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + redirectWithQuery(w, r, target) + }) +} + +// redirectRedirects registers redirect http handlers. +func registerRedirects(mux *http.ServeMux) { + if mux == nil { + mux = http.DefaultServeMux + } + + for prefix, baseURL := range prefixHelpers { + p := "/" + prefix + "/" + mux.Handle(p, hostRedirectHandler(wrappedHandler(prefixRedirectHandler(p, baseURL)))) + } + + for path, redirect := range redirects { + mux.Handle(path, hostRedirectHandler(wrappedHandler(redirectHandler(redirect)))) + } +} + +// registerStatic registers static file handlers +func registerStatic(mux *http.ServeMux, staticDir string) { + if mux == nil { + mux = http.DefaultServeMux + } + mux.Handle("/", hostRedirectHandler(wrappedHandler(http.FileServer(http.Dir(staticDir))))) +} + +func envFlagString(name, def string) string { + if val := os.Getenv(name); val != "" { + return val + } + return def +} + +var ( + addr = flag.String("http", envFlagString("HTTP", ":"+envFlagString("PORT", "8080")), "HTTP service address") + staticDir = flag.String("static-dir", envFlagString("STATIC_DIR", "_site"), "static files directory") + + // Uses the standard GOOGLE_CLOUD_PROJECT environment variable set by App Engine. + projectId = flag.String("project-id", envFlagString("GOOGLE_CLOUD_PROJECT", ""), "The App Engine project ID.") + customHost = flag.String("custom-domain", envFlagString("CUSTOM_DOMAIN", "gvisor.dev"), "The application's custom domain.") +) + +func main() { + flag.Parse() + + registerRedirects(nil) + registerStatic(nil, *staticDir) + + log.Printf("Listening on %s...", *addr) + log.Fatal(http.ListenAndServe(*addr, nil)) +} -- cgit v1.2.3 From 068716ddf36f4dcb3d88e92b90774dcba2fe4db8 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 1 Jul 2020 08:51:57 -0700 Subject: Fix FAQ URL The existing gvisor.dev/faq link returns 404 because the full URL has mistakenly been capitalized. PiperOrigin-RevId: 319233173 --- g3doc/user_guide/BUILD | 2 +- website/_includes/footer-links.html | 2 +- website/cmd/server/main.go | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'website/cmd/server/main.go') diff --git a/g3doc/user_guide/BUILD b/g3doc/user_guide/BUILD index 5568e1ba4..b69aee12c 100644 --- a/g3doc/user_guide/BUILD +++ b/g3doc/user_guide/BUILD @@ -33,7 +33,7 @@ doc( name = "FAQ", src = "FAQ.md", category = "User Guide", - permalink = "/docs/user_guide/FAQ/", + permalink = "/docs/user_guide/faq/", weight = "90", ) diff --git a/website/_includes/footer-links.html b/website/_includes/footer-links.html index 10c28ead4..2036dbaa9 100644 --- a/website/_includes/footer-links.html +++ b/website/_includes/footer-links.html @@ -15,7 +15,7 @@
diff --git a/website/cmd/server/main.go b/website/cmd/server/main.go index 7c8bc9bfa..c401b6abd 100644 --- a/website/cmd/server/main.go +++ b/website/cmd/server/main.go @@ -35,6 +35,10 @@ var redirects = map[string]string{ // For links. "/faq": "/docs/user_guide/faq/", + // From 2020-05-12 to 2020-06-30, the FAQ URL was uppercase. Redirect that + // back to maintain any links. + "/docs/user_guide/FAQ/": "/docs/user_guide/faq/", + // Redirects to compatibility docs. "/c": "/docs/user_guide/compatibility/", "/c/linux/amd64": "/docs/user_guide/compatibility/linux/amd64/", -- cgit v1.2.3