internal/redirect: add special case for /issues/new for multiple templates

For golang/go#29839.

Change-Id: Ic6ff96d0d1321946df7f19a9f4af889e90255cb1
Reviewed-on: https://go-review.googlesource.com/c/website/+/369154
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
diff --git a/internal/redirect/redirect.go b/internal/redirect/redirect.go
index 6496663..0c1d227 100644
--- a/internal/redirect/redirect.go
+++ b/internal/redirect/redirect.go
@@ -38,6 +38,9 @@
 	for path, redirect := range blogRedirects {
 		mux.Handle("/blog"+path, Handler("/blog/"+redirect))
 	}
+	for _, path := range newIssueRedirects {
+		mux.Handle(path, newIssueHandler(path))
+	}
 	// NB: /src/pkg (sans trailing slash) is the index of packages.
 	mux.HandleFunc("/src/pkg/", srcPkgHandler)
 	mux.HandleFunc("/cl/", clHandler)
@@ -100,9 +103,7 @@
 	"/cl":         "https://go-review.googlesource.com",
 	"/cmd/godoc/": "https://pkg.go.dev/golang.org/x/tools/cmd/godoc",
 	"/issue":      "https://github.com/golang/go/issues",
-	"/issue/new":  "https://github.com/golang/go/issues/new",
 	"/issues":     "https://github.com/golang/go/issues",
-	"/issues/new": "https://github.com/golang/go/issues/new",
 	"/design":     "https://go.googlesource.com/proposal/+/master/design",
 
 	// In Go 1.2 the references page is part of /doc/.
@@ -135,6 +136,13 @@
 	"/doc/go_tutorial.html":                          "/tour",
 }
 
+var newIssueRedirects = [...]string{
+	"/issue/new",
+	"/issue/new/",
+	"/issues/new",
+	"/issues/new/",
+}
+
 var prefixHelpers = map[string]string{
 	"issue":  "https://github.com/golang/go/issues/",
 	"issues": "https://github.com/golang/go/issues/",
@@ -170,6 +178,32 @@
 	})
 }
 
+// newIssueHandler handles /issue/new and similar requests,
+// redirecting to a "New Issue" UI in the main Go issue tracker.
+func newIssueHandler(source string) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.Path != source {
+			http.Error(w, "Not found", http.StatusNotFound)
+			return
+		}
+		target := "https://github.com/golang/go/issues/new"
+		if qs := r.URL.RawQuery; qs == "" {
+			// There are many "go.dev/issue/new" links that led to a good experience
+			// of reporting an issue when there was a single issue template.
+			// As of CL 366736 there are many templates, and the same URL results
+			// in an empty new issue UI, which defeats having any templates.
+			//
+			// Handle this case specially and redirect to "/new/choose" instead,
+			// at least until GitHub changes their behavior. See go.dev/issue/29839.
+			target += "/choose"
+		} else {
+			// Query options like ?title=...&body=...&labels=... only work on /new.
+			target += "?" + qs
+		}
+		http.Redirect(w, r, target, http.StatusFound)
+	})
+}
+
 // Redirect requests from the old "/src/pkg/foo" to the new "/src/foo".
 // See https://golang.org/s/go14nopkg
 func srcPkgHandler(w http.ResponseWriter, r *http.Request) {
diff --git a/internal/redirect/redirect_test.go b/internal/redirect/redirect_test.go
index ee2f67c..0ffdf23 100644
--- a/internal/redirect/redirect_test.go
+++ b/internal/redirect/redirect_test.go
@@ -46,11 +46,16 @@
 		"/issue":                    {301, "https://github.com/golang/go/issues"},
 		"/issue?":                   {301, "https://github.com/golang/go/issues"},
 		"/issue/1":                  {302, "https://github.com/golang/go/issues/1"},
-		"/issue/new":                {301, "https://github.com/golang/go/issues/new"},
-		"/issue/new?a=b&c=d%20&e=f": {301, "https://github.com/golang/go/issues/new?a=b&c=d%20&e=f"},
+		"/issue/new":                {302, "https://github.com/golang/go/issues/new/choose"},
+		"/issue/new/":               {302, "https://github.com/golang/go/issues/new/choose"},
+		"/issue/new?a=b&c=d%20&e=f": {302, "https://github.com/golang/go/issues/new?a=b&c=d%20&e=f"},
+		"/issue/new/choose":         errorResult(404),
 		"/issues":                   {301, "https://github.com/golang/go/issues"},
 		"/issues/1":                 {302, "https://github.com/golang/go/issues/1"},
-		"/issues/new":               {301, "https://github.com/golang/go/issues/new"},
+		"/issues/new":               {302, "https://github.com/golang/go/issues/new/choose"},
+		"/issues/new/":              {302, "https://github.com/golang/go/issues/new/choose"},
+		"/issues/new?title=pkg":     {302, "https://github.com/golang/go/issues/new?title=pkg"},
+		"/issues/new/choose":        errorResult(404),
 		"/issues/1/2/3":             errorResult(404),
 
 		"/wiki/foo":  {302, "https://github.com/golang/go/wiki/foo"},