Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve consistency in API of FormFields maxFields and maxLength #12718

Open
wants to merge 7 commits into
base: jetty-12.1.x
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,7 @@ public static void setFields(Request request, Fields fields)
*/
public static Fields getFields(Request request)
{
int maxFields = getContextAttribute(request.getContext(), FormFields.MAX_FIELDS_ATTRIBUTE, FormFields.MAX_FIELDS_DEFAULT);
int maxLength = getContextAttribute(request.getContext(), FormFields.MAX_LENGTH_ATTRIBUTE, FormFields.MAX_LENGTH_DEFAULT);
return getFields(request, maxFields, maxLength);
return getFields(request, -1, -1);
}

/**
Expand All @@ -129,15 +127,19 @@ public static Fields getFields(Request request)
* Calls to {@code onFields} and {@code getFields} methods are idempotent, and
* can be called multiple times, with subsequent calls returning the results of the first call.
* @param request The request to get or read the Fields from
* @param maxFields The maximum number of fields to accept or -1 for unlimited
* @param maxLength The maximum length of fields or -1 for unlimited.
* @param maxFields The maximum number of fields to accept or -1 for a default.
* @param maxLength The maximum length of fields or -1 for a default.
* @return the Fields
* @see #onFields(Request, Promise.Invocable)
* @see #onFields(Request, Charset, Promise.Invocable)
* @see #getFields(Request)
*/
public static Fields getFields(Request request, int maxFields, int maxLength)
{
if (maxFields < 0)
maxFields = getContextAttribute(request.getContext(), FormFields.MAX_FIELDS_ATTRIBUTE, FormFields.MAX_FIELDS_DEFAULT);
if (maxLength < 0)
maxLength = getContextAttribute(request.getContext(), FormFields.MAX_LENGTH_ATTRIBUTE, FormFields.MAX_LENGTH_DEFAULT);
Charset charset = getFormEncodedCharset(request);
return from(request, InvocationType.NON_BLOCKING, request, charset, maxFields, maxLength).join();
}
Expand All @@ -154,15 +156,20 @@ public static Fields getFields(Request request, int maxFields, int maxLength)
* @param attributes The {@link Attributes} in which to look for an existing {@link CompletableFuture} of
* {@link FormFields}, using the classname as the attribute name. If not found the attribute
* is set with the created {@link CompletableFuture} of {@link FormFields}.
* @param charset the {@link Charset} to use for byte to string conversion. * @param maxFields The maximum number of fields to accept
* @param maxLength The maximum length of fields
* @param charset the {@link Charset} to use for byte to string conversion.
* @param maxFields The maximum number of fields to accept or -1 for a default.
* @param maxLength The maximum length of fields or -1 for a default.
* @return the Fields
* @see #onFields(Request, Promise.Invocable)
* @see #onFields(Request, Charset, Promise.Invocable)
* @see #getFields(Request)
*/
public static Fields getFields(Content.Source source, Attributes attributes, Charset charset, int maxFields, int maxLength)
{
if (maxFields < 0)
maxFields = FormFields.MAX_FIELDS_DEFAULT;
if (maxLength < 0)
maxLength = FormFields.MAX_FIELDS_DEFAULT;
return from(source, InvocationType.NON_BLOCKING, attributes, charset, maxFields, maxLength).join();
}

