--- /dev/null
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Command server serves get.golang.org, redirecting users to the appropriate
+// getgo installer based on the request path.
+package main
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+ "strings"
+ "time"
+)
+
+const (
+ base = "https://dl.google.com/go/getgo/"
+ windowsInstaller = base + "installer.exe"
+ linuxInstaller = base + "installer_linux"
+ macInstaller = base + "installer_darwin"
+)
+
+// substring-based redirects.
+var stringMatch = map[string]string{
+ // via uname, from bash
+ "MINGW": windowsInstaller, // Reported as MINGW64_NT-10.0 in git bash
+ "Linux": linuxInstaller,
+ "Darwin": macInstaller,
+}
+
+func main() {
+ http.HandleFunc("/", handler)
+
+ port := os.Getenv("PORT")
+ if port == "" {
+ port = "8080"
+ fmt.Printf("Defaulting to port %s", port)
+ }
+
+ fmt.Printf("Listening on port %s", port)
+ if err := http.ListenAndServe(fmt.Sprintf(":%s", port), nil); err != nil {
+ fmt.Fprintf(os.Stderr, "http.ListenAndServe: %v", err)
+ }
+}
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ if containsIgnoreCase(r.URL.Path, "installer.exe") {
+ // cache bust
+ http.Redirect(w, r, windowsInstaller+cacheBust(), http.StatusFound)
+ return
+ }
+
+ for match, redirect := range stringMatch {
+ if containsIgnoreCase(r.URL.Path, match) {
+ http.Redirect(w, r, redirect, http.StatusFound)
+ return
+ }
+ }
+
+ http.NotFound(w, r)
+}
+
+func containsIgnoreCase(s, substr string) bool {
+ return strings.Contains(
+ strings.ToLower(s),
+ strings.ToLower(substr),
+ )
+}
+
+func cacheBust() string {
+ return fmt.Sprintf("?%d", time.Now().Nanosecond())
+}