Skip to content

Commit af401e3

Browse files
authored
chore: Linter rule for properly formatted api errors (#2123)
* chore: Linter rule for properly formatted api errors * Add omitempty to 'Detail' field
1 parent 3f1e885 commit af401e3

37 files changed

+351
-302
lines changed

coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ func New(options *Options) *API {
123123
)
124124
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
125125
httpapi.Write(w, http.StatusOK, httpapi.Response{
126+
//nolint:gocritic
126127
Message: "👋",
127128
})
128129
})

coderd/csp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func (api *API) logReportCSPViolations(rw http.ResponseWriter, r *http.Request)
2323
if err != nil {
2424
api.Logger.Warn(ctx, "csp violation", slog.Error(err))
2525
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
26-
Message: "Failed to read body, invalid json",
26+
Message: "Failed to read body, invalid json.",
2727
Detail: err.Error(),
2828
})
2929
return

coderd/files.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (api *API) postFile(rw http.ResponseWriter, r *http.Request) {
3232
case "application/x-tar":
3333
default:
3434
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
35-
Message: fmt.Sprintf("Unsupported content type header %q", contentType),
35+
Message: fmt.Sprintf("Unsupported content type header %q.", contentType),
3636
})
3737
return
3838
}
@@ -41,7 +41,7 @@ func (api *API) postFile(rw http.ResponseWriter, r *http.Request) {
4141
data, err := io.ReadAll(r.Body)
4242
if err != nil {
4343
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
44-
Message: "Failed to read file from request",
44+
Message: "Failed to read file from request.",
4545
Detail: err.Error(),
4646
})
4747
return
@@ -65,7 +65,7 @@ func (api *API) postFile(rw http.ResponseWriter, r *http.Request) {
6565
})
6666
if err != nil {
6767
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
68-
Message: "Internal error saving file",
68+
Message: "Internal error saving file.",
6969
Detail: err.Error(),
7070
})
7171
return
@@ -80,7 +80,7 @@ func (api *API) fileByHash(rw http.ResponseWriter, r *http.Request) {
8080
hash := chi.URLParam(r, "hash")
8181
if hash == "" {
8282
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
83-
Message: "File hash must be provided in url",
83+
Message: "File hash must be provided in url.",
8484
})
8585
return
8686
}
@@ -91,7 +91,7 @@ func (api *API) fileByHash(rw http.ResponseWriter, r *http.Request) {
9191
}
9292
if err != nil {
9393
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
94-
Message: "Internal error fetching file",
94+
Message: "Internal error fetching file.",
9595
Detail: err.Error(),
9696
})
9797
return

coderd/gitsshkey.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
2121
privateKey, publicKey, err := gitsshkey.Generate(api.SSHKeygenAlgorithm)
2222
if err != nil {
2323
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
24-
Message: "Internal error generating a new SSH keypair",
24+
Message: "Internal error generating a new SSH keypair.",
2525
Detail: err.Error(),
2626
})
2727
return
@@ -35,7 +35,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
3535
})
3636
if err != nil {
3737
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
38-
Message: "Internal error updating user's git SSH key",
38+
Message: "Internal error updating user's git SSH key.",
3939
Detail: err.Error(),
4040
})
4141
return
@@ -44,7 +44,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
4444
newKey, err := api.Database.GetGitSSHKey(r.Context(), user.ID)
4545
if err != nil {
4646
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
47-
Message: "Internal error fetching user's git SSH key",
47+
Message: "Internal error fetching user's git SSH key.",
4848
Detail: err.Error(),
4949
})
5050
return
@@ -69,7 +69,7 @@ func (api *API) gitSSHKey(rw http.ResponseWriter, r *http.Request) {
6969
gitSSHKey, err := api.Database.GetGitSSHKey(r.Context(), user.ID)
7070
if err != nil {
7171
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
72-
Message: "Internal error fetching user's SSH key",
72+
Message: "Internal error fetching user's SSH key.",
7373
Detail: err.Error(),
7474
})
7575
return
@@ -89,7 +89,7 @@ func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
8989
resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), agent.ResourceID)
9090
if err != nil {
9191
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
92-
Message: "Internal error fetching workspace resource",
92+
Message: "Internal error fetching workspace resource.",
9393
Detail: err.Error(),
9494
})
9595
return
@@ -98,7 +98,7 @@ func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
9898
job, err := api.Database.GetWorkspaceBuildByJobID(r.Context(), resource.JobID)
9999
if err != nil {
100100
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
101-
Message: "Internal error fetching workspace build",
101+
Message: "Internal error fetching workspace build.",
102102
Detail: err.Error(),
103103
})
104104
return
@@ -107,7 +107,7 @@ func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
107107
workspace, err := api.Database.GetWorkspaceByID(r.Context(), job.WorkspaceID)
108108
if err != nil {
109109
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
110-
Message: "Internal error fetching workspace",
110+
Message: "Internal error fetching workspace.",
111111
Detail: err.Error(),
112112
})
113113
return
@@ -116,7 +116,7 @@ func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
116116
gitSSHKey, err := api.Database.GetGitSSHKey(r.Context(), workspace.OwnerID)
117117
if err != nil {
118118
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
119-
Message: "Internal error fetching git SSH key",
119+
Message: "Internal error fetching git SSH key.",
120120
Detail: err.Error(),
121121
})
122122
return

