Skip to content

Commit 7c63da7

Browse files
committed
internal/frontend: add serveDetailsPage
serveDetailsPage is added, which replaces servePackagePageNew in serving details pages when the "use-directories" experiment flag is on. Like servePackagePageNew, serveDetailsPages supports the package/directory views. It also supports the module view, so that we can stop using LegacyModuleInfo and reading from modules.readme_file_path and modules.readme_contents. For golang/go#39629 Change-Id: I8e664bf1e9174a630db6b723c949ba1e9aa0dc9b Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/241397 Reviewed-by: Jonathan Amsterdam <[email protected]>
1 parent 329d947 commit 7c63da7

File tree

5 files changed

+91
-68
lines changed

5 files changed

+91
-68
lines changed

internal/frontend/details.go

+79-29
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,10 @@ func (s *Server) serveDetails(w http.ResponseWriter, r *http.Request) (err error
7474
if err := validatePathAndVersion(ctx, s.ds, urlInfo.fullPath, urlInfo.requestedVersion); err != nil {
7575
return err
7676
}
77-
var (
78-
resolvedModulePath = urlInfo.modulePath
79-
resolvedVersion = urlInfo.requestedVersion
80-
)
77+
78+
urlInfo.resolvedVersion = urlInfo.requestedVersion
8179
if experiment.IsActive(ctx, internal.ExperimentUsePathInfo) {
82-
resolvedModulePath, resolvedVersion, _, err = s.ds.GetPathInfo(ctx, urlInfo.fullPath, urlInfo.modulePath, urlInfo.requestedVersion)
80+
resolvedModulePath, resolvedVersion, _, err := s.ds.GetPathInfo(ctx, urlInfo.fullPath, urlInfo.modulePath, urlInfo.requestedVersion)
8381
if err != nil {
8482
if !errors.Is(err, derrors.NotFound) {
8583
return err
@@ -90,50 +88,102 @@ func (s *Server) serveDetails(w http.ResponseWriter, r *http.Request) (err error
9088
}
9189
return s.servePathNotFoundPage(w, r, urlInfo.fullPath, urlInfo.modulePath, urlInfo.requestedVersion, pathType)
9290
}
91+
urlInfo.modulePath = resolvedModulePath
92+
urlInfo.resolvedVersion = resolvedVersion
93+
94+
if isActivePathAtMaster(ctx) && urlInfo.requestedVersion == internal.MasterVersion {
95+
// Since path@master is a moving target, we don't want it to be stale.
96+
// As a result, we enqueue every request of path@master to the frontend
97+
// task queue, which will initiate a fetch request depending on the
98+
// last time we tried to fetch this module version.
99+
go func() {
100+
if err := s.queue.ScheduleFetch(ctx, urlInfo.modulePath, internal.MasterVersion, "", s.taskIDChangeInterval); err != nil {
101+
log.Errorf(ctx, "serveDetails(%q): %v", r.URL.Path, err)
102+
}
103+
}()
104+
}
93105
}
94-
if isActivePathAtMaster(ctx) && urlInfo.requestedVersion == internal.MasterVersion {
95-
// Since path@master is a moving target, we don't want it to be stale.
96-
// As a result, we enqueue every request of path@master to the frontend
97-
// task queue, which will initiate a fetch request depending on the
98-
// last time we tried to fetch this module version.
99-
go func() {
100-
if err := s.queue.ScheduleFetch(ctx, resolvedModulePath, internal.MasterVersion, "", s.taskIDChangeInterval); err != nil {
101-
log.Errorf(ctx, "serveDetails(%q): %v", r.URL.Path, err)
102-
}
103-
}()
106+
if isActiveUseDirectories(ctx) {
107+
return s.serveDetailsPage(w, r, urlInfo)
104108
}
105-
// Depending on what the request was for, return the module or package page.
106-
if urlInfo.isModule || urlInfo.fullPath == stdlib.ModulePath {
107-
return s.legacyServeModulePage(w, r, urlInfo.fullPath, urlInfo.requestedVersion, resolvedVersion)
109+
return s.legacyServeDetailsPage(w, r, urlInfo)
110+
}
111+
112+
// serveDetailsPage serves a details page for a path using the paths,
113+
// modules, documentation, readmes, licenses, and package_imports tables.
114+
func (s *Server) serveDetailsPage(w http.ResponseWriter, r *http.Request, info *urlPathInfo) (err error) {
115+
defer derrors.Wrap(&err, "serveDetailsPage(w, r, %v)", info)
116+
ctx := r.Context()
117+
vdir, err := s.ds.GetDirectoryNew(ctx, info.fullPath, info.modulePath, info.resolvedVersion)
118+
if err != nil {
119+
return err
108120
}
109-
if isActiveUseDirectories(ctx) {
110-
return s.servePackagePageNew(w, r, urlInfo.fullPath, resolvedModulePath, urlInfo.requestedVersion, resolvedVersion)
121+
switch {
122+
case info.isModule:
123+
var readme *internal.Readme
124+
if vdir.Readme != nil {
125+
readme = &internal.Readme{Filepath: vdir.Readme.Filepath, Contents: vdir.Readme.Contents}
126+
}
127+
return s.serveModulePageWithModule(ctx, w, r, &vdir.ModuleInfo, readme, info.requestedVersion)
128+
case vdir.Package != nil:
129+
return s.servePackagePageWithVersionedDirectory(ctx, w, r, vdir, info.requestedVersion)
130+
default:
131+
// TODO(https://golang.org/issue/39629): add function to get
132+
// subdirectories from the paths table, and deprecate LegacyGetDirectory.
133+
dir, err := s.ds.LegacyGetDirectory(ctx, info.fullPath, info.modulePath, info.resolvedVersion, internal.AllFields)
134+
if err != nil {
135+
return err
136+
}
137+
return s.legacyServeDirectoryPage(ctx, w, r, dir, info.requestedVersion)
111138
}
112-
return s.legacyServePackagePage(w, r, urlInfo.fullPath, resolvedModulePath, urlInfo.requestedVersion, resolvedVersion)
139+
}
140+
141+
// legacyServeDetailsPage serves a details page for a path using the packages,
142+
// modules, licenses and imports tables.
143+
func (s *Server) legacyServeDetailsPage(w http.ResponseWriter, r *http.Request, info *urlPathInfo) (err error) {
144+
defer derrors.Wrap(&err, "legacyServeDetailsPage(w, r, %v)", info)
145+
if info.isModule {
146+
return s.legacyServeModulePage(w, r, info.fullPath, info.requestedVersion, info.resolvedVersion)
147+
}
148+
return s.legacyServePackagePage(w, r, info.fullPath, info.modulePath, info.requestedVersion, info.resolvedVersion)
113149
}
114150

115151
type urlPathInfo struct {
116-
fullPath, modulePath, requestedVersion string
117-
isModule bool
118-
urlPath string
152+
// fullPath is the full import path corresponding to the requested
153+
// package/module/directory page.
154+
fullPath string
155+
// isModule indicates whether the /mod page should be shown.
156+
isModule bool
157+
// modulePath is the path of the module corresponding to the fullPath and
158+
// resolvedVersion. If unknown, it is set to internal.UnknownModulePath.
159+
modulePath string
160+
// requestedVersion is the version requested by the user, which will be one
161+
// of the following: "latest", "master", a Go version tag, or a semantic
162+
// version.
163+
requestedVersion string
164+
// resolvedVersion is the semantic version stored in the database.
165+
resolvedVersion string
119166
}
120167

121168
func extractURLPathInfo(urlPath string) (_ *urlPathInfo, err error) {
122169
defer derrors.Wrap(&err, "extractURLPathInfo(%q)", urlPath)
123170

124-
info := &urlPathInfo{urlPath: urlPath}
171+
info := &urlPathInfo{}
125172
if strings.HasPrefix(urlPath, "/mod/") {
126-
info.urlPath = strings.TrimPrefix(urlPath, "/mod")
173+
urlPath = strings.TrimPrefix(urlPath, "/mod")
127174
info.isModule = true
128175
}
129176
// Parse the fullPath, modulePath and requestedVersion, based on whether
130177
// the path is in the stdlib. If unable to parse these elements, return
131178
// http.StatusBadRequest.
132-
if parts := strings.SplitN(strings.TrimPrefix(info.urlPath, "/"), "@", 2); stdlib.Contains(parts[0]) {
133-
info.fullPath, info.requestedVersion, err = parseStdLibURLPath(info.urlPath)
179+
if parts := strings.SplitN(strings.TrimPrefix(urlPath, "/"), "@", 2); stdlib.Contains(parts[0]) {
180+
info.fullPath, info.requestedVersion, err = parseStdLibURLPath(urlPath)
134181
info.modulePath = stdlib.ModulePath
182+
if info.fullPath == stdlib.ModulePath {
183+
info.isModule = true
184+
}
135185
} else {
136-
info.fullPath, info.modulePath, info.requestedVersion, err = parseDetailsURLPath(info.urlPath)
186+
info.fullPath, info.modulePath, info.requestedVersion, err = parseDetailsURLPath(urlPath)
137187
}
138188
if err != nil {
139189
return nil, err

internal/frontend/details_test.go

-8
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ func TestExtractURLPathInfo(t *testing.T) {
2828
modulePath: internal.UnknownModulePath,
2929
requestedVersion: internal.LatestVersion,
3030
isModule: false,
31-
urlPath: "/a.com",
3231
},
3332
},
3433
{
@@ -38,7 +37,6 @@ func TestExtractURLPathInfo(t *testing.T) {
3837
modulePath: internal.UnknownModulePath,
3938
requestedVersion: "v1.2.3",
4039
isModule: false,
41-
urlPath: "/[email protected]",
4240
},
4341
},
4442
{
@@ -48,7 +46,6 @@ func TestExtractURLPathInfo(t *testing.T) {
4846
modulePath: "a.com",
4947
requestedVersion: "v1.2.3",
5048
isModule: false,
51-
urlPath: "/[email protected]/b",
5249
},
5350
},
5451
{
@@ -58,7 +55,6 @@ func TestExtractURLPathInfo(t *testing.T) {
5855
modulePath: "std",
5956
requestedVersion: internal.LatestVersion,
6057
isModule: false,
61-
urlPath: "/encoding/json",
6258
},
6359
},
6460
{
@@ -68,7 +64,6 @@ func TestExtractURLPathInfo(t *testing.T) {
6864
modulePath: "std",
6965
requestedVersion: "v1.12.0",
7066
isModule: false,
71-
urlPath: "/encoding/[email protected]",
7267
},
7368
},
7469
{
@@ -78,7 +73,6 @@ func TestExtractURLPathInfo(t *testing.T) {
7873
modulePath: internal.UnknownModulePath,
7974
requestedVersion: internal.LatestVersion,
8075
isModule: true,
81-
urlPath: "/a.com",
8276
},
8377
},
8478
{
@@ -88,7 +82,6 @@ func TestExtractURLPathInfo(t *testing.T) {
8882
modulePath: internal.UnknownModulePath,
8983
requestedVersion: "v1.2.3",
9084
isModule: true,
91-
urlPath: "/[email protected]",
9285
},
9386
},
9487
{
@@ -98,7 +91,6 @@ func TestExtractURLPathInfo(t *testing.T) {
9891
modulePath: internal.UnknownModulePath,
9992
requestedVersion: internal.LatestVersion,
10093
isModule: false,
101-
urlPath: "/moda.com",
10294
},
10395
},
10496
} {

internal/frontend/module.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ func (s *Server) legacyServeModulePage(w http.ResponseWriter, r *http.Request, m
3131
ctx := r.Context()
3232
mi, err := s.ds.LegacyGetModuleInfo(ctx, modulePath, resolvedVersion)
3333
if err == nil {
34-
return s.legacyServeModulePageWithModule(ctx, w, r, mi, requestedVersion)
34+
readme := &internal.Readme{Filepath: mi.LegacyReadmeFilePath, Contents: mi.LegacyReadmeContents}
35+
return s.serveModulePageWithModule(ctx, w, r, &mi.ModuleInfo, readme, requestedVersion)
3536
}
3637
if !errors.Is(err, derrors.NotFound) {
3738
return err
@@ -48,13 +49,15 @@ func (s *Server) legacyServeModulePage(w http.ResponseWriter, r *http.Request, m
4849
return pathNotFoundError(ctx, "module", modulePath, requestedVersion)
4950
}
5051

51-
func (s *Server) legacyServeModulePageWithModule(ctx context.Context, w http.ResponseWriter, r *http.Request, mi *internal.LegacyModuleInfo, requestedVersion string) error {
52+
func (s *Server) serveModulePageWithModule(ctx context.Context, w http.ResponseWriter, r *http.Request,
53+
mi *internal.ModuleInfo, readme *internal.Readme, requestedVersion string) error {
54+
// TODO(https://github.com/golang/go/issues/40027): read licenses using
55+
// GetLicenses, instead of LegacyGetModuleLicenses.
5256
licenses, err := s.ds.LegacyGetModuleLicenses(ctx, mi.ModulePath, mi.Version)
5357
if err != nil {
5458
return err
5559
}
56-
57-
modHeader := createModule(&mi.ModuleInfo, licensesToMetadatas(licenses), requestedVersion == internal.LatestVersion)
60+
modHeader := createModule(mi, licensesToMetadatas(licenses), requestedVersion == internal.LatestVersion)
5861
tab := r.FormValue("tab")
5962
settings, ok := moduleTabLookup[tab]
6063
if !ok {
@@ -65,7 +68,7 @@ func (s *Server) legacyServeModulePageWithModule(ctx context.Context, w http.Res
6568
var details interface{}
6669
if canShowDetails {
6770
var err error
68-
details, err = fetchDetailsForModule(ctx, r, tab, s.ds, mi, licenses)
71+
details, err = fetchDetailsForModule(ctx, r, tab, s.ds, mi, licenses, readme)
6972
if err != nil {
7073
return fmt.Errorf("error fetching page for %q: %v", tab, err)
7174
}

internal/frontend/package.go

-21
Original file line numberDiff line numberDiff line change
@@ -131,27 +131,6 @@ func (s *Server) legacyServePackagePageWithPackage(ctx context.Context, w http.R
131131
return nil
132132
}
133133

134-
func (s *Server) servePackagePageNew(w http.ResponseWriter, r *http.Request, fullPath, modulePath, requestedVersion, resolvedVersion string) (err error) {
135-
defer func() {
136-
if _, ok := err.(*serverError); !ok {
137-
derrors.Wrap(&err, "servePackagePageNew(w, r, %q, %q, %q)", fullPath, modulePath, requestedVersion)
138-
}
139-
}()
140-
ctx := r.Context()
141-
vdir, err := s.ds.GetDirectoryNew(ctx, fullPath, modulePath, resolvedVersion)
142-
if err != nil {
143-
return err
144-
}
145-
if vdir.Package != nil {
146-
return s.servePackagePageWithVersionedDirectory(ctx, w, r, vdir, requestedVersion)
147-
}
148-
dir, err := s.ds.LegacyGetDirectory(ctx, fullPath, modulePath, resolvedVersion, internal.AllFields)
149-
if err != nil {
150-
return err
151-
}
152-
return s.legacyServeDirectoryPage(ctx, w, r, dir, requestedVersion)
153-
}
154-
155134
// stdlibPathForShortcut returns a path in the stdlib that shortcut should redirect to,
156135
// or the empty string if there is no such path.
157136
func (s *Server) stdlibPathForShortcut(ctx context.Context, shortcut string) (path string, err error) {

internal/frontend/tabs.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -201,17 +201,16 @@ func urlIsVersioned(url *url.URL) bool {
201201

202202
// fetchDetailsForModule returns tab details by delegating to the correct detail
203203
// handler.
204-
func fetchDetailsForModule(ctx context.Context, r *http.Request, tab string, ds internal.DataSource, mi *internal.LegacyModuleInfo, licenses []*licenses.License) (interface{}, error) {
204+
func fetchDetailsForModule(ctx context.Context, r *http.Request, tab string, ds internal.DataSource, mi *internal.ModuleInfo, licenses []*licenses.License, readme *internal.Readme) (interface{}, error) {
205205
switch tab {
206206
case "packages":
207-
return fetchDirectoryDetails(ctx, ds, mi.ModulePath, &mi.ModuleInfo, licensesToMetadatas(licenses), true)
207+
return fetchDirectoryDetails(ctx, ds, mi.ModulePath, mi, licensesToMetadatas(licenses), true)
208208
case "licenses":
209209
return &LicensesDetails{Licenses: transformLicenses(mi.ModulePath, mi.Version, licenses)}, nil
210210
case "versions":
211-
return fetchModuleVersionsDetails(ctx, ds, &mi.ModuleInfo)
211+
return fetchModuleVersionsDetails(ctx, ds, mi)
212212
case "overview":
213-
readme := &internal.Readme{Filepath: mi.LegacyReadmeFilePath, Contents: mi.LegacyReadmeContents}
214-
return constructOverviewDetails(ctx, &mi.ModuleInfo, readme, mi.IsRedistributable, urlIsVersioned(r.URL))
213+
return constructOverviewDetails(ctx, mi, readme, mi.IsRedistributable, urlIsVersioned(r.URL))
215214
}
216215
return nil, fmt.Errorf("BUG: unable to fetch details: unknown tab %q", tab)
217216
}

0 commit comments

Comments
 (0)