From dee966f5dc5bb0a2d2d90fd456a83202794de4b7 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 27 Apr 2023 14:10:14 +0200 Subject: [PATCH 1/5] fix: vite fatals on receiving HTTP4xx --- coderd/httpmw/httpmw.go | 2 +- coderd/httpmw/httpmw_internal_test.go | 55 +++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 coderd/httpmw/httpmw_internal_test.go diff --git a/coderd/httpmw/httpmw.go b/coderd/httpmw/httpmw.go index 11f363e7ea244..74dd987248b87 100644 --- a/coderd/httpmw/httpmw.go +++ b/coderd/httpmw/httpmw.go @@ -26,7 +26,7 @@ func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID parsed, err := uuid.Parse(rawID) if err != nil { httpapi.Write(r.Context(), rw, http.StatusBadRequest, codersdk.Response{ - Message: fmt.Sprintf("Invalid UUID %q.", param), + Message: fmt.Sprintf("Invalid UUID %q.", rawID), Detail: err.Error(), }) return uuid.UUID{}, false diff --git a/coderd/httpmw/httpmw_internal_test.go b/coderd/httpmw/httpmw_internal_test.go new file mode 100644 index 0000000000000..381c8608d2649 --- /dev/null +++ b/coderd/httpmw/httpmw_internal_test.go @@ -0,0 +1,55 @@ +package httpmw + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-chi/chi/v5" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/coder/coder/codersdk" +) + +const ( + testParam = "workspaceagent" + testWorkspaceAgentID = "8a70c576-12dc-42bc-b791-112a32b5bd43" +) + +func TestParseUUID_Valid(t *testing.T) { + t.Parallel() + + rw := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/{workspaceagent}", nil) + + ctx := chi.NewRouteContext() + ctx.URLParams.Add(testParam, testWorkspaceAgentID) + r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, ctx)) + + parsed, ok := parseUUID(rw, r, "workspaceagent") + assert.True(t, ok, "UUID should be parsed") + assert.Equal(t, testWorkspaceAgentID, parsed.String()) +} + +func TestParseUUID_Invalid(t *testing.T) { + t.Parallel() + + rw := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/{workspaceagent}", nil) + + ctx := chi.NewRouteContext() + ctx.URLParams.Add(testParam, "wrong-id") + r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, ctx)) + + _, ok := parseUUID(rw, r, "workspaceagent") + assert.False(t, ok, "UUID should not be parsed") + assert.Equal(t, http.StatusBadRequest, rw.Code) + + var response codersdk.Response + err := json.Unmarshal(rw.Body.Bytes(), &response) + require.NoError(t, err) + assert.Contains(t, response.Message, `Invalid UUID "wrong-id"`) +} From ffe08a6a8180c6b61d611902d1e850ce279e9503 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 27 Apr 2023 15:16:43 +0200 Subject: [PATCH 2/5] tune Vite --- coderd/workspaceagents.go | 5 ++++- site/vite.config.ts | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go index 1b58c9f2c3c0c..8eff756376a31 100644 --- a/coderd/workspaceagents.go +++ b/coderd/workspaceagents.go @@ -447,7 +447,10 @@ func (api *API) workspaceAgentStartupLogs(rw http.ResponseWriter, r *http.Reques api.WebsocketWaitGroup.Add(1) api.WebsocketWaitMutex.Unlock() defer api.WebsocketWaitGroup.Done() - conn, err := websocket.Accept(rw, r, nil) + conn, err := websocket.Accept(rw, r, &websocket.AcceptOptions{ + // Vite in development mode can't cross-access this port. + OriginPatterns: []string{"localhost:8080"}, + }) if err != nil { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Failed to accept websocket.", diff --git a/site/vite.config.ts b/site/vite.config.ts index 9c0d2f50a76ba..e775f89745311 100644 --- a/site/vite.config.ts +++ b/site/vite.config.ts @@ -37,6 +37,16 @@ export default defineConfig({ changeOrigin: true, target: process.env.CODER_HOST || "http://localhost:3000", secure: process.env.NODE_ENV === "production", + configure: (proxy) => { + // Vite does not catch socket errors, and stops the webserver. + // As /startup-logs endpoint can return HTTP 4xx status, we need to embrace + // Vite with a custom error handler to prevent from quitting. + proxy.on('proxyReqWs', (proxyReq, req, socket) => { + socket.on('error', (error) => { + console.error(error); + }); + }); + }, }, "/swagger": { target: process.env.CODER_HOST || "http://localhost:3000", From b8f1a9d464593a6d3caf6f6de853595008b21c4d Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 27 Apr 2023 15:23:34 +0200 Subject: [PATCH 3/5] fmt --- site/vite.config.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/site/vite.config.ts b/site/vite.config.ts index e775f89745311..70a2633a95e54 100644 --- a/site/vite.config.ts +++ b/site/vite.config.ts @@ -41,11 +41,11 @@ export default defineConfig({ // Vite does not catch socket errors, and stops the webserver. // As /startup-logs endpoint can return HTTP 4xx status, we need to embrace // Vite with a custom error handler to prevent from quitting. - proxy.on('proxyReqWs', (proxyReq, req, socket) => { - socket.on('error', (error) => { - console.error(error); - }); - }); + proxy.on("proxyReqWs", (proxyReq, req, socket) => { + socket.on("error", (error) => { + console.error(error) + }) + }) }, }, "/swagger": { From 282fc2cc0f9b640a4172569b0ddc6c585269064f Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 27 Apr 2023 16:55:32 +0200 Subject: [PATCH 4/5] rewrite --- coderd/workspaceagents.go | 5 +---- site/vite.config.ts | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go index 8eff756376a31..1b58c9f2c3c0c 100644 --- a/coderd/workspaceagents.go +++ b/coderd/workspaceagents.go @@ -447,10 +447,7 @@ func (api *API) workspaceAgentStartupLogs(rw http.ResponseWriter, r *http.Reques api.WebsocketWaitGroup.Add(1) api.WebsocketWaitMutex.Unlock() defer api.WebsocketWaitGroup.Done() - conn, err := websocket.Accept(rw, r, &websocket.AcceptOptions{ - // Vite in development mode can't cross-access this port. - OriginPatterns: []string{"localhost:8080"}, - }) + conn, err := websocket.Accept(rw, r, nil) if err != nil { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Failed to accept websocket.", diff --git a/site/vite.config.ts b/site/vite.config.ts index 70a2633a95e54..019223b32049a 100644 --- a/site/vite.config.ts +++ b/site/vite.config.ts @@ -42,6 +42,10 @@ export default defineConfig({ // As /startup-logs endpoint can return HTTP 4xx status, we need to embrace // Vite with a custom error handler to prevent from quitting. proxy.on("proxyReqWs", (proxyReq, req, socket) => { + if (process.env.NODE_ENV === "development") { + proxyReq.setHeader('origin', process.env.CODER_HOST || "http://localhost:3000"); + } + socket.on("error", (error) => { console.error(error) }) From 6de9a17775cd31ea9b29d7a5f03cb880b3f02068 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Thu, 27 Apr 2023 16:57:11 +0200 Subject: [PATCH 5/5] fmt --- site/vite.config.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/site/vite.config.ts b/site/vite.config.ts index 019223b32049a..72816177d7675 100644 --- a/site/vite.config.ts +++ b/site/vite.config.ts @@ -43,7 +43,10 @@ export default defineConfig({ // Vite with a custom error handler to prevent from quitting. proxy.on("proxyReqWs", (proxyReq, req, socket) => { if (process.env.NODE_ENV === "development") { - proxyReq.setHeader('origin', process.env.CODER_HOST || "http://localhost:3000"); + proxyReq.setHeader( + "origin", + process.env.CODER_HOST || "http://localhost:3000", + ) } socket.on("error", (error) => {