1// Copyright 2017 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Command server serves get.golang.org, redirecting users to the appropriate
6// getgo installer based on the request path.
7package main
8
9import (
10	"fmt"
11	"net/http"
12	"os"
13	"strings"
14	"time"
15)
16
17const (
18	base             = "https://dl.google.com/go/getgo/"
19	windowsInstaller = base + "installer.exe"
20	linuxInstaller   = base + "installer_linux"
21	macInstaller     = base + "installer_darwin"
22)
23
24// substring-based redirects.
25var stringMatch = map[string]string{
26	// via uname, from bash
27	"MINGW":  windowsInstaller, // Reported as MINGW64_NT-10.0 in git bash
28	"Linux":  linuxInstaller,
29	"Darwin": macInstaller,
30}
31
32func main() {
33	http.HandleFunc("/", handler)
34
35	port := os.Getenv("PORT")
36	if port == "" {
37		port = "8080"
38		fmt.Printf("Defaulting to port %s", port)
39	}
40
41	fmt.Printf("Listening on port %s", port)
42	if err := http.ListenAndServe(fmt.Sprintf(":%s", port), nil); err != nil {
43		fmt.Fprintf(os.Stderr, "http.ListenAndServe: %v", err)
44	}
45}
46
47func handler(w http.ResponseWriter, r *http.Request) {
48	if containsIgnoreCase(r.URL.Path, "installer.exe") {
49		// cache bust
50		http.Redirect(w, r, windowsInstaller+cacheBust(), http.StatusFound)
51		return
52	}
53
54	for match, redirect := range stringMatch {
55		if containsIgnoreCase(r.URL.Path, match) {
56			http.Redirect(w, r, redirect, http.StatusFound)
57			return
58		}
59	}
60
61	http.NotFound(w, r)
62}
63
64func containsIgnoreCase(s, substr string) bool {
65	return strings.Contains(
66		strings.ToLower(s),
67		strings.ToLower(substr),
68	)
69}
70
71func cacheBust() string {
72	return fmt.Sprintf("?%d", time.Now().Nanosecond())
73}
74