aboutsummaryrefslogtreecommitdiff
path: root/internal/api/api.go
diff options
context:
space:
mode:
authorEthan Lee <ethanalee@google.com>2026-03-11 21:00:08 +0000
committerGopher Robot <gobot@golang.org>2026-03-19 11:14:09 -0700
commitab4b6a99d7828154fc803870bbb2f18835d6470b (patch)
tree5c0613956d2f6498d2cb4d5e38d69b80ebe6f9ba /internal/api/api.go
parent6d0faac5e074a8a4e101da820e7e21a8a6c2ff2d (diff)
downloadgo-x-pkgsite-ab4b6a99d7828154fc803870bbb2f18835d6470b.tar.xz
internal/api: implement module metadata endpoint
Change-Id: Id6b8686012803c88c9b7ea71e4b1c0058b7967b0 Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/754861 Auto-Submit: Ethan Lee <ethanalee@google.com> Reviewed-by: Jonathan Amsterdam <jba@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> kokoro-CI: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'internal/api/api.go')
-rw-r--r--internal/api/api.go54
1 files changed, 54 insertions, 0 deletions
diff --git a/internal/api/api.go b/internal/api/api.go
index d27e49b0..97c3b5a1 100644
--- a/internal/api/api.go
+++ b/internal/api/api.go
@@ -158,6 +158,60 @@ func ServePackage(w http.ResponseWriter, r *http.Request, ds internal.DataSource
return serveJSON(w, http.StatusOK, resp)
}
+// ServeModule handles requests for the v1 module metadata endpoint.
+func ServeModule(w http.ResponseWriter, r *http.Request, ds internal.DataSource) (err error) {
+ defer derrors.Wrap(&err, "ServeModule")
+
+ modulePath := strings.TrimPrefix(r.URL.Path, "/v1/module/")
+ if modulePath == "" {
+ return serveErrorJSON(w, http.StatusBadRequest, "missing module path", nil)
+ }
+
+ var params ModuleParams
+ if err := ParseParams(r.URL.Query(), &params); err != nil {
+ return serveErrorJSON(w, http.StatusBadRequest, err.Error(), nil)
+ }
+
+ requestedVersion := params.Version
+ if requestedVersion == "" {
+ requestedVersion = version.Latest
+ }
+
+ // For modules, we can use GetUnitMeta on the module path.
+ um, err := ds.GetUnitMeta(r.Context(), modulePath, modulePath, requestedVersion)
+ if err != nil {
+ if errors.Is(err, derrors.NotFound) {
+ return serveErrorJSON(w, http.StatusNotFound, err.Error(), nil)
+ }
+ return err
+ }
+
+ resp := Module{
+ Path: um.ModulePath,
+ Version: um.Version,
+ IsStandardLibrary: stdlib.Contains(um.ModulePath),
+ IsRedistributable: um.IsRedistributable,
+ }
+ // RepoURL needs to be extracted from source info if available
+ if um.SourceInfo != nil {
+ resp.RepoURL = um.SourceInfo.RepoURL()
+ }
+
+ if params.Readme {
+ readme, err := ds.GetModuleReadme(r.Context(), um.ModulePath, um.Version)
+ if err == nil && readme != nil {
+ resp.Readme = &Readme{
+ Filepath: readme.Filepath,
+ Contents: readme.Contents,
+ }
+ }
+ }
+
+ // Future: handle licenses param.
+
+ return serveJSON(w, http.StatusOK, resp)
+}
+
// needsResolution reports whether the version string is a sentinel like "latest" or "master".
func needsResolution(v string) bool {
return v == version.Latest || v == version.Master || v == version.Main