Expand Down Expand Up @@ -206,8 +213,8 @@ public static void onFields(Request request, Charset charset, Promise.Invocable<
*
* @param request The request to get or read the Fields from
* @param charset The {@link Charset} of the request content, if previously extracted.
* @param maxFields The maximum number of fields to accept; or -1 for a default
* @param maxLength The maximum length of fields; or -1 for a default
* @param maxFields The maximum number of fields to accept; or -1 for a default.
* @param maxLength The maximum length of fields; or -1 for a default.
* @param promise The action to take when the FormFields are available.
*/
public static void onFields(Request request, Charset charset, int maxFields, int maxLength, Promise.Invocable<Fields> promise)
Expand Down Expand Up @@ -247,9 +254,7 @@ else if (attr instanceof Fields fields)
@Deprecated(forRemoval = true, since = "12.0.15")
public static CompletableFuture<Fields> from(Request request)
{
int maxFields = getContextAttribute(request.getContext(), FormFields.MAX_FIELDS_ATTRIBUTE, FormFields.MAX_FIELDS_DEFAULT);
int maxLength = getContextAttribute(request.getContext(), FormFields.MAX_LENGTH_ATTRIBUTE, FormFields.MAX_LENGTH_DEFAULT);
return from(request, maxFields, maxLength);
return from(request, -1, -1);
}

/**
Expand All @@ -264,18 +269,16 @@ public static CompletableFuture<Fields> from(Request request)
@Deprecated(forRemoval = true, since = "12.0.15")
public static CompletableFuture<Fields> from(Request request, Charset charset)
{
int maxFields = getContextAttribute(request.getContext(), FormFields.MAX_FIELDS_ATTRIBUTE, FormFields.MAX_FIELDS_DEFAULT);
int maxLength = getContextAttribute(request.getContext(), FormFields.MAX_LENGTH_ATTRIBUTE, FormFields.MAX_LENGTH_DEFAULT);
return from(request, charset, maxFields, maxLength);
return from(request, charset, -1, -1);
}

/**
* Find or create a {@link FormFields} from a {@link Content.Source}.
* @param request The {@link Request} in which to look for an existing {@link FormFields} attribute,
* using the classname as the attribute name, else the request is used
* as a {@link Content.Source} from which to read the fields and set the attribute.
* @param maxFields The maximum number of fields to be parsed or -1 for unlimited
* @param maxLength The maximum total size of the fields or -1 for unlimited
* @param maxFields The maximum number of fields to be parsed or -1 for a default.
* @param maxLength The maximum total size of the fields or -1 for a default.
* @return A {@link CompletableFuture} that will provide the {@link Fields} or a failure.
* @deprecated use {@link #onFields(Request, Charset, int, int, Promise.Invocable)} instead.
*/
Expand All @@ -291,14 +294,18 @@ public static CompletableFuture<Fields> from(Request request, int maxFields, int
* using the classname as the attribute name, else the request is used
* as a {@link Content.Source} from which to read the fields and set the attribute.
* @param charset the {@link Charset} to use for byte to string conversion.
* @param maxFields The maximum number of fields to be parsed or -1 for unlimited
* @param maxLength The maximum total size of the fields or -1 for unlimited
* @param maxFields The maximum number of fields to be parsed or -1 for a default.
* @param maxLength The maximum total size of the fields or -1 for a default.
* @return A {@link CompletableFuture} that will provide the {@link Fields} or a failure.
* @deprecated use {@link #onFields(Request, Charset, int, int, Promise.Invocable)} instead.
*/
@Deprecated(forRemoval = true, since = "12.0.15")
public static CompletableFuture<Fields> from(Request request, Charset charset, int maxFields, int maxLength)
{
if (maxFields < 0)
maxFields = getContextAttribute(request.getContext(), FormFields.MAX_FIELDS_ATTRIBUTE, FormFields.MAX_FIELDS_DEFAULT);
if (maxLength < 0)
maxLength = getContextAttribute(request.getContext(), FormFields.MAX_LENGTH_ATTRIBUTE, FormFields.MAX_LENGTH_DEFAULT);
return from(request, InvocationType.NON_BLOCKING, request, charset, maxFields, maxLength);
}

Expand All @@ -310,8 +317,8 @@ public static CompletableFuture<Fields> from(Request request, Charset charset, i
* {@link FormFields}, using the classname as the attribute name. If not found the attribute
* is set with the created {@link CompletableFuture} of {@link FormFields}.
* @param charset the {@link Charset} to use for byte to string conversion.
* @param maxFields The maximum number of fields to be parsed
* @param maxLength The maximum total size of the fields
* @param maxFields The maximum number of fields to be parsed or -1 for unlimited.
* @param maxLength The maximum total size of the fields or -1 for unlimited.
* @return A {@link CompletableFuture} that will provide the {@link Fields} or a failure.
*/
static CompletableFuture<Fields> from(Content.Source source, InvocationType invocationType, Attributes attributes, Charset charset, int maxFields, int maxLength)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,9 @@ public String[] getWelcomeFiles()
return _welcomeFiles;
}

/**
* @return the maximum size of the form content (in bytes).
*/
@ManagedAttribute("The maximum content size")
public int getMaxFormContentSize()
{
Expand All @@ -675,13 +678,19 @@ public int getMaxFormContentSize()
/**
* Set the maximum size of a form post, to protect against DOS attacks from large forms.
*
* @param maxSize the maximum size of the form content (in bytes)
* @param maxSize the maximum size of the form content (in bytes) or -1 for a default value.
*/
public void setMaxFormContentSize(int maxSize)
{
if (maxSize < 0)
maxSize = Integer.getInteger(MAX_FORM_CONTENT_SIZE_KEY, DEFAULT_MAX_FORM_CONTENT_SIZE);
_maxFormContentSize = maxSize;
}

/**
* @return the maximum number of form Keys.
*/
@ManagedAttribute("The maximum number of form keys")
public int getMaxFormKeys()
{
return _maxFormKeys;
Expand All @@ -690,10 +699,12 @@ public int getMaxFormKeys()
/**
* Set the maximum number of form Keys to protect against DOS attack from crafted hash keys.
*
* @param max the maximum number of form keys
* @param max the maximum number of form keys or -1 for a default value.
*/
public void setMaxFormKeys(int max)
{
if (max < 0)
max = Integer.getInteger(MAX_FORM_KEYS_KEY, DEFAULT_MAX_FORM_KEYS);
_maxFormKeys = max;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
})
.send();

int expected = (maxFormContentSize != null && maxFormContentSize < 0)
? HttpStatus.OK_200
: HttpStatus.BAD_REQUEST_400;
assertEquals(expected, response.getStatus());
assertEquals(HttpStatus.BAD_REQUEST_400, response.getStatus());
}

public static Stream<Integer> formKeysScenarios()
Expand Down Expand Up @@ -193,10 +190,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
.body(new FormRequestContent(formParams))
.send();

int expected = (maxFormKeys != null && maxFormKeys < 0)
? HttpStatus.OK_200
: HttpStatus.BAD_REQUEST_400;
assertEquals(expected, response.getStatus());
assertEquals(HttpStatus.BAD_REQUEST_400, response.getStatus());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,9 @@ public String[] getWelcomeFiles()
return _welcomeFiles;
}

/**
* @return the maximum size of the form content (in bytes).
*/
@ManagedAttribute("The maximum content size")
public int getMaxFormContentSize()
{
Expand All @@ -673,13 +676,19 @@ public int getMaxFormContentSize()
/**
* Set the maximum size of a form post, to protect against DOS attacks from large forms.
*
* @param maxSize the maximum size of the form content (in bytes)
* @param maxSize the maximum size of the form content (in bytes) or -1 for a default value.
*/
public void setMaxFormContentSize(int maxSize)
{
if (maxSize < 0)
maxSize = Integer.getInteger(MAX_FORM_CONTENT_SIZE_KEY, DEFAULT_MAX_FORM_CONTENT_SIZE);
_maxFormContentSize = maxSize;
}

/**
* @return the maximum number of form Keys.
*/
@ManagedAttribute("The maximum number of form keys")
public int getMaxFormKeys()
{
return _maxFormKeys;
Expand All @@ -688,10 +697,12 @@ public int getMaxFormKeys()
/**
* Set the maximum number of form Keys to protect against DOS attack from crafted hash keys.
*
* @param max the maximum number of form keys
* @param max the maximum number of form keys or -1 for a default value.
*/
public void setMaxFormKeys(int max)
{
if (max < 0)
max = Integer.getInteger(MAX_FORM_KEYS_KEY, DEFAULT_MAX_FORM_KEYS);
_maxFormKeys = max;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
})
.send();

int expected = (maxFormContentSize != null && maxFormContentSize < 0)
? HttpStatus.OK_200
: HttpStatus.BAD_REQUEST_400;
assertEquals(expected, response.getStatus());
assertEquals(HttpStatus.BAD_REQUEST_400, response.getStatus());
}

public static Stream<Integer> formKeysScenarios()
Expand Down Expand Up @@ -193,10 +190,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
.body(new FormRequestContent(formParams))
.send();

int expected = (maxFormKeys != null && maxFormKeys < 0)
? HttpStatus.OK_200
: HttpStatus.BAD_REQUEST_400;
assertEquals(expected, response.getStatus());
assertEquals(HttpStatus.BAD_REQUEST_400, response.getStatus());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,9 @@ public void setErrorHandler(ErrorHandler errorHandler)
_errorHandler = errorHandler;
}

/**
* @return the maximum size of the form content (in bytes).
*/
@ManagedAttribute("The maximum content size")
public int getMaxFormContentSize()
{
Expand All @@ -1386,13 +1389,19 @@ public int getMaxFormContentSize()
/**
* Set the maximum size of a form post, to protect against DOS attacks from large forms.
*
* @param maxSize the maximum size of the form content (in bytes)
* @param maxSize the maximum size of the form content (in bytes) or -1 for a default value.
*/
public void setMaxFormContentSize(int maxSize)
{
if (maxSize < 0)
maxSize = Integer.getInteger(MAX_FORM_CONTENT_SIZE_KEY, DEFAULT_MAX_FORM_CONTENT_SIZE);
_maxFormContentSize = maxSize;
}

/**
* @return the maximum number of form Keys.
*/
@ManagedAttribute("The maximum number of form keys")
public int getMaxFormKeys()
{
return _maxFormKeys;
Expand All @@ -1401,10 +1410,12 @@ public int getMaxFormKeys()
/**
* Set the maximum number of form Keys to protect against DOS attack from crafted hash keys.
*
* @param max the maximum number of form keys
* @param max the maximum number of form keys or -1 for a default value.
*/
public void setMaxFormKeys(int max)
{
if (max < 0)
max = Integer.getInteger(MAX_FORM_KEYS_KEY, DEFAULT_MAX_FORM_KEYS);
_maxFormKeys = max;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2052,7 +2052,12 @@ private Collection<Part> getParts(Fields params) throws IOException
else
{
maxFormContentSize = lookupServerAttribute(ContextHandler.MAX_FORM_CONTENT_SIZE_KEY, maxFormContentSize);
if (maxFormContentSize < 0)
maxFormContentSize = ContextHandler.DEFAULT_MAX_FORM_CONTENT_SIZE;

maxFormKeys = lookupServerAttribute(ContextHandler.MAX_FORM_KEYS_KEY, maxFormKeys);
if (maxFormKeys < 0)
maxFormKeys = ContextHandler.DEFAULT_MAX_FORM_KEYS;
}

MultiPartCompliance multiPartCompliance = getHttpChannel().getHttpConfiguration().getMultiPartCompliance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
})
.send();

int expected = (maxFormContentSize != null && maxFormContentSize < 0)
? HttpStatus.OK_200
: HttpStatus.BAD_REQUEST_400;
assertEquals(expected, response.getStatus());
assertEquals(HttpStatus.BAD_REQUEST_400, response.getStatus());
}

public static Stream<Integer> formKeysScenarios()
Expand Down Expand Up @@ -199,10 +196,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
.body(new FormRequestContent(formParams))
.send();

int expected = (maxFormKeys != null && maxFormKeys < 0)
? HttpStatus.OK_200
: HttpStatus.BAD_REQUEST_400;
assertEquals(expected, response.getStatus());
assertEquals(HttpStatus.BAD_REQUEST_400, response.getStatus());
}

@Test
Expand Down
Loading