diff options
| author | Jonathan Amsterdam <jba@google.com> | 2026-04-07 18:52:05 -0400 |
|---|---|---|
| committer | Jonathan Amsterdam <jba@google.com> | 2026-04-08 13:35:34 -0700 |
| commit | b0096dc799437fdf92fc65135a7141fa8ad358be (patch) | |
| tree | 59514073b525d15fd7917f424d0228ded51e67b9 /internal/api/api_test.go | |
| parent | 0ef8af41d6814a34f239b02ab621c4cfcb8c0019 (diff) | |
| download | go-x-pkgsite-b0096dc799437fdf92fc65135a7141fa8ad358be.tar.xz | |
internal/api: set cache-control headers
Set an HTTP Cache-Control header for all API responses.
Since requests that reference a specific, numbered version apparently
always produce the same response, it is tempting to use the "immutable"
Cache-Control directive so these pages can be cached indefinitely. But
occasionally we must exclude a module. It would be unfortunate if the
module's data lived in caches forever. Instead, we cache such pages for
one day.
Pages that are subject to more rapid change, like those with versions
"latest", "master" and so on, or those that depend on data other than
a module (imported-by, search, etc.) are cached for an hour.
That is an arbitrary value that seems like a good compromise, since
the likelihood of a particular page's value changing in an hour is low.
Change-Id: I21414c22c724220c993c1dd7e7a0b49074efd8b9
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/763782
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ethan Lee <ethanalee@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
Diffstat (limited to 'internal/api/api_test.go')
| -rw-r--r-- | internal/api/api_test.go | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/internal/api/api_test.go b/internal/api/api_test.go index 5d5c9c03..5de0ab6e 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -1053,3 +1053,58 @@ func unmarshalResponse[T any](data []byte) (any, error) { } return nil, errors.Join(err1, err2) } + +func TestCacheControl(t *testing.T) { + ctx := context.Background() + ds := fakedatasource.New() + const modulePath = "example.com" + for _, v := range []string{"v1.0.0", "master"} { + ds.MustInsertModule(ctx, &internal.Module{ + ModuleInfo: internal.ModuleInfo{ + ModulePath: modulePath, + Version: v, + }, + Units: []*internal.Unit{{ + UnitMeta: internal.UnitMeta{ + Path: modulePath, + ModuleInfo: internal.ModuleInfo{ + ModulePath: modulePath, + Version: v, + }, + }, + }}, + }) + } + + for _, test := range []struct { + version string + want string + }{ + {"v1.0.0", "public, max-age=10800"}, + {"latest", "public, max-age=3600"}, + {"master", "public, max-age=3600"}, + {"", "public, max-age=3600"}, + } { + t.Run(test.version, func(t *testing.T) { + url := "/v1/module/" + modulePath + if test.version != "" { + url += "?version=" + test.version + } + r := httptest.NewRequest("GET", url, nil) + w := httptest.NewRecorder() + + if err := ServeModule(w, r, ds); err != nil { + t.Fatal(err) + } + + if w.Code != http.StatusOK { + t.Fatalf("status = %d, want %d", w.Code, http.StatusOK) + } + + got := w.Header().Get("Cache-Control") + if got != test.want { + t.Errorf("Cache-Control = %q, want %q", got, test.want) + } + }) + } +} |