coderd/httpapi/httpapi.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ type Response struct {
6363
// err.Error() text.
6464
// - "database: too many open connections"
6565
// - "stat: too many open files"
66-
Detail string `json:"detail"`
66+
Detail string `json:"detail,omitempty"`
6767
// Validations are form field-specific friendly error messages. They will be
6868
// shown on a form field in the UI. These can also be used to add additional
6969
// context if there is a set of errors in the primary 'Message'.
@@ -78,7 +78,7 @@ type Error struct {
7878

7979
func Forbidden(rw http.ResponseWriter) {
8080
Write(rw, http.StatusForbidden, Response{
81-
Message: "Forbidden",
81+
Message: "Forbidden.",
8282
})
8383
}
8484

@@ -107,7 +107,7 @@ func Read(rw http.ResponseWriter, r *http.Request, value interface{}) bool {
107107
err := json.NewDecoder(r.Body).Decode(value)
108108
if err != nil {
109109
Write(rw, http.StatusBadRequest, Response{
110-
Message: "Request body must be valid JSON",
110+
Message: "Request body must be valid JSON.",
111111
Detail: err.Error(),
112112
})
113113
return false
@@ -123,14 +123,14 @@ func Read(rw http.ResponseWriter, r *http.Request, value interface{}) bool {
123123
})
124124
}
125125
Write(rw, http.StatusBadRequest, Response{
126-
Message: "Validation failed",
126+
Message: "Validation failed.",
127127
Validations: apiErrors,
128128
})
129129
return false
130130
}
131131
if err != nil {
132132
Write(rw, http.StatusInternalServerError, Response{
133-
Message: "Internal error validating request body payload",
133+
Message: "Internal error validating request body payload.",
134134
Detail: err.Error(),
135135
})
136136
return false

coderd/httpapi/httpapi_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestWrite(t *testing.T) {
2020
t.Parallel()
2121
rw := httptest.NewRecorder()
2222
httpapi.Write(rw, http.StatusOK, httpapi.Response{
23-
Message: "wow",
23+
Message: "Wow.",
2424
})
2525
var m map[string]interface{}
2626
err := json.NewDecoder(rw.Body).Decode(&m)

coderd/httpmw/apikey.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,15 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
6565
}
6666
if cookieValue == "" {
6767
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
68-
Message: fmt.Sprintf("Cookie %q or query parameter must be provided", SessionTokenKey),
68+
Message: fmt.Sprintf("Cookie %q or query parameter must be provided.", SessionTokenKey),
6969
})
7070
return
7171
}
7272
parts := strings.Split(cookieValue, "-")
7373
// APIKeys are formatted: ID-SECRET
7474
if len(parts) != 2 {
7575
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
76-
Message: fmt.Sprintf("Invalid %q cookie API key format", SessionTokenKey),
76+
Message: fmt.Sprintf("Invalid %q cookie API key format.", SessionTokenKey),
7777
})
7878
return
7979
}
@@ -82,26 +82,26 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
8282
// Ensuring key lengths are valid.
8383
if len(keyID) != 10 {
8484
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
85-
Message: fmt.Sprintf("Invalid %q cookie API key id", SessionTokenKey),
85+
Message: fmt.Sprintf("Invalid %q cookie API key id.", SessionTokenKey),
8686
})
8787
return
8888
}
8989
if len(keySecret) != 22 {
9090
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
91-
Message: fmt.Sprintf("Invalid %q cookie API key secret", SessionTokenKey),
91+
Message: fmt.Sprintf("Invalid %q cookie API key secret.", SessionTokenKey),
9292
})
9393
return
9494
}
9595
key, err := db.GetAPIKeyByID(r.Context(), keyID)
9696
if err != nil {
9797
if errors.Is(err, sql.ErrNoRows) {
9898
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
99-
Message: "API key is invalid",
99+
Message: "API key is invalid.",
100100
})
101101
return
102102
}
103103
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
104-
Message: "Internal error fetching API key by id",
104+
Message: "Internal error fetching API key by id.",
105105
Detail: err.Error(),
106106
})
107107
return
@@ -111,7 +111,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
111111
// Checking to see if the secret is valid.
112112
if subtle.ConstantTimeCompare(key.HashedSecret, hashed[:]) != 1 {
113113
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
114-
Message: "API key secret is invalid",
114+
Message: "API key secret is invalid.",
115115
})
116116
return
117117
}
@@ -128,7 +128,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
128128
oauthConfig = oauth.Github
129129
default:
130130
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
131-
Message: fmt.Sprintf("Unexpected authentication type %q", key.LoginType),
131+
Message: fmt.Sprintf("Unexpected authentication type %q.", key.LoginType),
132132
})
133133
return
134134
}
@@ -140,7 +140,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
140140
}).Token()
141141
if err != nil {
142142
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
143-
Message: "Could not refresh expired Oauth token",
143+
Message: "Could not refresh expired Oauth token.",
144144
Detail: err.Error(),
145145
})
146146
return
@@ -156,7 +156,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
156156
// Checking if the key is expired.
157157
if key.ExpiresAt.Before(now) {
158158
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
159-
Message: fmt.Sprintf("API key expired at %q", key.ExpiresAt.String()),
159+
Message: fmt.Sprintf("API key expired at %q.", key.ExpiresAt.String()),
160160
})
161161
return
162162
}
@@ -184,7 +184,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
184184
})
185185
if err != nil {
186186
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
187-
Message: fmt.Sprintf("API key couldn't update: %s", err.Error()),
187+
Message: fmt.Sprintf("API key couldn't update: %s.", err.Error()),
188188
})
189189
return
190190
}
@@ -196,7 +196,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
196196
roles, err := db.GetAuthorizationUserRoles(r.Context(), key.UserID)
197197
if err != nil {
198198
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
199-
Message: "Internal error fetching user's roles",
199+
Message: "Internal error fetching user's roles.",
200200
Detail: err.Error(),
201201
})
202202
return

