cmd,internal: change search timeout error page

Symbol search requests for popular symbols (such as "New") can
occasionally timeout.

Rather than return a 500 if a request times out, return a 408 and ask
the user to try again.

This will prevent on-callers from being paged if a request times out for
symbol search, and it is very likely the request will succeed on the
second try.

Change-Id: Ic0ffe02261f94c931fc26e76490f1bca87b9f566
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/355369
Trust: Julie Qiu <julie@golang.org>
Run-TryBot: Julie Qiu <julie@golang.org>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
diff --git a/internal/frontend/search.go b/internal/frontend/search.go
index c43da71..4c0beec 100644
--- a/internal/frontend/search.go
+++ b/internal/frontend/search.go
@@ -101,6 +101,17 @@
 	mode := searchMode(r)
 	page, err := fetchSearchPage(ctx, db, cq, symbol, pageParams, mode == searchModeSymbol, s.getVulnEntries)
 	if err != nil {
+		// Instead of returning a 500, return a 408, since symbol searches may
+		// timeout for very popular symbols.
+		if mode == searchModeSymbol && strings.Contains(err.Error(), "i/o timeout") {
+			return &serverError{
+				status: http.StatusRequestTimeout,
+				epage: &errorPage{
+					messageTemplate: template.MakeTrustedTemplate(
+						`<h3 class="Error-message">Request timed out. Please try again!</h3>`),
+				},
+			}
+		}
 		return fmt.Errorf("fetchSearchPage(ctx, db, %q): %v", cq, err)
 	}
 	page.basePage = s.newBasePage(r, fmt.Sprintf("%s - Search Results", cq))