Handle oversized requests.

This commit is contained in:
Daniel Krol 2022-06-19 17:49:05 -04:00
parent f472b73a68
commit 62866a0045
3 changed files with 22 additions and 14 deletions

View file

@ -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
}

View file

@ -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",

View file

@ -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
}