Skip to content

Commit 712da68

Browse files
committed
internal/frontend: move base types to their own packages
This change moves serverError, basePage and errorPage out to different packages so that the fetch page logic can use them but be moved out of internal/frontend. For golang/go#61399 Change-Id: I72ccee40d1847d3211ca851a320530c4c1dcf2e2 Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/517976 TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Michael Matloob <[email protected]> kokoro-CI: kokoro <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 82f79ed commit 712da68

File tree

16 files changed

+265
-214
lines changed

16 files changed

+265
-214
lines changed

internal/frontend/404.go

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"golang.org/x/pkgsite/internal/cookie"
2222
"golang.org/x/pkgsite/internal/derrors"
2323
"golang.org/x/pkgsite/internal/experiment"
24+
"golang.org/x/pkgsite/internal/frontend/page"
25+
"golang.org/x/pkgsite/internal/frontend/serrors"
2426
"golang.org/x/pkgsite/internal/log"
2527
"golang.org/x/pkgsite/internal/stdlib"
2628
"golang.org/x/pkgsite/internal/version"
@@ -29,10 +31,10 @@ import (
2931
// errUnitNotFoundWithoutFetch returns a 404 with instructions to the user on
3032
// how to manually fetch the package. No fetch button is provided. This is used
3133
// for very large modules or modules that previously 500ed.
32-
var errUnitNotFoundWithoutFetch = &serverError{
33-
status: http.StatusNotFound,
34-
epage: &errorPage{
35-
messageTemplate: template.MakeTrustedTemplate(`
34+
var errUnitNotFoundWithoutFetch = &serrors.ServerError{
35+
Status: http.StatusNotFound,
36+
Epage: &page.ErrorPage{
37+
MessageTemplate: template.MakeTrustedTemplate(`
3638
<h3 class="Error-message">{{.StatusText}}</h3>
3739
<p class="Error-message">Check that you entered the URL correctly or try fetching it following the
3840
<a href="/about#adding-a-package">instructions here</a>.</p>`),
@@ -66,15 +68,15 @@ func (s *Server) servePathNotFoundPage(w http.ResponseWriter, r *http.Request,
6668
}
6769

6870
if experiment.IsActive(ctx, internal.ExperimentEnableStdFrontendFetch) {
69-
return &serverError{
70-
status: http.StatusNotFound,
71-
epage: &errorPage{
72-
templateName: "fetch",
71+
return &serrors.ServerError{
72+
Status: http.StatusNotFound,
73+
Epage: &page.ErrorPage{
74+
TemplateName: "fetch",
7375
MessageData: stdlib.ModulePath,
7476
},
7577
}
7678
}
77-
return &serverError{status: http.StatusNotFound}
79+
return &serrors.ServerError{Status: http.StatusNotFound}
7880
}
7981

8082
fr, err := previousFetchStatusAndResponse(ctx, db, fullPath, modulePath, requestedVersion)
@@ -150,10 +152,10 @@ func (s *Server) servePathNotFoundPage(w http.ResponseWriter, r *http.Request,
150152
http.Redirect(w, r, "/search?q="+url.QueryEscape(fullPath), http.StatusFound)
151153
return nil
152154
}
153-
return &serverError{
154-
status: fr.status,
155-
epage: &errorPage{
156-
messageTemplate: uncheckedconversions.TrustedTemplateFromStringKnownToSatisfyTypeContract(`
155+
return &serrors.ServerError{
156+
Status: fr.status,
157+
Epage: &page.ErrorPage{
158+
MessageTemplate: uncheckedconversions.TrustedTemplateFromStringKnownToSatisfyTypeContract(`
157159
<h3 class="Error-message">{{.StatusText}}</h3>
158160
<p class="Error-message">` + html.UnescapeString(fr.responseText) + `</p>`),
159161
MessageData: struct{ StatusText string }{http.StatusText(fr.status)},
@@ -190,24 +192,24 @@ func pathNotFoundError(ctx context.Context, fullPath, requestedVersion string) e
190192
}
191193
if stdlib.Contains(fullPath) {
192194
if experiment.IsActive(ctx, internal.ExperimentEnableStdFrontendFetch) {
193-
return &serverError{
194-
status: http.StatusNotFound,
195-
epage: &errorPage{
196-
templateName: "fetch",
195+
return &serrors.ServerError{
196+
Status: http.StatusNotFound,
197+
Epage: &page.ErrorPage{
198+
TemplateName: "fetch",
197199
MessageData: stdlib.ModulePath,
198200
},
199201
}
200202
}
201-
return &serverError{status: http.StatusNotFound}
203+
return &serrors.ServerError{Status: http.StatusNotFound}
202204
}
203205
path := fullPath
204206
if requestedVersion != version.Latest {
205207
path = fmt.Sprintf("%s@%s", fullPath, requestedVersion)
206208
}
207-
return &serverError{
208-
status: http.StatusNotFound,
209-
epage: &errorPage{
210-
templateName: "fetch",
209+
return &serrors.ServerError{
210+
Status: http.StatusNotFound,
211+
Epage: &page.ErrorPage{
212+
TemplateName: "fetch",
211213
MessageData: path,
212214
},
213215
}
@@ -222,8 +224,8 @@ func previousFetchStatusAndResponse(ctx context.Context, db internal.PostgresDB,
222224
// Get all candidate module paths for this path.
223225
paths, err := modulePathsToFetch(ctx, db, fullPath, modulePath)
224226
if err != nil {
225-
var serr *serverError
226-
if errors.As(err, &serr) && serr.status == http.StatusBadRequest {
227+
var serr *serrors.ServerError
228+
if errors.As(err, &serr) && serr.Status == http.StatusBadRequest {
227229
// Return this as an invalid argument so that we don't log it in
228230
// servePathNotFoundPage above.
229231
return nil, derrors.InvalidArgument

internal/frontend/badge.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ package frontend
77
import (
88
"net/http"
99
"strings"
10+
11+
"golang.org/x/pkgsite/internal/frontend/page"
1012
)
1113

1214
type badgePage struct {
13-
basePage
15+
page.BasePage
1416
// LinkPath is the URL path of the badge will link to.
1517
LinkPath string
1618
// BadgePath is the URL path of the badge SVG.
@@ -35,7 +37,7 @@ func (s *Server) badgeHandler(w http.ResponseWriter, r *http.Request) {
3537
}
3638

3739
page := badgePage{
38-
basePage: s.newBasePage(r, "Badge"),
40+
BasePage: s.newBasePage(r, "Badge"),
3941
LinkPath: path,
4042
BadgePath: "badge/" + path + ".svg",
4143
}

internal/frontend/details.go

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ package frontend
77
import (
88
"context"
99
"errors"
10-
mstats "golang.org/x/pkgsite/internal/middleware/stats"
1110
"net/http"
1211
"strings"
1312

13+
"golang.org/x/pkgsite/internal/frontend/page"
14+
"golang.org/x/pkgsite/internal/frontend/serrors"
15+
mstats "golang.org/x/pkgsite/internal/middleware/stats"
16+
1417
"github.com/google/safehtml/template"
1518
"go.opencensus.io/stats"
1619
"go.opencensus.io/stats/view"
@@ -29,7 +32,7 @@ func (s *Server) serveDetails(w http.ResponseWriter, r *http.Request, ds interna
2932

3033
ctx := r.Context()
3134
if r.Method != http.MethodGet && r.Method != http.MethodHead {
32-
return &serverError{status: http.StatusMethodNotAllowed}
35+
return &serrors.ServerError{Status: http.StatusMethodNotAllowed}
3336
}
3437
if r.URL.Path == "/" {
3538
s.serveHomepage(ctx, w, r)
@@ -50,14 +53,14 @@ func (s *Server) serveDetails(w http.ResponseWriter, r *http.Request, ds interna
5053

5154
urlInfo, err := extractURLPathInfo(r.URL.Path)
5255
if err != nil {
53-
var epage *errorPage
56+
var epage *page.ErrorPage
5457
if uerr := new(userError); errors.As(err, &uerr) {
55-
epage = &errorPage{MessageData: uerr.userMessage}
58+
epage = &page.ErrorPage{MessageData: uerr.userMessage}
5659
}
57-
return &serverError{
58-
status: http.StatusBadRequest,
59-
err: err,
60-
epage: epage,
60+
return &serrors.ServerError{
61+
Status: http.StatusBadRequest,
62+
Err: err,
63+
Epage: epage,
6164
}
6265
}
6366
if !isSupportedVersion(urlInfo.fullPath, urlInfo.requestedVersion) {
@@ -88,10 +91,10 @@ func stdlibRedirectURL(fullPath string) string {
8891
}
8992

9093
func invalidVersionError(fullPath, requestedVersion string) error {
91-
return &serverError{
92-
status: http.StatusBadRequest,
93-
epage: &errorPage{
94-
messageTemplate: template.MakeTrustedTemplate(`
94+
return &serrors.ServerError{
95+
Status: http.StatusBadRequest,
96+
Epage: &page.ErrorPage{
97+
MessageTemplate: template.MakeTrustedTemplate(`
9598
<h3 class="Error-message">{{.Version}} is not a valid semantic version.</h3>
9699
<p class="Error-message">
97100
To search for packages like {{.Path}}, <a href="/search?q={{.Path}}">click here</a>.
@@ -102,10 +105,10 @@ func invalidVersionError(fullPath, requestedVersion string) error {
102105
}
103106

104107
func datasourceNotSupportedErr() error {
105-
return &serverError{
106-
status: http.StatusFailedDependency,
107-
epage: &errorPage{
108-
messageTemplate: template.MakeTrustedTemplate(
108+
return &serrors.ServerError{
109+
Status: http.StatusFailedDependency,
110+
Epage: &page.ErrorPage{
111+
MessageTemplate: template.MakeTrustedTemplate(
109112
`<h3 class="Error-message">This page is not supported by this datasource.</h3>`),
110113
},
111114
}

internal/frontend/fetch.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"golang.org/x/pkgsite/internal/derrors"
2525
"golang.org/x/pkgsite/internal/experiment"
2626
"golang.org/x/pkgsite/internal/fetch"
27+
"golang.org/x/pkgsite/internal/frontend/serrors"
2728
"golang.org/x/pkgsite/internal/log"
2829
"golang.org/x/pkgsite/internal/proxy"
2930
"golang.org/x/pkgsite/internal/queue"
@@ -99,16 +100,16 @@ func (s *Server) serveFetch(w http.ResponseWriter, r *http.Request, ds internal.
99100
if r.Method != http.MethodPost {
100101
// If a user makes a GET request, treat this as a request for the
101102
// "fetch" package, which does not exist.
102-
return &serverError{status: http.StatusNotFound}
103+
return &serrors.ServerError{Status: http.StatusNotFound}
103104
}
104105

105106
urlInfo, err := extractURLPathInfo(strings.TrimPrefix(r.URL.Path, "/fetch"))
106107
if err != nil {
107-
return &serverError{status: http.StatusBadRequest}
108+
return &serrors.ServerError{Status: http.StatusBadRequest}
108109
}
109110
status, responseText := s.fetchAndPoll(r.Context(), ds, urlInfo.modulePath, urlInfo.fullPath, urlInfo.requestedVersion)
110111
if status != http.StatusOK {
111-
return &serverError{status: status, responseText: responseText}
112+
return &serrors.ServerError{Status: status, ResponseText: responseText}
112113
}
113114
return nil
114115
}
@@ -144,9 +145,9 @@ func (s *Server) fetchAndPoll(ctx context.Context, ds internal.DataSource, modul
144145
db := ds.(internal.PostgresDB)
145146
modulePaths, err := modulePathsToFetch(ctx, db, fullPath, modulePath)
146147
if err != nil {
147-
var serr *serverError
148+
var serr *serrors.ServerError
148149
if errors.As(err, &serr) {
149-
return serr.status, http.StatusText(serr.status)
150+
return serr.Status, http.StatusText(serr.Status)
150151
}
151152
log.Errorf(ctx, "fetchAndPoll(ctx, ds, q, %q, %q, %q): %v", modulePath, fullPath, requestedVersion, err)
152153
return http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)
@@ -497,9 +498,9 @@ func modulePathsToFetch(ctx context.Context, ds internal.DataSource, fullPath, m
497498
}
498499
um, err := ds.GetUnitMeta(ctx, fullPath, modulePath, version.Latest)
499500
if err != nil && !errors.Is(err, derrors.NotFound) {
500-
return nil, &serverError{
501-
status: http.StatusInternalServerError,
502-
err: err,
501+
return nil, &serrors.ServerError{
502+
Status: http.StatusInternalServerError,
503+
Err: err,
503504
}
504505
}
505506
if err == nil {
@@ -520,16 +521,16 @@ func candidateModulePaths(fullPath string) (_ []string, err error) {
520521
return []string{stdlib.ModulePath}, nil
521522
}
522523
if !isValidPath(fullPath) {
523-
return nil, &serverError{
524-
status: http.StatusBadRequest,
525-
err: fmt.Errorf("isValidPath(%q): false", fullPath),
524+
return nil, &serrors.ServerError{
525+
Status: http.StatusBadRequest,
526+
Err: fmt.Errorf("isValidPath(%q): false", fullPath),
526527
}
527528
}
528529
paths := internal.CandidateModulePaths(fullPath)
529530
if paths == nil {
530-
return nil, &serverError{
531-
status: http.StatusBadRequest,
532-
err: fmt.Errorf("invalid path: %q", fullPath),
531+
return nil, &serrors.ServerError{
532+
Status: http.StatusBadRequest,
533+
Err: fmt.Errorf("invalid path: %q", fullPath),
533534
}
534535
}
535536
if len(paths) > maxPathsToFetch {

internal/frontend/homepage.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"context"
99
"math/rand"
1010
"net/http"
11+
12+
"golang.org/x/pkgsite/internal/frontend/page"
1113
)
1214

1315
// searchTip represents a snippet of text on the homepage demonstrating
@@ -38,7 +40,7 @@ var searchTips = []searchTip{
3840

3941
// Homepage contains fields used in rendering the homepage template.
4042
type homepage struct {
41-
basePage
43+
page.BasePage
4244

4345
// TipIndex is the index of the initial search tip to render.
4446
TipIndex int
@@ -61,7 +63,7 @@ type LocalModule struct {
6163

6264
func (s *Server) serveHomepage(ctx context.Context, w http.ResponseWriter, r *http.Request) {
6365
s.servePage(ctx, w, "homepage", homepage{
64-
basePage: s.newBasePage(r, "Go Packages"),
66+
BasePage: s.newBasePage(r, "Go Packages"),
6567
SearchTips: searchTips,
6668
TipIndex: rand.Intn(len(searchTips)),
6769
LocalModules: s.localModules,

internal/frontend/page/page.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2023 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+
// Package page defines common fields shared by pages when rendering templages.
6+
package page
7+
8+
import (
9+
"github.com/google/safehtml"
10+
"github.com/google/safehtml/template"
11+
"golang.org/x/pkgsite/internal/experiment"
12+
)
13+
14+
// BasePage contains fields shared by all pages when rendering templates.
15+
type BasePage struct {
16+
// HTMLTitle is the value to use in the page’s <title> tag.
17+
HTMLTitle string
18+
19+
// MetaDescription is the html used for rendering the <meta name="Description"> tag.
20+
MetaDescription safehtml.HTML
21+
22+
// Query is the current search query (if applicable).
23+
Query string
24+
25+
// Experiments contains the experiments currently active.
26+
Experiments *experiment.Set
27+
28+
// DevMode indicates whether the server is running in development mode.
29+
DevMode bool
30+
31+
// LocalMode indicates whether the server is running in local mode (i.e. ./cmd/pkgsite).
32+
LocalMode bool
33+
34+
// AppVersionLabel contains the current version of the app.
35+
AppVersionLabel string
36+
37+
// GoogleTagManagerID is the ID used to load Google Tag Manager.
38+
GoogleTagManagerID string
39+
40+
// AllowWideContent indicates whether the content should be displayed in a
41+
// way that’s amenable to wider viewports.
42+
AllowWideContent bool
43+
44+
// Enables the two and three column layouts on the unit page.
45+
UseResponsiveLayout bool
46+
47+
// SearchPrompt is the prompt/placeholder for search input.
48+
SearchPrompt string
49+
50+
// SearchMode is the search mode for the current search request.
51+
SearchMode string
52+
53+
// SearchModePackage is the value of const searchModePackage. It is used in
54+
// the search bar dropdown.
55+
SearchModePackage string
56+
57+
// SearchModeSymbol is the value of const searchModeSymbol. It is used in
58+
// the search bar dropdown.
59+
SearchModeSymbol string
60+
}
61+
62+
func (p *BasePage) SetBasePage(bp BasePage) {
63+
bp.SearchMode = p.SearchMode
64+
*p = bp
65+
}
66+
67+
// ErrorPage contains fields for rendering a HTTP error page.
68+
type ErrorPage struct {
69+
BasePage
70+
TemplateName string
71+
MessageTemplate template.TrustedTemplate
72+
MessageData any
73+
}

0 commit comments

Comments
 (0)