internal,static: add vuln mode to search modes
When searching by vuln ID on the /vuln page a search for
something other than a vuln ID would default to package
search. This change adds a vuln mode to search prevent that.
Change-Id: I3fbf76d6b4c6c548a8dfc83b4e1243d62d9991cf
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/422909
Reviewed-by: Julie Qiu <julieqiu@google.com>
Run-TryBot: Jamal Carvalho <jamal@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
diff --git a/internal/frontend/search.go b/internal/frontend/search.go
index 4578791..9863338 100644
--- a/internal/frontend/search.go
+++ b/internal/frontend/search.go
@@ -89,7 +89,8 @@
},
}
}
- if path := searchRequestRedirectPath(ctx, ds, cq); path != "" {
+ mode := searchMode(r)
+ if path := searchRequestRedirectPath(ctx, ds, cq, mode); path != "" {
http.Redirect(w, r, path, http.StatusFound)
return nil
}
@@ -98,7 +99,6 @@
if len(filters) > 0 {
symbol = filters[0]
}
- mode := searchMode(r)
var getVulnEntries vulnEntriesFunc
if s.vulnClient != nil {
getVulnEntries = s.vulnClient.GetByModule
@@ -153,6 +153,9 @@
// by symbols.
searchModeSymbol = "symbol"
+ // searchModeVuln is the query param for searching by vuln id.
+ searchModeVuln = "vuln"
+
// symbolSearchFilter is a filter that can be used to indicate that the query
// contains a symbol. For example, searching for "#unmarshal json" indicates
// that unmarshal is a symbol.
@@ -316,13 +319,14 @@
//
// If the user types a name that is in the form of a Go vulnerability ID, we will
// redirect to the page for that ID (whether or not it exists).
-func searchRequestRedirectPath(ctx context.Context, ds internal.DataSource, query string) string {
+func searchRequestRedirectPath(ctx context.Context, ds internal.DataSource, query, mode string) string {
urlSchemeIdx := strings.Index(query, "://")
if urlSchemeIdx > -1 {
query = query[urlSchemeIdx+3:]
}
- if goVulnIDRegexp.MatchString(query) {
- return fmt.Sprintf("/vuln/%s", query)
+ // TODO(go.dev/issue/54465): add support for searching by alias.
+ if goVulnIDRegexp.MatchString(query) || mode == searchModeVuln {
+ return fmt.Sprintf("/vuln/%s?q", query)
}
requestedPath := path.Clean(query)
if !strings.Contains(requestedPath, "/") {
@@ -345,17 +349,19 @@
if len(filters) > 0 {
return searchModeSymbol
}
- mode := rawSearchMode(r)
- if mode == searchModePackage {
+ switch rawSearchMode(r) {
+ case searchModePackage:
+ return searchModePackage
+ case searchModeSymbol:
+ return searchModeSymbol
+ case searchModeVuln:
+ return searchModeVuln
+ default:
+ if shouldDefaultToSymbolSearch(q) {
+ return searchModeSymbol
+ }
return searchModePackage
}
- if mode == searchModeSymbol {
- return searchModeSymbol
- }
- if shouldDefaultToSymbolSearch(q) {
- return searchModeSymbol
- }
- return searchModePackage
}
// searchQueryAndFilters returns the search query, trimmed of any filters, and
diff --git a/internal/frontend/search_test.go b/internal/frontend/search_test.go
index c675fcb..ef6f6bb 100644
--- a/internal/frontend/search_test.go
+++ b/internal/frontend/search_test.go
@@ -50,6 +50,12 @@
q: "foo",
wantSearchMode: searchModeSymbol,
},
+ {
+ name: "search in vuln mode",
+ m: searchModeVuln,
+ q: "foo",
+ wantSearchMode: searchModeVuln,
+ },
} {
t.Run(test.name, func(t *testing.T) {
u := fmt.Sprintf("/search?q=%s&m=%s", test.q, test.m)
@@ -365,21 +371,23 @@
name string
query string
want string
+ mode string
}{
- {"module", "golang.org/x/tools", "/golang.org/x/tools"},
- {"directory", "golang.org/x/tools/internal", "/golang.org/x/tools/internal"},
- {"package", "golang.org/x/tools/internal/lsp", "/golang.org/x/tools/internal/lsp"},
- {"stdlib package does not redirect", "errors", ""},
- {"stdlib package does redirect", "cmd/go", "/cmd/go"},
- {"stdlib directory does redirect", "cmd/go/internal", "/cmd/go/internal"},
- {"std does not redirect", "std", ""},
- {"non-existent path does not redirect", "github.com/non-existent", ""},
- {"trim URL scheme from query", "https://golang.org/x/tools", "/golang.org/x/tools"},
- {"Go vuln redirects", "GO-1969-0720", "/vuln/GO-1969-0720"},
- {"not a Go vuln", "somepkg/GO-1969-0720", ""},
+ {"module", "golang.org/x/tools", "/golang.org/x/tools", ""},
+ {"directory", "golang.org/x/tools/internal", "/golang.org/x/tools/internal", ""},
+ {"package", "golang.org/x/tools/internal/lsp", "/golang.org/x/tools/internal/lsp", ""},
+ {"stdlib package does not redirect", "errors", "", ""},
+ {"stdlib package does redirect", "cmd/go", "/cmd/go", ""},
+ {"stdlib directory does redirect", "cmd/go/internal", "/cmd/go/internal", ""},
+ {"std does not redirect", "std", "", ""},
+ {"non-existent path does not redirect", "github.com/non-existent", "", ""},
+ {"trim URL scheme from query", "https://golang.org/x/tools", "/golang.org/x/tools", ""},
+ {"Go vuln redirects", "GO-1969-0720", "/vuln/GO-1969-0720?q", ""},
+ {"not a Go vuln", "somepkg/GO-1969-0720", "", ""},
+ {"search mode is vuln", "searchmodevuln", "/vuln/searchmodevuln?q", searchModeVuln},
} {
t.Run(test.name, func(t *testing.T) {
- if got := searchRequestRedirectPath(ctx, testDB, test.query); got != test.want {
+ if got := searchRequestRedirectPath(ctx, testDB, test.query, test.mode); got != test.want {
t.Errorf("searchRequestRedirectPath(ctx, %q) = %q; want = %q", test.query, got, test.want)
}
})
diff --git a/internal/frontend/vulns.go b/internal/frontend/vulns.go
index 192cea7..35cdd69 100644
--- a/internal/frontend/vulns.go
+++ b/internal/frontend/vulns.go
@@ -135,6 +135,9 @@
default: // the path should be "/<ID>", e.g. "/GO-2021-0001".
id := r.URL.Path[1:]
if !goVulnIDRegexp.MatchString(id) {
+ if r.URL.Query().Has("q") {
+ return &serverError{status: derrors.ToStatus(derrors.NotFound)}
+ }
return &serverError{
status: http.StatusBadRequest,
responseText: "invalid Go vuln ID; should be GO-YYYY-NNNN",
diff --git a/static/frontend/vuln/main/main.tmpl b/static/frontend/vuln/main/main.tmpl
index dfe177d..b771286 100644
--- a/static/frontend/vuln/main/main.tmpl
+++ b/static/frontend/vuln/main/main.tmpl
@@ -29,6 +29,7 @@
role="search"
>
<input name="q" class="go-Input" placeholder="Search GO IDs" />
+ <input name="m" value="vuln" hidden />
<button class="go-Button">Submit</button>
</form>