From da84f9e5be4a0e220a2121fc25c89bdab0434574 Mon Sep 17 00:00:00 2001 From: Scott Windsor Date: Tue, 5 Sep 2023 14:41:33 -0700 Subject: [PATCH 1/2] fix: Cache control 404 asset requests (#15327) * backfill cache control header tests for ui assets Signed-off-by: Scott Windsor * Set cache-control header non-cache for assets not found Signed-off-by: Scott Windsor * fix golang-cilint warning Signed-off-by: Scott Windsor --------- Signed-off-by: Scott Windsor --- server/server.go | 6 ++- server/server_norace_test.go | 8 ++-- server/server_test.go | 86 +++++++++++++++++++++++++++++++++--- 3 files changed, 90 insertions(+), 10 deletions(-) diff --git a/server/server.go b/server/server.go index 4dff6de3621b4..9a7b92cd02ed8 100644 --- a/server/server.go +++ b/server/server.go @@ -1218,7 +1218,11 @@ func (server *ArgoCDServer) newStaticAssetsHandler() func(http.ResponseWriter, * http.ServeContent(w, r, "index.html", modTime, io.NewByteReadSeeker(data)) } else { if isMainJsBundle(r.URL) { - w.Header().Set("Cache-Control", "public, max-age=31536000, immutable") + cacheControl := "public, max-age=31536000, immutable" + if !fileRequest { + cacheControl = "no-cache" + } + w.Header().Set("Cache-Control", cacheControl) } http.FileServer(server.staticAssets).ServeHTTP(w, r) } diff --git a/server/server_norace_test.go b/server/server_norace_test.go index 1fef9a90f02fd..eaef2e67257d1 100644 --- a/server/server_norace_test.go +++ b/server/server_norace_test.go @@ -27,7 +27,7 @@ func TestUserAgent(t *testing.T) { // the data race, it APPEARS to be intentional, but in any case it's nothing we are doing in Argo CD // that is causing this issue. - s, closer := fakeServer() + s, closer := fakeServer(t) defer closer() lns, err := s.Listen() assert.NoError(t, err) @@ -94,7 +94,7 @@ func Test_StaticHeaders(t *testing.T) { // Test default policy "sameorigin" and "frame-ancestors 'self';" { - s, closer := fakeServer() + s, closer := fakeServer(t) defer closer() lns, err := s.Listen() assert.NoError(t, err) @@ -121,7 +121,7 @@ func Test_StaticHeaders(t *testing.T) { // Test custom policy for X-Frame-Options and Content-Security-Policy { - s, closer := fakeServer() + s, closer := fakeServer(t) defer closer() s.XFrameOptions = "deny" s.ContentSecurityPolicy = "frame-ancestors 'none';" @@ -150,7 +150,7 @@ func Test_StaticHeaders(t *testing.T) { // Test disabled X-Frame-Options and Content-Security-Policy { - s, closer := fakeServer() + s, closer := fakeServer(t) defer closer() s.XFrameOptions = "" s.ContentSecurityPolicy = "" diff --git a/server/server_test.go b/server/server_test.go index b304313bc1bc6..303f938871f38 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -7,6 +7,8 @@ import ( "net/http" "net/http/httptest" "net/url" + "os" + "path/filepath" "strings" "testing" "time" @@ -37,7 +39,12 @@ import ( testutil "github.com/argoproj/argo-cd/v2/util/test" ) -func fakeServer() (*ArgoCDServer, func()) { +type FakeArgoCDServer struct { + *ArgoCDServer + TmpAssetsDir string +} + +func fakeServer(t *testing.T) (*FakeArgoCDServer, func()) { cm := test.NewFakeConfigMap() secret := test.NewFakeSecret() kubeclientset := fake.NewSimpleClientset(cm, secret) @@ -45,6 +52,7 @@ func fakeServer() (*ArgoCDServer, func()) { redis, closer := test.NewInMemoryRedis() port, err := test.GetFreePort() mockRepoClient := &mocks.Clientset{RepoServerServiceClient: &mocks.RepoServerServiceClient{}} + tmpAssetsDir := t.TempDir() if err != nil { panic(err) @@ -68,11 +76,13 @@ func fakeServer() (*ArgoCDServer, func()) { 1*time.Minute, 1*time.Minute, ), - RedisClient: redis, - RepoClientset: mockRepoClient, + RedisClient: redis, + RepoClientset: mockRepoClient, + StaticAssetsDir: tmpAssetsDir, } srv := NewServer(context.Background(), argoCDOpts) - return srv, closer + fakeSrv := &FakeArgoCDServer{srv, tmpAssetsDir} + return fakeSrv, closer } func TestEnforceProjectToken(t *testing.T) { @@ -393,7 +403,7 @@ func TestRevokedToken(t *testing.T) { } func TestCertsAreNotGeneratedInInsecureMode(t *testing.T) { - s, closer := fakeServer() + s, closer := fakeServer(t) defer closer() assert.True(t, s.Insecure) assert.Nil(t, s.settings.Certificate) @@ -1230,6 +1240,72 @@ func TestIsMainJsBundle(t *testing.T) { } } +func TestCacheControlHeaders(t *testing.T) { + testCases := []struct { + name string + filename string + createFile bool + expectedStatus int + expectedCacheControlHeaders []string + }{ + { + name: "file exists", + filename: "exists.html", + createFile: true, + expectedStatus: 200, + expectedCacheControlHeaders: nil, + }, + { + name: "file does not exist", + filename: "missing.html", + createFile: false, + expectedStatus: 404, + expectedCacheControlHeaders: nil, + }, + { + name: "main js bundle exists", + filename: "main.e4188e5adc97bbfc00c3.js", + createFile: true, + expectedStatus: 200, + expectedCacheControlHeaders: []string{"public, max-age=31536000, immutable"}, + }, + { + name: "main js bundle does not exists", + filename: "main.e4188e5adc97bbfc00c0.js", + createFile: false, + expectedStatus: 404, + expectedCacheControlHeaders: []string{"no-cache"}, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + argocd, closer := fakeServer(t) + defer closer() + + handler := argocd.newStaticAssetsHandler() + + rr := httptest.NewRecorder() + req := httptest.NewRequest("", fmt.Sprintf("/%s", testCase.filename), nil) + + fp := filepath.Join(argocd.TmpAssetsDir, testCase.filename) + + if testCase.createFile { + tmpFile, err := os.Create(fp) + assert.NoError(t, err) + err = tmpFile.Close() + assert.NoError(t, err) + } + + handler(rr, req) + + assert.Equal(t, testCase.expectedStatus, rr.Code) + + cacheControl := rr.Result().Header["Cache-Control"] + assert.Equal(t, testCase.expectedCacheControlHeaders, cacheControl) + }) + } +} func TestReplaceBaseHRef(t *testing.T) { testCases := []struct { name string From eba40d4dec9b88a7d4cdee5d645193a6aaa0cf47 Mon Sep 17 00:00:00 2001 From: Prasad Katti Date: Tue, 5 Sep 2023 15:35:00 -0700 Subject: [PATCH 2/2] docs: Fixes a markdown typo in USERS.md (#15362) This removes the whitespace between the link text and the link URL. Signed-off-by: Prasad Katti --- USERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/USERS.md b/USERS.md index 4c3e447e14023..fe5e0ddbe8c06 100644 --- a/USERS.md +++ b/USERS.md @@ -277,7 +277,7 @@ Currently, the following organizations are **officially** using Argo CD: 1. [Trendyol](https://www.trendyol.com/) 1. [tru.ID](https://tru.id) 1. [Trusting Social](https://trustingsocial.com/) -1. [Twilio Segment] (https://segment.com/) +1. [Twilio Segment](https://segment.com/) 1. [Twilio SendGrid](https://sendgrid.com) 1. [tZERO](https://www.tzero.com/) 1. [U.S. Veterans Affairs Department](https://www.va.gov/)