diff --git a/server/server.go b/server/server.go index 4413ff5..01bead6 100644 --- a/server/server.go +++ b/server/server.go @@ -82,16 +82,6 @@ func requestOverhead(w http.ResponseWriter, req *http.Request, method string) bo return false } - /* - TODO - http.StatusRequestEntityTooLarge for some arbitrary large size - see: - * MaxBytesReader or LimitReader - * https://pkg.go.dev/net/http#Request.ParseForm - * some library/framework that handles it (along with req.Method) - - also - GET params too large? - */ - return true } @@ -100,14 +90,31 @@ type PostRequest interface { validate() bool } +// TODO decoder.DisallowUnknownFields? +// TODO GET params too large (like StatusRequestEntityTooLarge)? Or is that +// somehow handled by the http library due to a size limit in the http spec? + // Confirm it's a Post request, various overhead, decode the json, validate the struct func getPostData(w http.ResponseWriter, req *http.Request, reqStruct PostRequest) bool { if !requestOverhead(w, req, http.MethodPost) { return false } - if err := json.NewDecoder(req.Body).Decode(&reqStruct); err != nil { - errorJson(w, http.StatusBadRequest, "Request body JSON malformed or structure mismatch") + // Make the limit 100k. Increase from there as needed. I'd rather block some + // people's large wallets and increase the limit than OOM for everybody and + // decrease the limit. + req.Body = http.MaxBytesReader(w, req.Body, 100000) + err := json.NewDecoder(req.Body).Decode(&reqStruct) + switch { + case err == nil: + break + case err.Error() == "http: request body too large": + errorJson(w, http.StatusRequestEntityTooLarge, "") + return false + default: + // Maybe we can suss out specific errors later. Need to study what errors + // come from Decode. + errorJson(w, http.StatusBadRequest, "Error parsing JSON") return false } diff --git a/server/server_test.go b/server/server_test.go index 838ed2a..df7bc19 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -158,7 +158,7 @@ func TestServerHelperGetPostDataErrors(t *testing.T) { { name: "request body too large", method: http.MethodPost, - requestBody: fmt.Sprintf(`{"key": "%s"}`, strings.Repeat("a", 10000)), + requestBody: fmt.Sprintf(`{"key": "%s"}`, strings.Repeat("a", 100000)), expectedStatusCode: http.StatusRequestEntityTooLarge, expectedErrorString: http.StatusText(http.StatusRequestEntityTooLarge), }, @@ -167,7 +167,7 @@ func TestServerHelperGetPostDataErrors(t *testing.T) { method: http.MethodPost, requestBody: "{", expectedStatusCode: http.StatusBadRequest, - expectedErrorString: http.StatusText(http.StatusBadRequest) + ": Request body JSON malformed or structure mismatch", + expectedErrorString: http.StatusText(http.StatusBadRequest) + ": Error parsing JSON", }, { name: "body JSON failed validation", diff --git a/store/store.go b/store/store.go index c18fd40..cd200d6 100644 --- a/store/store.go +++ b/store/store.go @@ -379,6 +379,7 @@ func (s *Store) CreateAccount(email auth.Email, password auth.Password) (err err // Maybe for psql it will be? // TODO - is this right? Does the above comment explain that it's backwards // from what I would have expected? Or did I do this backwards? + // Or is this a holdover from when an account was attached to a walletstate? if errors.Is(sqliteErr.ExtendedCode, sqlite3.ErrConstraintPrimaryKey) { err = ErrDuplicateEmail }