This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new f221c65 Context API refactoring.
f221c65 is described below
commit f221c6586e8f874a73496e5c4d91a4b4c33e0b42
Author: JamesBognar <[email protected]>
AuthorDate: Sat Aug 28 15:13:37 2021 -0400
Context API refactoring.
---
.../java/org/apache/juneau/rest/RestContext.java | 441 +--------------------
.../org/apache/juneau/rest/RestContextBuilder.java | 301 ++++++++++++--
.../java/org/apache/juneau/rest/RestOpContext.java | 7 +-
.../apache/juneau/rest/RestOpContextBuilder.java | 102 ++++-
.../org/apache/juneau/rest/annotation/Rest.java | 21 +-
.../juneau/rest/annotation/RestAnnotation.java | 13 +-
.../apache/juneau/rest/annotation/RestDelete.java | 7 +-
.../rest/annotation/RestDeleteAnnotation.java | 3 +-
.../org/apache/juneau/rest/annotation/RestGet.java | 7 +-
.../juneau/rest/annotation/RestGetAnnotation.java | 3 +-
.../org/apache/juneau/rest/annotation/RestOp.java | 11 +-
.../juneau/rest/annotation/RestOpAnnotation.java | 5 +-
.../apache/juneau/rest/annotation/RestPost.java | 11 +-
.../juneau/rest/annotation/RestPostAnnotation.java | 5 +-
.../org/apache/juneau/rest/annotation/RestPut.java | 11 +-
.../juneau/rest/annotation/RestPutAnnotation.java | 5 +-
16 files changed, 448 insertions(+), 505 deletions(-)
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 2ed1dd1..2a2a409 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -105,221 +105,6 @@ public class RestContext extends BeanContext {
static final String PREFIX = "RestContext";
/**
- * Configuration property: Allowed header URL parameters.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_allowedHeaderParams
REST_allowedHeaderParams}
- * <li><b>Name:</b> <js>"RestContext.allowedHeaderParams.s"</js>
- * <li><b>Data type:</b> <c>String</c> (comma-delimited)
- * <li><b>System property:</b>
<c>RestContext.allowedHeaderParams</c>
- * <li><b>Environment variable:</b>
<c>RESTCONTEXT_ALLOWHEADERPARAMS</c>
- * <li><b>Default:</b> <js>"Accept,Content-Type"</js>
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#allowedHeaderParams()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#allowedHeaderParams(String)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * When specified, allows headers such as <js>"Accept"</js> and
<js>"Content-Type"</js> to be passed in as URL query
- * parameters.
- * <br>
- * For example:
- * <p class='bcode w800'>
- * ?Accept=text/json&Content-Type=text/json
- * </p>
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Option #1 - Defined via annotation.</jc>
- *
<ja>@Rest</ja>(allowedHeaderParams=<js>"Accept,Content-Type"</js>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- *
<jv>builder</jv>.allowedHeaderParams(<js>"Accept,Content-Type"</js>);
- *
- * <jc>// Same, but using property.</jc>
- *
<jv>builder</jv>.set(<jsf>REST_allowedHeaderParams</jsf>,
<js>"Accept,Content-Type"</js>);
- * }
- *
- * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
- * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
- * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
<jv>builder</jv>.allowedHeaderParams(<js>"Accept,Content-Type"</js>);
- * }
- * }
- * </p>
- *
- * <ul class='notes'>
- * <li>
- * Useful for debugging REST interface using only a
browser so that you can quickly simulate header values
- * in the URL bar.
- * <li>
- * Header names are case-insensitive.
- * <li>
- * Use <js>"*"</js> to allow any headers to be specified
as URL parameters.
- * <li>
- * Use <js>"NONE"</js> (case insensitive) to suppress
inheriting a value from a parent class.
- * </ul>
- */
- public static final String REST_allowedHeaderParams = PREFIX +
".allowedHeaderParams.s";
-
- /**
- * Configuration property: Allowed method headers.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_allowedMethodHeaders
REST_allowedMethodHeaders}
- * <li><b>Name:</b> <js>"RestContext.allowedMethodHeaders.s"</js>
- * <li><b>Data type:</b> <c>String</c> (comma-delimited)
- * <li><b>System property:</b>
<c>RestContext.allowedMethodHeaders</c>
- * <li><b>Environment variable:</b>
<c>RESTCONTEXT_ALLOWEDMETHODHEADERS</c>
- * <li><b>Default:</b> empty string
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#allowedMethodHeaders()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#allowedMethodHeaders(String)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * A comma-delimited list of HTTP method names that are allowed to be
passed as values in an <c>X-Method</c> HTTP header
- * to override the real HTTP method name.
- * <p>
- * Allows you to override the actual HTTP method with a simulated
method.
- * <br>For example, if an HTTP Client API doesn't support <c>PATCH</c>
but does support <c>POST</c> (because
- * <c>PATCH</c> is not part of the original HTTP spec), you can add a
<c>X-Method: PATCH</c> header on a normal
- * <c>HTTP POST /foo</c> request call which will make the HTTP call
look like a <c>PATCH</c> request in any of the REST APIs.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
- * <ja>@Rest</ja>(allowedMethodHeaders=<js>"PATCH"</js>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- *
<jv>builder</jv>.allowedMethodHeaders(<js>"PATCH"</js>);
- *
- * <jc>// Same, but using property.</jc>
- *
<jv>builder</jv>.set(<jsf>REST_allowedMethodHeaders</jsf>, <js>"PATCH"</js>);
- * }
- *
- * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
- * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
- * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
<jv>builder</jv>.allowedMethodHeaders(<js>"PATCH"</js>);
- * }
- * }
- * </p>
- *
- * <ul class='notes'>
- * <li>
- * Method names are case-insensitive.
- * <li>
- * Use <js>"*"</js> to represent all methods.
- * <li>
- * Use <js>"NONE"</js> (case insensitive) to suppress
inheriting a value from a parent class.
- * </ul>
- */
- public static final String REST_allowedMethodHeaders = PREFIX +
".allowedMethodHeaders.s";
-
- /**
- * Configuration property: Allowed method URL parameters.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_allowedMethodParams
REST_allowedMethodParams}
- * <li><b>Name:</b> <js>"RestContext.allowedMethodParams.s"</js>
- * <li><b>Data type:</b> <c>String</c> (comma-delimited)
- * <li><b>System property:</b>
<c>RestContext.allowedMethodParams</c>
- * <li><b>Environment variable:</b>
<c>RESTCONTEXT_ALLOWEDMETHODPARAMS</c>
- * <li><b>Default:</b> <js>"HEAD,OPTIONS"</js>
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#allowedMethodParams()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#allowedMethodParams(String)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * When specified, the HTTP method can be overridden by passing in a
<js>"method"</js> (case-insensitive) URL parameter on a regular
- * GET request.
- * <br>
- * For example:
- * <p class='bcode w800'>
- * /myservlet/myendpoint?method=OPTIONS
- * </p>
- * <p>
- * Useful in cases where you want to simulate a non-GET request in
a browser by simply adding a parameter.
- * <br>Also useful if you want to construct hyperlinks to non-GET
REST endpoints such as links to <c>OPTIONS</c>
- * pages.
- *
- * <p>
- * Note that per the {@doc ExtRFC2616.section9 HTTP specification},
special care should
- * be taken when allowing non-safe (<c>POST</c>, <c>PUT</c>,
<c>DELETE</c>) methods to be invoked through GET requests.
- *
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Option #1 - Defined via annotation.</jc>
- * <ja>@Rest</ja>(allowedMethodParams=<js>"HEAD,OPTIONS,PUT"</js>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- *
<jv>builder</jv>.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
- *
- * <jc>// Same, but using property.</jc>
- *
<jv>builder</jv>.set(<jsf>REST_allowedMethodParams</jsf>,
<js>"HEAD,OPTIONS,PUT"</js>);
- * }
- *
- * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
- * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
- * <jk>public void</jk> init(RestContextBuilder builder)
<jk>throws</jk> Exception {
- *
<jv>builder</jv>.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
- * }
- * }
- * </p>
- *
- * <ul class='notes'>
- * <li>
- * Format is a comma-delimited list of HTTP method names
that can be passed in as a method parameter.
- * <li>
- * <js>'method'</js> parameter name is case-insensitive.
- * <li>
- * Use <js>"*"</js> to represent all methods.
- * <li>
- * Use <js>"NONE"</js> (case insensitive) to suppress
inheriting a value from a parent class.
- * </ul>
- */
- public static final String REST_allowedMethodParams = PREFIX +
".allowedMethodParams.s";
-
- /**
* Configuration property: Bean store.
*
* <h5 class='section'>Property:</h5>
@@ -597,82 +382,6 @@ public class RestContext extends BeanContext {
public static final String REST_children = PREFIX + ".children.lo";
/**
- * Configuration property: Client version header.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_clientVersionHeader
REST_clientVersionHeader}
- * <li><b>Name:</b> <js>"RestContext.clientVersionHeader.s"</js>
- * <li><b>Data type:</b> <c>String</c>
- * <li><b>System property:</b>
<c>RestContext.clientVersionHeader</c>
- * <li><b>Environment variable:</b>
<c>RESTCONTEXT_CLIENTVERSIONHEADER</c>
- * <li><b>Default:</b> <js>"Client-Version"</js>
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#clientVersionHeader()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#clientVersionHeader(String)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * Specifies the name of the header used to denote the client version
on HTTP requests.
- *
- * <p>
- * The client version is used to support backwards compatibility for
breaking REST interface changes.
- * <br>Used in conjunction with {@link RestOp#clientVersion()
@RestOp(clientVersion)} annotation.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
- *
<ja>@Rest</ja>(clientVersionHeader=<js>"$C{REST/clientVersionHeader,Client-Version}"</js>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- *
<jv>builder</jv>.clientVersionHeader(<js>"Client-Version"</js>);
- *
- * <jc>// Same, but using property.</jc>
- *
<jv>builder</jv>.set(<jsf>REST_clientVersionHeader</jsf>,
<js>"Client-Version"</js>);
- * }
- *
- * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
- * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
- * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
<jv>builder</jv>.clientVersionHeader(<js>"Client-Version"</js>);
- * }
- * }
- * </p>
- * <p class='bcode w800'>
- * <jc>// Call this method if Client-Version is at least 2.0.
- * // Note that this also matches 2.0.1.</jc>
- * <ja>@RestGet/ja>(path=<js>"/foobar"</js>,
clientVersion=<js>"2.0"</js>)
- * <jk>public</jk> Object method1() {
- * ...
- * }
- *
- * <jc>// Call this method if Client-Version is at least 1.1, but
less than 2.0.</jc>
- * <ja>@RestGet</ja>(path=<js>"/foobar"</js>,
clientVersion=<js>"[1.1,2.0)"</js>)
- * <jk>public</jk> Object method2() {
- * ...
- * }
- *
- * <jc>// Call this method if Client-Version is less than 1.1.</jc>
- * <ja>@RestGet</ja>(path=<js>"/foobar"</js>,
clientVersion=<js>"[0,1.1)"</js>)
- * <jk>public</jk> Object method3() {
- * ...
- * }
- * </p>
- */
- public static final String REST_clientVersionHeader = PREFIX +
".clientVersionHeader.s";
-
- /**
* Configuration property: Supported content media types.
*
* <h5 class='section'>Property:</h5>
@@ -1033,64 +742,6 @@ public class RestContext extends BeanContext {
public static final String REST_debugOn = PREFIX + ".debugOn.s";
/**
- * Configuration property: Default character encoding.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_defaultCharset REST_defaultCharset}
- * <li><b>Name:</b> <js>"RestContext.defaultCharset.s"</js>
- * <li><b>Data type:</b> <c>String</c>
- * <li><b>System property:</b> <c>RestContext.defaultCharset</c>
- * <li><b>Environment variable:</b>
<c>RESTCONTEXT_DEFAULTCHARSET</c>
- * <li><b>Default:</b> <js>"utf-8"</js>
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#defaultCharset()}
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.RestOp#defaultCharset()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#defaultCharset(String)}
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#defaultCharset(Charset)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * The default character encoding for the request and response if not
specified on the request.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
- *
<ja>@Rest</ja>(defaultCharset=<js>"$C{REST/defaultCharset,US-ASCII}"</js>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- *
<jv>builder</jv>.defaultCharset(<js>"US-ASCII"</js>);
- *
- * <jc>// Same, but using property.</jc>
- *
<jv>builder</jv>.set(<jsf>REST_defaultCharset</jsf>, <js>"US-ASCII"</js>);
- * }
- *
- * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
- * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
- * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
<jv>builder</jv>.defaultCharset(<js>"US-ASCII"</js>);
- * }
- *
- * <jc>// Override at the method level.</jc>
- * <ja>@RestGet</ja>(defaultCharset=<js>"UTF-16"</js>)
- * <jk>public</jk> Object myMethod() {...}
- * }
- * </p>
- */
- public static final String REST_defaultCharset = PREFIX +
".defaultCharset.s";
-
- /**
* Configuration property: Default request attributes.
*
* <h5 class='section'>Property:</h5>
@@ -1659,74 +1310,6 @@ public class RestContext extends BeanContext {
public static final String REST_guards = PREFIX + ".guards.lo";
/**
- * Configuration property: The maximum allowed input size (in bytes)
on HTTP requests.
- *
- * <h5 class='section'>Property:</h5>
- * <ul class='spaced-list'>
- * <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_maxInput REST_maxInput}
- * <li><b>Name:</b> <js>"RestContext.maxInput.s"</js>
- * <li><b>Data type:</b> <c>String</c>
- * <li><b>System property:</b> <c>RestContext.maxInput</c>
- * <li><b>Environment variable:</b> <c>RESTCONTEXT_MAXINPUT</c>
- * <li><b>Default:</b> <js>"100M"</js>
- * <li><b>Session property:</b> <jk>false</jk>
- * <li><b>Annotations:</b>
- * <ul>
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.Rest#maxInput()}
- * <li class='ja'>{@link
org.apache.juneau.rest.annotation.RestOp#maxInput()}
- * </ul>
- * <li><b>Methods:</b>
- * <ul>
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#maxInput(String)}
- * </ul>
- * </ul>
- *
- * <h5 class='section'>Description:</h5>
- * <p>
- * Useful for alleviating DoS attacks by throwing an exception when too
much input is received instead of resulting
- * in out-of-memory errors which could affect system stability.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
- * <ja>@Rest</ja>(maxInput=<js>"$C{REST/maxInput,10M}"</js>)
- * <jk>public class</jk> MyResource {
- *
- * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
- * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- *
- * <jc>// Using method on builder.</jc>
- * <jv>builder</jv>.maxInput(<js>"10M"</js>);
- *
- * <jc>// Same, but using property.</jc>
- * <jv>builder</jv>.set(<jsf>REST_maxInput</jsf>,
<js>"10M"</js>);
- * }
- *
- * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
- * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
- * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
- * <jv>builder</jv>.maxInput(<js>"10M"</js>);
- * }
- *
- * <jc>// Override at the method level.</jc>
- * <ja>@RestPost</ja>(maxInput=<js>"10M"</js>)
- * <jk>public</jk> Object myMethod() {...}
- * }
- * </p>
- *
- * <ul class='notes'>
- * <li>
- * String value that gets resolved to a <jk>long</jk>.
- * <li>
- * Can be suffixed with any of the following representing
kilobytes, megabytes, and gigabytes:
- * <js>'K'</js>, <js>'M'</js>, <js>'G'</js>.
- * <li>
- * A value of <js>"-1"</js> can be used to represent no
limit.
- * </ul>
- */
- public static final String REST_maxInput = PREFIX + ".maxInput.s";
-
- /**
* Configuration property: Messages.
*
* <h5 class='section'>Property:</h5>
@@ -3396,6 +2979,8 @@ public class RestContext extends BeanContext {
private final ConcurrentHashMap<Locale,Swagger> swaggerCache = new
ConcurrentHashMap<>();
private final Instant startTime;
private final Map<Class<?>,ResponseBeanMeta> responseBeanMetas = new
ConcurrentHashMap<>();
+ final Charset defaultCharset;
+ final long maxInput;
// Lifecycle methods
private final MethodInvoker[]
@@ -3533,11 +3118,13 @@ public class RestContext extends BeanContext {
uriRelativity = cp.get(REST_uriRelativity,
UriRelativity.class).orElse(UriRelativity.RESOURCE);
allowBodyParam = !
cp.getBoolean(REST_disableAllowBodyParam).orElse(false);
- allowedHeaderParams =
newCaseInsensitiveSet(cp.getString(REST_allowedHeaderParams).map(x ->
"NONE".equals(x) ? "" : x).orElse("Accept,Content-Type"));
- allowedMethodParams =
newCaseInsensitiveSet(cp.getString(REST_allowedMethodParams).map(x ->
"NONE".equals(x) ? "" : x).orElse("HEAD,OPTIONS"));
- allowedMethodHeaders =
newCaseInsensitiveSet(cp.getString(REST_allowedMethodHeaders).map(x ->
"NONE".equals(x) ? "" : x).orElse(""));
+ allowedHeaderParams =
newCaseInsensitiveSet(Optional.of(builder.allowedHeaderParams).map(x ->
"NONE".equals(x) ? "" : x).orElse(""));
+ allowedMethodParams =
newCaseInsensitiveSet(Optional.of(builder.allowedMethodParams).map(x ->
"NONE".equals(x) ? "" : x).orElse(""));
+ allowedMethodHeaders =
newCaseInsensitiveSet(Optional.of(builder.allowedMethodHeaders).map(x ->
"NONE".equals(x) ? "" : x).orElse(""));
renderResponseStackTraces =
cp.getBoolean(REST_renderResponseStackTraces).orElse(false);
- clientVersionHeader =
cp.getString(REST_clientVersionHeader).orElse("Client-Version");
+ clientVersionHeader = builder.clientVersionHeader;
+ defaultCharset = builder.defaultCharset;
+ maxInput = builder.maxInput;
debugEnablement = createDebugEnablement(r, cp, bf);
@@ -5947,7 +5534,8 @@ public class RestContext extends BeanContext {
* Allowed header URL parameters.
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_allowedHeaderParams}
+ * <li class='ja'>{@link Rest#allowedHeaderParams}
+ * <li class='jm'>{@link
RestContextBuilder#allowedHeaderParams(String)}
* </ul>
*
* @return
@@ -5962,7 +5550,8 @@ public class RestContext extends BeanContext {
* Allowed method headers.
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_allowedMethodHeaders}
+ * <li class='ja'>{@link Rest#allowedMethodHeaders}
+ * <li class='jm'>{@link
RestContextBuilder#allowedMethodHeaders(String)}
* </ul>
*
* @return
@@ -5977,7 +5566,8 @@ public class RestContext extends BeanContext {
* Allowed method URL parameters.
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_allowedMethodParams}
+ * <li class='ja'>{@link Rest#allowedMethodParams}
+ * <li class='jm'>{@link
RestContextBuilder#allowedMethodParams(String)}
* </ul>
*
* @return
@@ -5992,7 +5582,8 @@ public class RestContext extends BeanContext {
* Returns the name of the client version header name used by this
resource.
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='ja'>{@link Rest#clientVersionHeader}
+ * <li class='jm'>{@link
RestContextBuilder#clientVersionHeader(String)}
* </ul>
*
* @return
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index 0227888..a3b48c2 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -112,6 +112,9 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
Config config;
VarResolverBuilder varResolverBuilder;
+ String allowedHeaderParams, allowedMethodHeaders, allowedMethodParams,
clientVersionHeader;
+ Charset defaultCharset;
+ long maxInput;
RestContextBuilder(Optional<RestContext> parentContext,
Optional<ServletConfig> servletConfig, Class<?> resourceClass, Optional<Object>
resource) throws ServletException {
try {
@@ -138,6 +141,13 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
SerializedPojoProcessor.class
);
+ allowedHeaderParams =
env("RestContext.allowedHeaderParams", "Accept,Content-Type");
+ allowedMethodHeaders =
env("RestContext.allowedMethodHeaders", "");
+ allowedMethodParams =
env("RestContext.allowedMethodParams", "HEAD,OPTIONS");
+ clientVersionHeader =
env("RestContext.clientVersionHeader", "Client-Version");
+ defaultCharset = env("RestContext.defaultCharset",
IOUtils.UTF8);
+ maxInput =
StringUtils.parseLongWithSuffix(env("RestContext.maxInput", "100M"));
+
// Pass-through default values.
if (parentContext.isPresent()) {
RestContext pc = parentContext.get();
@@ -454,7 +464,7 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
//----------------------------------------------------------------------------------------------------
/**
- * <i><l>RestContext</l> configuration property: </i> Allowed
header URL parameters.
+ * Allowed header URL parameters.
*
* <p>
* When specified, allows headers such as <js>"Accept"</js> and
<js>"Content-Type"</js> to be passed in as URL query
@@ -465,48 +475,103 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
* ?Accept=text/json&Content-Type=text/json
* </p>
*
+ * <ul class='notes'>
+ * <li>
+ * Useful for debugging REST interface using only a
browser so that you can quickly simulate header values
+ * in the URL bar.
+ * <li>
+ * Header names are case-insensitive.
+ * <li>
+ * Use <js>"*"</js> to allow any headers to be specified
as URL parameters.
+ * <li>
+ * Use <js>"NONE"</js> (case insensitive) to suppress
inheriting a value from a parent class.
+ * </ul>
+
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_allowedHeaderParams}
+ * <li class='ja'>{@link Rest#allowedHeaderParams}
* </ul>
*
* @param value
* The new value for this setting.
- * <br>The default is <jk>true</jk>.
+ * <br>The default is the first value found:
+ * <ul>
+ * <li>System property
<js>"RestContext.allowedHeaderParams"
+ * <li>Environment variable
<js>"RESTCONTEXT_ALLOWEDHEADERPARAMS"
+ * <li><js>"Accept,Content-Type"</js>
+ * </ul>
* @return This object (for method chaining).
*/
@FluentSetter
public RestContextBuilder allowedHeaderParams(String value) {
- return set(REST_allowedHeaderParams, value);
+ allowedHeaderParams = value;
+ return this;
}
/**
- * <i><l>RestContext</l> configuration property: </i> Allowed
method headers.
+ * Allowed method headers.
*
* <p>
* A comma-delimited list of HTTP method names that are allowed to be
passed as values in an <c>X-Method</c> HTTP header
* to override the real HTTP method name.
+ *
* <p>
* Allows you to override the actual HTTP method with a simulated
method.
* <br>For example, if an HTTP Client API doesn't support <c>PATCH</c>
but does support <c>POST</c> (because
* <c>PATCH</c> is not part of the original HTTP spec), you can add a
<c>X-Method: PATCH</c> header on a normal
* <c>HTTP POST /foo</c> request call which will make the HTTP call
look like a <c>PATCH</c> request in any of the REST APIs.
*
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
+ * <ja>@Rest</ja>(allowedMethodHeaders=<js>"PATCH"</js>)
+ * <jk>public class</jk> MyResource {
+ *
+ * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
+ * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
+ * <jc>// Using method on builder.</jc>
+ *
<jv>builder</jv>.allowedMethodHeaders(<js>"PATCH"</js>);
+ * }
+ *
+ * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
+ * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
<jv>builder</jv>.allowedMethodHeaders(<js>"PATCH"</js>);
+ * }
+ * }
+ * </p>
+ *
+ * <ul class='notes'>
+ * <li>
+ * Method names are case-insensitive.
+ * <li>
+ * Use <js>"*"</js> to represent all methods.
+ * <li>
+ * Use <js>"NONE"</js> (case insensitive) to suppress
inheriting a value from a parent class.
+ * </ul>
+ *
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_allowedMethodHeaders}
+ * <li class='ja'>{@link Rest#allowedMethodHeaders}
* </ul>
*
* @param value
* The new value for this setting.
- * <br>The default is <jk>true</jk>.
+ * <br>The default is the first value found:
+ * <ul>
+ * <li>System property
<js>"RestContext.allowedMethodHeaders"
+ * <li>Environment variable
<js>"RESTCONTEXT_ALLOWEDMETHODHEADERS"
+ * <li><js>""</js>
+ * </ul>
* @return This object (for method chaining).
*/
@FluentSetter
public RestContextBuilder allowedMethodHeaders(String value) {
- return set(REST_allowedMethodHeaders, value);
+ allowedMethodHeaders = value;
+ return this;
}
/**
- * <i><l>RestContext</l> configuration property: </i> Allowed
method parameters.
+ * Allowed method parameters.
*
* <p>
* When specified, the HTTP method can be overridden by passing in a
<js>"method"</js> URL parameter on a regular
@@ -517,19 +582,65 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
* ?method=OPTIONS
* </p>
*
+ * <p>
+ * Useful in cases where you want to simulate a non-GET request in
a browser by simply adding a parameter.
+ * <br>Also useful if you want to construct hyperlinks to non-GET
REST endpoints such as links to <c>OPTIONS</c>
+ * pages.
+ *
+ * <p>
+ * Note that per the {@doc ExtRFC2616.section9 HTTP specification},
special care should
+ * be taken when allowing non-safe (<c>POST</c>, <c>PUT</c>,
<c>DELETE</c>) methods to be invoked through GET requests.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Option #1 - Defined via annotation.</jc>
+ * <ja>@Rest</ja>(allowedMethodParams=<js>"HEAD,OPTIONS,PUT"</js>)
+ * <jk>public class</jk> MyResource {
+ *
+ * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
+ * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
+ * <jc>// Using method on builder.</jc>
+ *
<jv>builder</jv>.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
+ * }
+ *
+ * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
+ * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * <jk>public void</jk> init(RestContextBuilder builder)
<jk>throws</jk> Exception {
+ *
<jv>builder</jv>.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
+ * }
+ * }
+ * </p>
+ *
+ * <ul class='notes'>
+ * <li>
+ * Format is a comma-delimited list of HTTP method names
that can be passed in as a method parameter.
+ * <li>
+ * <js>'method'</js> parameter name is case-insensitive.
+ * <li>
+ * Use <js>"*"</js> to represent all methods.
+ * <li>
+ * Use <js>"NONE"</js> (case insensitive) to suppress
inheriting a value from a parent class.
+ * </ul>
+ *
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_allowedMethodParams}
+ * <li class='ja'>{@link Rest#allowedMethodParams}
* </ul>
*
* @param value
* The new value for this setting.
- * <br>The default is
<code>[<js>"HEAD"</js>,<js>"OPTIONS"</js>]</code>.
- * <br>Individual values can also be comma-delimited lists.
+ * <br>The default is the first value found:
+ * <ul>
+ * <li>System property
<js>"RestContext.allowedMethodParams"
+ * <li>Environment variable
<js>"RESTCONTEXT_ALLOWEDMETHODPARAMS"
+ * <li><js>"HEAD,OPTIONS"</js>
+ * </ul>
* @return This object (for method chaining).
*/
@FluentSetter
public RestContextBuilder allowedMethodParams(String value) {
- return set(REST_allowedMethodParams, value);
+ allowedMethodParams = value;
+ return this;
}
/**
@@ -731,7 +842,7 @@ public class RestContextBuilder extends BeanContextBuilder
implements ServletCon
}
/**
- * <i><l>RestContext</l> configuration property: </i> Client
version header.
+ * Client version header.
*
* <p>
* Specifies the name of the header used to denote the client version
on HTTP requests.
@@ -740,18 +851,66 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
* The client version is used to support backwards compatibility for
breaking REST interface changes.
* <br>Used in conjunction with {@link RestOp#clientVersion()
@RestOp(clientVersion)} annotation.
*
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
+ *
<ja>@Rest</ja>(clientVersionHeader=<js>"$C{REST/clientVersionHeader,Client-Version}"</js>)
+ * <jk>public class</jk> MyResource {
+ *
+ * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
+ * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
+ * <jc>// Using method on builder.</jc>
+ *
<jv>builder</jv>.clientVersionHeader(<js>"Client-Version"</js>);
+ * }
+ *
+ * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
+ * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
<jv>builder</jv>.clientVersionHeader(<js>"Client-Version"</js>);
+ * }
+ * }
+ * </p>
+ *
+ * <p class='bcode w800'>
+ * <jc>// Call this method if Client-Version is at least 2.0.
+ * // Note that this also matches 2.0.1.</jc>
+ * <ja>@RestGet/ja>(path=<js>"/foobar"</js>,
clientVersion=<js>"2.0"</js>)
+ * <jk>public</jk> Object method1() {
+ * ...
+ * }
+ *
+ * <jc>// Call this method if Client-Version is at least 1.1, but
less than 2.0.</jc>
+ * <ja>@RestGet</ja>(path=<js>"/foobar"</js>,
clientVersion=<js>"[1.1,2.0)"</js>)
+ * <jk>public</jk> Object method2() {
+ * ...
+ * }
+ *
+ * <jc>// Call this method if Client-Version is less than 1.1.</jc>
+ * <ja>@RestGet</ja>(path=<js>"/foobar"</js>,
clientVersion=<js>"[0,1.1)"</js>)
+ * <jk>public</jk> Object method3() {
+ * ...
+ * }
+ * </p>
+ *
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='ja'>{@link Rest#clientVersionHeader}
* </ul>
*
* @param value
* The new value for this setting.
- * <br>The default is <js>"Client-Version"</js>.
+ * <br>The default is the first value found:
+ * <ul>
+ * <li>System property
<js>"RestContext.clientVersionHeader"
+ * <li>Environment variable
<js>"RESTCONTEXT_CLIENTVERSIONHEADER"
+ * <li><js>"Client-Version"</js>
+ * </ul>
* @return This object (for method chaining).
*/
@FluentSetter
public RestContextBuilder clientVersionHeader(String value) {
- return set(REST_clientVersionHeader, value);
+ clientVersionHeader = value;
+ return this;
}
@Override
@@ -881,43 +1040,55 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
}
/**
- * <i><l>RestContext</l> configuration property: </i> Default
character encoding.
+ * Default character encoding.
*
* <p>
* The default character encoding for the request and response if not
specified on the request.
*
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_defaultCharset}
- * </ul>
- *
- * @param value
- * The new value for this setting.
- * <br>The default is <js>"utf-8"</js>.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder defaultCharset(String value) {
- return set(REST_defaultCharset, value);
- }
-
- /**
- * <i><l>RestContext</l> configuration property: </i> Default
character encoding.
- *
- * <p>
- * Same as {@link #defaultCharset(Charset)} but takes in an instance of
{@link Charset}.
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
+ *
<ja>@Rest</ja>(defaultCharset=<js>"$C{REST/defaultCharset,US-ASCII}"</js>)
+ * <jk>public class</jk> MyResource {
+ *
+ * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
+ * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
+ * <jc>// Using method on builder.</jc>
+ *
<jv>builder</jv>.defaultCharset(<js>"US-ASCII"</js>);
+ * }
+ *
+ * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
+ * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
<jv>builder</jv>.defaultCharset(<js>"US-ASCII"</js>);
+ * }
+ *
+ * <jc>// Override at the method level.</jc>
+ * <ja>@RestGet</ja>(defaultCharset=<js>"UTF-16"</js>)
+ * <jk>public</jk> Object myMethod() {...}
+ * }
+ * </p>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_defaultCharset}
+ * <li class='ja'>{@link Rest#defaultCharset}
+ * <li class='ja'>{@link RestOp#defaultCharset}
* </ul>
*
* @param value
* The new value for this setting.
- * <br>The default is <js>"utf-8"</js>.
+ * <br>The default is the first value found:
+ * <ul>
+ * <li>System property <js>"RestContext.defaultCharset"
+ * <li>Environment variable
<js>"RESTCONTEXT_defaultCharset"
+ * <li><js>"utf-8"</js>
+ * </ul>
* @return This object (for method chaining).
*/
@FluentSetter
public RestContextBuilder defaultCharset(Charset value) {
- return set(REST_defaultCharset, value);
+ defaultCharset = value;
+ return this;
}
/**
@@ -1301,24 +1472,68 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
}
/**
- * <i><l>RestContext</l> configuration property: </i> The maximum
allowed input size (in bytes) on HTTP requests.
+ * The maximum allowed input size (in bytes) on HTTP requests.
*
* <p>
* Useful for alleviating DoS attacks by throwing an exception when too
much input is received instead of resulting
* in out-of-memory errors which could affect system stability.
*
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
+ * <ja>@Rest</ja>(maxInput=<js>"$C{REST/maxInput,10M}"</js>)
+ * <jk>public class</jk> MyResource {
+ *
+ * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
+ * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
+ * <jc>// Using method on builder.</jc>
+ * <jv>builder</jv>.maxInput(<js>"10M"</js>);
+ * }
+ *
+ * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
+ * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ * <jv>builder</jv>.maxInput(<js>"10M"</js>);
+ * }
+ *
+ * <jc>// Override at the method level.</jc>
+ * <ja>@RestPost</ja>(maxInput=<js>"10M"</js>)
+ * <jk>public</jk> Object myMethod() {...}
+ * }
+ * </p>
+ *
+ * <ul class='notes'>
+ * <li>
+ * String value that gets resolved to a <jk>long</jk>.
+ * <li>
+ * Can be suffixed with any of the following representing
kilobytes, megabytes, and gigabytes:
+ * <js>'K'</js>, <js>'M'</js>, <js>'G'</js>.
+ * <li>
+ * A value of <js>"-1"</js> can be used to represent no
limit.
+ * </ul>
+ *
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_maxInput}
+ * <li class='ja'>{@link Rest#maxInput}
+ * <li class='ja'>{@link RestOp#maxInput}
+ * <li class='jm'>{@link RestOpContextBuilder#maxInput(String)}
* </ul>
*
* @param value
* The new value for this setting.
+ * <br>The default is the first value found:
+ * <ul>
+ * <li>System property <js>"RestContext.maxInput"
+ * <li>Environment variable <js>"RESTCONTEXT_MAXINPUT"
+ * <li><js>"100M"</js>
+ * </ul>
* <br>The default is <js>"100M"</js>.
* @return This object (for method chaining).
*/
@FluentSetter
public RestContextBuilder maxInput(String value) {
- return set(REST_maxInput, value);
+ maxInput = StringUtils.parseLongWithSuffix(value);
+ return this;
}
/**
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
index 179d0c2..45bfa9e 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
@@ -23,6 +23,7 @@ import static org.apache.juneau.rest.util.RestUtils.*;
import static org.apache.juneau.rest.HttpRuntimeException.*;
import static java.util.Collections.*;
import static org.apache.juneau.http.HttpParts.*;
+import static java.util.Optional.*;
import java.lang.annotation.*;
import java.lang.reflect.Method;
@@ -46,7 +47,6 @@ import org.apache.juneau.http.header.*;
import org.apache.juneau.http.part.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.httppart.bean.*;
-import org.apache.juneau.internal.*;
import org.apache.juneau.internal.HttpUtils;
import org.apache.juneau.jsonschema.*;
import org.apache.juneau.oapi.*;
@@ -206,9 +206,8 @@ public class RestOpContext extends BeanContext implements
Comparable<RestOpConte
_httpMethod = "*";
httpMethod = _httpMethod.toUpperCase(Locale.ENGLISH);
- defaultCharset =
Charset.forName(cp.getString(REST_defaultCharset).orElse("utf-8"));
-
- maxInput =
StringUtils.parseLongWithSuffix(cp.get(REST_maxInput,
String.class).orElse("100M"));
+ defaultCharset =
ofNullable(builder.defaultCharset).orElse(context.defaultCharset);
+ maxInput =
ofNullable(builder.maxInput).orElse(context.maxInput);
responseMeta = ResponseBeanMeta.create(mi, cp);
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContextBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContextBuilder.java
index 8713bf7..d8a8b63 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContextBuilder.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContextBuilder.java
@@ -27,6 +27,7 @@ import org.apache.juneau.reflect.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.svl.*;
import java.lang.reflect.Method;
+import java.nio.charset.*;
/**
* Builder class for {@link RestOpContext} objects.
@@ -44,6 +45,9 @@ public class RestOpContextBuilder extends BeanContextBuilder {
HeaderListBuilder defaultRequestHeaders, defaultResponseHeaders;
RestMatcherListBuilder restMatchers;
+ Charset defaultCharset;
+ Long maxInput;
+
private BeanStore beanStore;
@Override /* ContextBuilder */
@@ -187,7 +191,7 @@ public class RestOpContextBuilder extends
BeanContextBuilder {
* <li class='ja'>{@link RestPut#clientVersion}
* <li class='ja'>{@link RestPost#clientVersion}
* <li class='ja'>{@link RestDelete#clientVersion}
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='jm'>{@link
RestContextBuilder#clientVersionHeader(String)}
* </ul>
*
* @param value The new value for this setting.
@@ -229,6 +233,37 @@ public class RestOpContextBuilder extends
BeanContextBuilder {
}
/**
+ * Default character encoding.
+ *
+ * <p>
+ * The default character encoding for the request and response if not
specified on the request.
+ *
+ * <p>
+ * This overrides the value defined on the {@link RestContext}.
+ *
+ * <ul class='seealso'>
+ * <li class='jm'>{@link
RestContextBuilder#defaultCharset(Charset)}
+ * <li class='ja'>{@link Rest#defaultCharset}
+ * <li class='ja'>{@link RestOp#defaultCharset}
+ * </ul>
+ *
+ * @param value
+ * The new value for this setting.
+ * <br>The default is the first value found:
+ * <ul>
+ * <li>System property <js>"RestContext.defaultCharset"
+ * <li>Environment variable
<js>"RESTCONTEXT_defaultCharset"
+ * <li><js>"utf-8"</js>
+ * </ul>
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestOpContextBuilder defaultCharset(Charset value) {
+ defaultCharset = value;
+ return this;
+ }
+
+ /**
* Default form data parameters.
*
* <p>
@@ -506,6 +541,71 @@ public class RestOpContextBuilder extends
BeanContextBuilder {
}
/**
+ * The maximum allowed input size (in bytes) on HTTP requests.
+ *
+ * <p>
+ * Useful for alleviating DoS attacks by throwing an exception when too
much input is received instead of resulting
+ * in out-of-memory errors which could affect system stability.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * <jc>// Option #1 - Defined via annotation resolving to a config
file setting with default value.</jc>
+ * <ja>@Rest</ja>(maxInput=<js>"$C{REST/maxInput,10M}"</js>)
+ * <jk>public class</jk> MyResource {
+ *
+ * <jc>// Option #2 - Defined via builder passed in
through resource constructor.</jc>
+ * <jk>public</jk> MyResource(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ *
+ * <jc>// Using method on builder.</jc>
+ * <jv>builder</jv>.maxInput(<js>"10M"</js>);
+ * }
+ *
+ * <jc>// Option #3 - Defined via builder passed in
through init method.</jc>
+ * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * <jk>public void</jk> init(RestContextBuilder
<jv>builder</jv>) <jk>throws</jk> Exception {
+ * <jv>builder</jv>.maxInput(<js>"10M"</js>);
+ * }
+ *
+ * <jc>// Override at the method level.</jc>
+ * <ja>@RestPost</ja>(maxInput=<js>"10M"</js>)
+ * <jk>public</jk> Object myMethod() {...}
+ * }
+ * </p>
+ *
+ * <ul class='notes'>
+ * <li>
+ * String value that gets resolved to a <jk>long</jk>.
+ * <li>
+ * Can be suffixed with any of the following representing
kilobytes, megabytes, and gigabytes:
+ * <js>'K'</js>, <js>'M'</js>, <js>'G'</js>.
+ * <li>
+ * A value of <js>"-1"</js> can be used to represent no
limit.
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * <li class='ja'>{@link Rest#maxInput}
+ * <li class='ja'>{@link RestOp#maxInput}
+ * <li class='jm'>{@link RestOpContextBuilder#maxInput(String)}
+ * </ul>
+ *
+ * @param value
+ * The new value for this setting.
+ * <br>The default is the first value found:
+ * <ul>
+ * <li>System property <js>"RestContext.maxInput"
+ * <li>Environment variable <js>"RESTCONTEXT_MAXINPUT"
+ * <li><js>"100M"</js>
+ * </ul>
+ * <br>The default is <js>"100M"</js>.
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestOpContextBuilder maxInput(String value) {
+ maxInput = StringUtils.parseLongWithSuffix(value);
+ return this;
+ }
+
+ /**
* Configuration property: Resource method paths.
*
* <p>
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
index e2b97f3..3d6b27f 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Rest.java
@@ -16,6 +16,7 @@ import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import java.util.*;
import org.apache.juneau.*;
@@ -93,7 +94,7 @@ public @interface Rest {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_allowedHeaderParams}
+ * <li class='jm'>{@link
RestContextBuilder#allowedHeaderParams(String)}
* </ul>
*/
String allowedHeaderParams() default "";
@@ -147,7 +148,7 @@ public @interface Rest {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_allowedMethodParams}
+ * <li class='jm'>{@link
RestContextBuilder#allowedMethodParams(String)}
* </ul>
*/
String allowedMethodParams() default "";
@@ -225,7 +226,7 @@ public @interface Rest {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='jm'>{@link
RestContextBuilder#clientVersionHeader(String)}
* </ul>
*/
String clientVersionHeader() default "";
@@ -486,7 +487,13 @@ public @interface Rest {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_defaultCharset}
+ * <li class='jm'>{@link
RestContextBuilder#defaultCharset(Charset)}
+ * <li class='jm'>{@link
RestOpContextBuilder#defaultCharset(Charset)}
+ * <li class='ja'>{@link RestOp#defaultCharset}
+ * <li class='ja'>{@link RestGet#defaultCharset}
+ * <li class='ja'>{@link RestPut#defaultCharset}
+ * <li class='ja'>{@link RestPost#defaultCharset}
+ * <li class='ja'>{@link RestDelete#defaultCharset}
* </ul>
*/
String defaultCharset() default "";
@@ -639,7 +646,11 @@ public @interface Rest {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_maxInput}
+ * <li class='jm'>{@link RestContextBuilder#maxInput(String)}
+ * <li class='jm'>{@link RestOpContextBuilder#maxInput(String)}
+ * <li class='ja'>{@link RestOp#maxInput}
+ * <li class='ja'>{@link RestPost#maxInput}
+ * <li class='ja'>{@link RestPut#maxInput}
* </ul>
*/
String maxInput() default "";
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
index 33ca17b..2536617 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
@@ -19,6 +19,7 @@ import static org.apache.juneau.rest.RestContext.*;
import static org.apache.juneau.rest.util.RestUtils.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
@@ -1061,7 +1062,7 @@ public class RestAnnotation {
b.setIf(a.fileFinder() != FileFinder.Null.class,
REST_fileFinder, a.fileFinder());
b.setIf(a.staticFiles() != StaticFiles.Null.class,
REST_staticFiles, a.staticFiles());
b.setIfNotEmpty(REST_path,
trimLeadingSlash(string(a.path())));
- b.setIfNotEmpty(REST_clientVersionHeader,
string(a.clientVersionHeader()));
+ value(a.clientVersionHeader()).ifPresent(x ->
b.clientVersionHeader(x));
b.setIf(a.beanStore() != BeanStore.Null.class,
REST_beanStore, a.beanStore());
b.setIf(a.callLogger() != RestLogger.Null.class,
REST_callLogger, a.callLogger());
b.setIf(a.swaggerProvider() !=
SwaggerProvider.Null.class, REST_swaggerProvider, a.swaggerProvider());
@@ -1070,9 +1071,9 @@ public class RestAnnotation {
b.setIf(a.restOperationsClass() !=
RestOperations.Null.class, REST_restOperationsClass, a.restOperationsClass());
b.setIf(a.debugEnablement() !=
DebugEnablement.Null.class, REST_debugEnablement, a.debugEnablement());
b.setIfNotEmpty(REST_disableAllowBodyParam,
bool(a.disableAllowBodyParam()));
- b.setIfNotEmpty(REST_allowedHeaderParams,
string(a.allowedHeaderParams()));
- b.setIfNotEmpty(REST_allowedMethodHeaders,
string(a.allowedMethodHeaders()));
- b.setIfNotEmpty(REST_allowedMethodParams,
string(a.allowedMethodParams()));
+ value(a.allowedHeaderParams()).ifPresent(x ->
b.allowedHeaderParams(x));
+ value(a.allowedMethodHeaders()).ifPresent(x ->
b.allowedMethodHeaders(x));
+ value(a.allowedMethodParams()).ifPresent(x ->
b.allowedMethodParams(x));
b.setIfNotEmpty(REST_renderResponseStackTraces,
bool(a.renderResponseStackTraces()));
b.setIfNotEmpty(REST_debug, string(a.debug()));
b.setIfNotEmpty(REST_debugOn, string(a.debugOn()));
@@ -1113,8 +1114,8 @@ public class RestAnnotation {
b.prependTo(REST_converters, a.converters());
b.prependTo(REST_guards, reverse(a.guards()));
b.setIfNotEmpty(REST_path,
trimLeadingSlash(string(a.path())));
- b.setIfNotEmpty(REST_defaultCharset,
string(a.defaultCharset()));
- b.setIfNotEmpty(REST_maxInput, string(a.maxInput()));
+
value(a.defaultCharset()).map(Charset::forName).ifPresent(x ->
b.defaultCharset(x));
+ value(a.maxInput()).ifPresent(x -> b.maxInput(x));
cdStream(a.rolesDeclared()).forEach(x ->
b.addTo(REST_rolesDeclared, x));
b.addToIfNotEmpty(REST_roleGuard,
string(a.roleGuard()));
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDelete.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDelete.java
index cf965e2..4310381 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDelete.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDelete.java
@@ -16,6 +16,7 @@ import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.rest.*;
@@ -94,7 +95,7 @@ public @interface RestDelete {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='jm'>{@link
RestContextBuilder#clientVersionHeader(String)}
* </ul>
*/
String clientVersion() default "";
@@ -165,7 +166,9 @@ public @interface RestDelete {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_defaultCharset}
+ * <li class='jm'>{@link
RestContextBuilder#defaultCharset(Charset)}
+ * <li class='jm'>{@link
RestOpContextBuilder#defaultCharset(Charset)}
+ * <li class='ja'>{@link Rest#defaultCharset}
* </ul>
*/
String defaultCharset() default "";
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
index 49a0b51..03b1cb1 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
@@ -19,6 +19,7 @@ import static org.apache.juneau.rest.util.RestUtils.*;
import static org.apache.juneau.http.HttpParts.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
@@ -465,7 +466,7 @@ public class RestDeleteAnnotation {
b.prependTo(REST_guards, reverse(a.guards()));
b.matchers(a.matchers());
value(a.clientVersion()).ifPresent(x ->
b.clientVersion(x));
- b.setIfNotEmpty(REST_defaultCharset,
string(a.defaultCharset()));
+
value(a.defaultCharset()).map(Charset::forName).ifPresent(x ->
b.defaultCharset(x));
stringStream(a.path()).forEach(x -> b.path(x));
value(a.value()).ifPresent(x -> b.path(x));
cdStream(a.rolesDeclared()).forEach(x ->
b.addTo(REST_rolesDeclared, x));
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGet.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGet.java
index 2723575..188bfc7 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGet.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGet.java
@@ -16,6 +16,7 @@ import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.rest.*;
@@ -96,7 +97,7 @@ public @interface RestGet {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='jm'>{@link
RestContextBuilder#clientVersionHeader(String)}
* </ul>
*/
String clientVersion() default "";
@@ -179,7 +180,9 @@ public @interface RestGet {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_defaultCharset}
+ * <li class='jm'>{@link
RestContextBuilder#defaultCharset(Charset)}
+ * <li class='jm'>{@link
RestOpContextBuilder#defaultCharset(Charset)}
+ * <li class='ja'>{@link Rest#defaultCharset}
* </ul>
*/
String defaultCharset() default "";
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
index 3612818..d2572e2 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
@@ -19,6 +19,7 @@ import static org.apache.juneau.rest.util.RestUtils.*;
import static org.apache.juneau.http.HttpParts.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
@@ -521,7 +522,7 @@ public class RestGetAnnotation {
b.prependTo(REST_guards, reverse(a.guards()));
b.matchers(a.matchers());
value(a.clientVersion()).ifPresent(x ->
b.clientVersion(x));
- b.setIfNotEmpty(REST_defaultCharset,
string(a.defaultCharset()));
+
value(a.defaultCharset()).map(Charset::forName).ifPresent(x ->
b.defaultCharset(x));
stringStream(a.path()).forEach(x -> b.path(x));
value(a.value()).ifPresent(x -> b.path(x));
cdStream(a.rolesDeclared()).forEach(x ->
b.addTo(REST_rolesDeclared, x));
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOp.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOp.java
index a7cea06..14304e5 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOp.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOp.java
@@ -16,6 +16,7 @@ import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.rest.*;
@@ -94,7 +95,7 @@ public @interface RestOp {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='jm'>{@link
RestContextBuilder#clientVersionHeader(String)}
* </ul>
*/
String clientVersion() default "";
@@ -195,7 +196,9 @@ public @interface RestOp {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_defaultCharset}
+ * <li class='jm'>{@link
RestContextBuilder#defaultCharset(Charset)}
+ * <li class='jm'>{@link
RestOpContextBuilder#defaultCharset(Charset)}
+ * <li class='ja'>{@link Rest#defaultCharset}
* </ul>
*/
String defaultCharset() default "";
@@ -435,7 +438,9 @@ public @interface RestOp {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_maxInput}
+ * <li class='jm'>{@link RestContextBuilder#maxInput(String)}
+ * <li class='jm'>{@link RestOpContextBuilder#maxInput(String)}
+ * <li class='ja'>{@link Rest#maxInput}
* </ul>
*/
String maxInput() default "";
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
index 0ec5490..5e34d85 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
@@ -19,6 +19,7 @@ import static org.apache.juneau.rest.util.RestUtils.*;
import static org.apache.juneau.http.HttpParts.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
@@ -625,8 +626,8 @@ public class RestOpAnnotation {
b.prependTo(REST_guards, reverse(a.guards()));
b.matchers(a.matchers());
value(a.clientVersion()).ifPresent(x ->
b.clientVersion(x));
- b.setIfNotEmpty(REST_defaultCharset,
string(a.defaultCharset()));
- b.setIfNotEmpty(REST_maxInput, string(a.maxInput()));
+
value(a.defaultCharset()).map(Charset::forName).ifPresent(x ->
b.defaultCharset(x));
+ value(a.maxInput()).ifPresent(x -> b.maxInput(x));
stringStream(a.path()).forEach(x -> b.path(x));
cdStream(a.rolesDeclared()).forEach(x ->
b.addTo(REST_rolesDeclared, x));
b.addToIfNotEmpty(REST_roleGuard,
string(a.roleGuard()));
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPost.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPost.java
index 74e7253..8f85585 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPost.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPost.java
@@ -16,6 +16,7 @@ import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.rest.*;
@@ -96,7 +97,7 @@ public @interface RestPost {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='jm'>{@link
RestContextBuilder#clientVersionHeader(String)}
* </ul>
*/
String clientVersion() default "";
@@ -197,7 +198,9 @@ public @interface RestPost {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_defaultCharset}
+ * <li class='jm'>{@link
RestContextBuilder#defaultCharset(Charset)}
+ * <li class='jm'>{@link
RestOpContextBuilder#defaultCharset(Charset)}
+ * <li class='ja'>{@link Rest#defaultCharset}
* </ul>
*/
String defaultCharset() default "";
@@ -437,7 +440,9 @@ public @interface RestPost {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_maxInput}
+ * <li class='jm'>{@link RestContextBuilder#maxInput(String)}
+ * <li class='jm'>{@link RestOpContextBuilder#maxInput(String)}
+ * <li class='ja'>{@link Rest#maxInput}
* </ul>
*/
String maxInput() default "";
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
index f1fb4b9..ac4a714 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
@@ -19,6 +19,7 @@ import static org.apache.juneau.rest.util.RestUtils.*;
import static org.apache.juneau.http.HttpParts.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
@@ -610,8 +611,8 @@ public class RestPostAnnotation {
b.prependTo(REST_guards, reverse(a.guards()));
b.matchers(a.matchers());
value(a.clientVersion()).ifPresent(x ->
b.clientVersion(x));
- b.setIfNotEmpty(REST_defaultCharset,
string(a.defaultCharset()));
- b.setIfNotEmpty(REST_maxInput, string(a.maxInput()));
+
value(a.defaultCharset()).map(Charset::forName).ifPresent(x ->
b.defaultCharset(x));
+ value(a.maxInput()).ifPresent(x -> b.maxInput(x));
stringStream(a.path()).forEach(x -> b.path(x));
value(a.value()).ifPresent(x -> b.path(x));
cdStream(a.rolesDeclared()).forEach(x ->
b.addTo(REST_rolesDeclared, x));
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPut.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPut.java
index b848ac0..9139625 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPut.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPut.java
@@ -16,6 +16,7 @@ import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.rest.*;
@@ -96,7 +97,7 @@ public @interface RestPut {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_clientVersionHeader}
+ * <li class='jm'>{@link
RestContextBuilder#clientVersionHeader(String)}
* </ul>
*/
String clientVersion() default "";
@@ -197,7 +198,9 @@ public @interface RestPut {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_defaultCharset}
+ * <li class='jm'>{@link
RestContextBuilder#defaultCharset(Charset)}
+ * <li class='jm'>{@link
RestOpContextBuilder#defaultCharset(Charset)}
+ * <li class='ja'>{@link Rest#defaultCharset}
* </ul>
*/
String defaultCharset() default "";
@@ -437,7 +440,9 @@ public @interface RestPut {
* </ul>
*
* <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_maxInput}
+ * <li class='jm'>{@link RestContextBuilder#maxInput(String)}
+ * <li class='jm'>{@link RestOpContextBuilder#maxInput(String)}
+ * <li class='ja'>{@link Rest#maxInput}
* </ul>
*/
String maxInput() default "";
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
index 08b6279..b931366 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
@@ -19,6 +19,7 @@ import static org.apache.juneau.rest.util.RestUtils.*;
import static org.apache.juneau.http.HttpParts.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
@@ -610,8 +611,8 @@ public class RestPutAnnotation {
b.prependTo(REST_guards, reverse(a.guards()));
b.matchers(a.matchers());
value(a.clientVersion()).ifPresent(x ->
b.clientVersion(x));
- b.setIfNotEmpty(REST_defaultCharset,
string(a.defaultCharset()));
- b.setIfNotEmpty(REST_maxInput, string(a.maxInput()));
+
value(a.defaultCharset()).map(Charset::forName).ifPresent(x ->
b.defaultCharset(x));
+ value(a.maxInput()).ifPresent(x -> b.maxInput(x));
stringStream(a.path()).forEach(x -> b.path(x));
value(a.value()).ifPresent(x -> b.path(x));
cdStream(a.rolesDeclared()).forEach(x ->
b.addTo(REST_rolesDeclared, x));