coderd/httpmw/apikey_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func TestAPIKey(t *testing.T) {
3232
successHandler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
3333
// Only called if the API key passes through the handler.
3434
httpapi.Write(rw, http.StatusOK, httpapi.Response{
35-
Message: "it worked!",
35+
Message: "It worked!",
3636
})
3737
})
3838

@@ -203,7 +203,7 @@ func TestAPIKey(t *testing.T) {
203203
// Checks that it exists on the context!
204204
_ = httpmw.APIKey(r)
205205
httpapi.Write(rw, http.StatusOK, httpapi.Response{
206-
Message: "it worked!",
206+
Message: "It worked!",
207207
})
208208
})).ServeHTTP(rw, r)
209209
res := rw.Result()
@@ -241,7 +241,7 @@ func TestAPIKey(t *testing.T) {
241241
// Checks that it exists on the context!
242242
_ = httpmw.APIKey(r)
243243
httpapi.Write(rw, http.StatusOK, httpapi.Response{
244-
Message: "it worked!",
244+
Message: "It worked!",
245245
})
246246
})).ServeHTTP(rw, r)
247247
res := rw.Result()

coderd/httpmw/httpmw.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID
1515
rawID := chi.URLParam(r, param)
1616
if rawID == "" {
1717
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
18-
Message: "Missing UUID in URL",
18+
Message: "Missing UUID in URL.",
1919
// Url params mean nothing to a user
2020
Detail: fmt.Sprintf("%q URL param missing", param),
2121
})
@@ -25,7 +25,7 @@ func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID
2525
parsed, err := uuid.Parse(rawID)
2626
if err != nil {
2727
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
28-
Message: fmt.Sprintf("Invalid UUID %q", param),
28+
Message: fmt.Sprintf("Invalid UUID %q.", param),
2929
Detail: err.Error(),
3030
})
3131
return uuid.UUID{}, false

coderd/httpmw/oauth2.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func ExtractOAuth2(config OAuth2Config) func(http.Handler) http.Handler {
6363
state, err := cryptorand.String(32)
6464
if err != nil {
6565
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
66-
Message: "Internal error generating state string",
66+
Message: "Internal error generating state string.",
6767
Detail: err.Error(),
6868
})
6969
return
@@ -92,21 +92,21 @@ func ExtractOAuth2(config OAuth2Config) func(http.Handler) http.Handler {
9292

9393
if state == "" {
9494
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
95-
Message: "State must be provided",
95+
Message: "State must be provided.",
9696
})
9797
return
9898
}
9999

100100
stateCookie, err := r.Cookie(oauth2StateCookieName)
101101
if err != nil {
102102
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
103-
Message: fmt.Sprintf("Cookie %q must be provided", oauth2StateCookieName),
103+
Message: fmt.Sprintf("Cookie %q must be provided.", oauth2StateCookieName),
104104
})
105105
return
106106
}
107107
if stateCookie.Value != state {
108108
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
109-
Message: "State mismatched",
109+
Message: "State mismatched.",
110110
})
111111
return
112112
}
@@ -120,7 +120,7 @@ func ExtractOAuth2(config OAuth2Config) func(http.Handler) http.Handler {
120120
oauthToken, err := config.Exchange(r.Context(), code)
121121
if err != nil {
122122
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
123-
Message: "Internal error exchanging Oauth code",
123+
Message: "Internal error exchanging Oauth code.",
124124
Detail: err.Error(),
125125
})
126126
return

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy