From a9879df8b029b6582c87720a367f42672e27ca22 Mon Sep 17 00:00:00 2001 From: Tristan Tarrant Date: Mon, 28 Aug 2017 13:00:59 +0200 Subject: [PATCH] ISPN-8229 Add Max Content Length configuration to the REST endpoint --- .../persistence/rest/RestStore.java | 2 +- ...actRestStoreConfigurationChildBuilder.java | 5 +++ .../rest/configuration/Attribute.java | 3 +- .../ConnectionPoolConfiguration.java | 12 +++--- .../configuration/RestStoreConfiguration.java | 23 +++++++---- .../RestStoreConfigurationBuilder.java | 8 +++- .../RestStoreConfigurationChildBuilder.java | 5 +++ .../RestStoreConfigurationParser.java | 4 ++ .../infinispan-cachestore-rest-config-9.2.xsd | 5 +++ .../configuration/XmlFileParsingTest.java | 1 + .../src/test/resources/rest-cl-config.xml | 8 ++-- .../server/endpoint/subsystem/Attribute.java | 1 + .../subsystem/EndpointSubsystemReader.java | 4 ++ .../server/endpoint/subsystem/ModelKeys.java | 1 + .../subsystem/RestConnectorResource.java | 10 ++++- .../endpoint/subsystem/RestService.java | 8 +++- .../endpoint/subsystem/RestSubsystemAdd.java | 3 +- .../subsystem/LocalDescriptions.properties | 1 + .../schema/jboss-infinispan-endpoint_9_2.xsd | 5 +++ .../endpoint/EndpointSubsystemTestCase.java | 2 +- .../server/endpoint/endpoint-9.2.xml | 38 +++++++++---------- .../infinispan/subsystem/Attribute.java | 1 + .../subsystem/CacheConfigurationAdd.java | 34 +++++------------ .../InfinispanSubsystemXMLReader.java | 18 +++++---- .../infinispan/subsystem/ModelKeys.java | 2 +- .../RestStoreConfigurationResource.java | 25 ++++++++---- .../subsystem/LocalDescriptions.properties | 1 + .../schema/jboss-infinispan-core_9_2.xsd | 5 +++ .../rest/Http11To2UpgradeHandler.java | 28 +++++++------- .../RestServerConfiguration.java | 8 +++- .../RestServerConfigurationBuilder.java | 14 +++++-- .../infinispan/rest/RestOperationsTest.java | 38 +++++++++++++++++++ .../rest/assertion/ResponseAssertion.java | 5 +++ .../rest/helper/RestServerHelper.java | 2 +- 34 files changed, 225 insertions(+), 105 deletions(-) diff --git a/persistence/rest/src/main/java/org/infinispan/persistence/rest/RestStore.java b/persistence/rest/src/main/java/org/infinispan/persistence/rest/RestStore.java index 63b1b5eeca49..07f2f459dae2 100644 --- a/persistence/rest/src/main/java/org/infinispan/persistence/rest/RestStore.java +++ b/persistence/rest/src/main/java/org/infinispan/persistence/rest/RestStore.java @@ -113,7 +113,7 @@ protected void initChannel(SocketChannel ch) { b.option(ChannelOption.SO_RCVBUF, pool.bufferSize()); b.option(ChannelOption.TCP_NODELAY, pool.tcpNoDelay()); bootstrap = b; - maxContentLength = 10 * 1024 * 1024; // TODO make this part of configuration options. + maxContentLength = configuration.maxContentLength(); this.key2StringMapper = Util.getInstance(configuration.key2StringMapper(), ctx.getCache().getAdvancedCache().getClassLoader()); this.key2StringMapper.setMarshaller(ctx.getMarshaller()); diff --git a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/AbstractRestStoreConfigurationChildBuilder.java b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/AbstractRestStoreConfigurationChildBuilder.java index c6522064f1fb..de4acab14a8a 100644 --- a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/AbstractRestStoreConfigurationChildBuilder.java +++ b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/AbstractRestStoreConfigurationChildBuilder.java @@ -70,4 +70,9 @@ public RestStoreConfigurationBuilder appendCacheNameToPath(boolean appendCacheNa public RestStoreConfigurationBuilder rawValues(boolean rawValues) { return builder.rawValues(rawValues); } + + @Override + public RestStoreConfigurationBuilder maxContentLength(int maxContentLength) { + return builder.maxContentLength(maxContentLength); + } } diff --git a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/Attribute.java b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/Attribute.java index 4e64449b3d76..53e07ffded0b 100644 --- a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/Attribute.java +++ b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/Attribute.java @@ -25,7 +25,8 @@ public enum Attribute { PORT("port"), RAW_VALUES("raw-values"), SOCKET_TIMEOUT("socket-timeout"), - TCP_NO_DELAY("tcp-no-delay"), ; + TCP_NO_DELAY("tcp-no-delay"), + MAX_CONTENT_LENGTH("max-content-length"); private final String name; diff --git a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/ConnectionPoolConfiguration.java b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/ConnectionPoolConfiguration.java index f5f6e843c160..05e9cfca292f 100644 --- a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/ConnectionPoolConfiguration.java +++ b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/ConnectionPoolConfiguration.java @@ -12,12 +12,12 @@ */ @BuiltBy(ConnectionPoolConfigurationBuilder.class) public class ConnectionPoolConfiguration { - static final AttributeDefinition CONNECTION_TIMEOUT = AttributeDefinition.builder("connectionTimeout", 60000).immutable().build(); - static final AttributeDefinition MAX_CONNECTIONS_PER_HOST = AttributeDefinition.builder("maxConnectionsPerHostTimeout", 4).immutable().build(); - static final AttributeDefinition MAX_TOTAL_CONNECTIONS = AttributeDefinition.builder("maxTotalConnections", 20).immutable().build(); - static final AttributeDefinition BUFFER_SIZE = AttributeDefinition.builder("bufferSize", 8192).immutable().build(); - static final AttributeDefinition SOCKET_TIMEOUT = AttributeDefinition.builder("socketTimeout", 60000).immutable().build(); - static final AttributeDefinition TCP_NO_DELAY = AttributeDefinition.builder("tcpNoDelay", true).immutable().build(); + public static final AttributeDefinition CONNECTION_TIMEOUT = AttributeDefinition.builder("connectionTimeout", 60000).immutable().build(); + public static final AttributeDefinition MAX_CONNECTIONS_PER_HOST = AttributeDefinition.builder("maxConnectionsPerHostTimeout", 4).immutable().build(); + public static final AttributeDefinition MAX_TOTAL_CONNECTIONS = AttributeDefinition.builder("maxTotalConnections", 20).immutable().build(); + public static final AttributeDefinition BUFFER_SIZE = AttributeDefinition.builder("bufferSize", 8192).immutable().build(); + public static final AttributeDefinition SOCKET_TIMEOUT = AttributeDefinition.builder("socketTimeout", 60000).immutable().build(); + public static final AttributeDefinition TCP_NO_DELAY = AttributeDefinition.builder("tcpNoDelay", true).immutable().build(); static AttributeSet attributeDefinitionSet() { return new AttributeSet(ConnectionPoolConfiguration.class, CONNECTION_TIMEOUT, MAX_CONNECTIONS_PER_HOST, diff --git a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfiguration.java b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfiguration.java index 3157f4280106..119b713989a3 100644 --- a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfiguration.java +++ b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfiguration.java @@ -23,16 +23,17 @@ @ConfigurationFor(RestStore.class) @SerializedWith(RestStoreConfigurationSerializer.class) public class RestStoreConfiguration extends AbstractStoreConfiguration { - static final AttributeDefinition KEY2STRING_MAPPER = AttributeDefinition.builder("key2StringMapper", WrappedByteArrayOrPrimitiveMapper.class.getName()).immutable().xmlName("key-to-string-mapper").build(); - static final AttributeDefinition METADATA_HELPER = AttributeDefinition.builder("metadataHelper", EmbeddedMetadataHelper.class.getName()).immutable().build(); - static final AttributeDefinition HOST = AttributeDefinition.builder("host", null, String.class).immutable().autoPersist(false).build(); - static final AttributeDefinition PORT = AttributeDefinition.builder("port", 80).immutable().autoPersist(false).build(); - static final AttributeDefinition PATH = AttributeDefinition.builder("path", "/").immutable().build(); - static final AttributeDefinition APPEND_CACHE_NAME_TO_PATH = AttributeDefinition.builder("appendCacheNameToPath", false).immutable().build(); - static final AttributeDefinition RAW_VALUES = AttributeDefinition.builder("rawValues", false).immutable().build(); + public static final AttributeDefinition KEY2STRING_MAPPER = AttributeDefinition.builder("key2StringMapper", WrappedByteArrayOrPrimitiveMapper.class.getName()).immutable().xmlName("key-to-string-mapper").build(); + public static final AttributeDefinition METADATA_HELPER = AttributeDefinition.builder("metadataHelper", EmbeddedMetadataHelper.class.getName()).immutable().build(); + public static final AttributeDefinition HOST = AttributeDefinition.builder("host", null, String.class).immutable().autoPersist(false).build(); + public static final AttributeDefinition PORT = AttributeDefinition.builder("port", 80).immutable().autoPersist(false).build(); + public static final AttributeDefinition PATH = AttributeDefinition.builder("path", "/").immutable().build(); + public static final AttributeDefinition APPEND_CACHE_NAME_TO_PATH = AttributeDefinition.builder("appendCacheNameToPath", false).immutable().build(); + public static final AttributeDefinition RAW_VALUES = AttributeDefinition.builder("rawValues", false).immutable().build(); + public static final AttributeDefinition MAX_CONTENT_LENGTH = AttributeDefinition.builder("maxContentLength", 10 * 1024 * 1024).immutable().build(); public static AttributeSet attributeDefinitionSet() { - return new AttributeSet(RestStoreConfiguration.class, AbstractStoreConfiguration.attributeDefinitionSet(), KEY2STRING_MAPPER, METADATA_HELPER, HOST, PORT, PATH, APPEND_CACHE_NAME_TO_PATH, RAW_VALUES); + return new AttributeSet(RestStoreConfiguration.class, AbstractStoreConfiguration.attributeDefinitionSet(), KEY2STRING_MAPPER, METADATA_HELPER, HOST, PORT, PATH, APPEND_CACHE_NAME_TO_PATH, RAW_VALUES, MAX_CONTENT_LENGTH); } private final Attribute key2StringMapper; @@ -42,6 +43,7 @@ public static AttributeSet attributeDefinitionSet() { private final Attribute path; private final Attribute appendCacheNameToPath; private final Attribute rawValues; + private final Attribute maxContentLength; private final ConnectionPoolConfiguration connectionPool; public RestStoreConfiguration(AttributeSet attributes, @@ -54,6 +56,7 @@ public RestStoreConfiguration(AttributeSet attributes, path = attributes.attribute(PATH); appendCacheNameToPath = attributes.attribute(APPEND_CACHE_NAME_TO_PATH); rawValues = attributes.attribute(RAW_VALUES); + maxContentLength = attributes.attribute(MAX_CONTENT_LENGTH); this.connectionPool = connectionPool; } @@ -89,6 +92,10 @@ public boolean rawValues() { return rawValues.get(); } + public int maxContentLength() { + return maxContentLength.get(); + } + @Override public String toString() { return "RestStoreConfiguration [connectionPool=" + connectionPool + ", attributes=" + attributes + "]"; diff --git a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationBuilder.java b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationBuilder.java index 91cc38fae46b..802166308fee 100644 --- a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationBuilder.java +++ b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationBuilder.java @@ -3,6 +3,7 @@ import static org.infinispan.persistence.rest.configuration.RestStoreConfiguration.APPEND_CACHE_NAME_TO_PATH; import static org.infinispan.persistence.rest.configuration.RestStoreConfiguration.HOST; import static org.infinispan.persistence.rest.configuration.RestStoreConfiguration.KEY2STRING_MAPPER; +import static org.infinispan.persistence.rest.configuration.RestStoreConfiguration.MAX_CONTENT_LENGTH; import static org.infinispan.persistence.rest.configuration.RestStoreConfiguration.METADATA_HELPER; import static org.infinispan.persistence.rest.configuration.RestStoreConfiguration.PATH; import static org.infinispan.persistence.rest.configuration.RestStoreConfiguration.PORT; @@ -52,7 +53,6 @@ public RestStoreConfigurationBuilder key2StringMapper(String key2StringMapper) { return this; } - @Override public RestStoreConfigurationBuilder key2StringMapper(Class klass) { attributes.attribute(KEY2STRING_MAPPER).set(klass.getName()); @@ -95,6 +95,12 @@ public RestStoreConfigurationBuilder rawValues(boolean rawValues) { return this; } + @Override + public RestStoreConfigurationBuilder maxContentLength(int maxContentLength) { + attributes.attribute(MAX_CONTENT_LENGTH).set(maxContentLength); + return this; + } + @Override public RestStoreConfiguration create() { return new RestStoreConfiguration(attributes.protect(), async.create(), diff --git a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationChildBuilder.java b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationChildBuilder.java index a7dba4ca076c..f7faec87e01d 100644 --- a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationChildBuilder.java +++ b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationChildBuilder.java @@ -67,4 +67,9 @@ public interface RestStoreConfigurationChildBuilder extends StoreConfiguratio * Reads/writes "raw" values to the REST server instead of marshalling (used by the rolling upgrades feature) */ RestStoreConfigurationBuilder rawValues(boolean rawValues); + + /** + * Sets the maximum content length. Defaults to 10M. + */ + RestStoreConfigurationBuilder maxContentLength(int maxContentLength); } diff --git a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationParser.java b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationParser.java index 9a1ff7c46560..d64fb0ad0ff0 100644 --- a/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationParser.java +++ b/persistence/rest/src/main/java/org/infinispan/persistence/rest/configuration/RestStoreConfigurationParser.java @@ -168,6 +168,10 @@ private void parseRestStoreAttributes(XMLExtendedStreamReader reader, RestStoreC builder.rawValues(Boolean.parseBoolean(value)); break; } + case MAX_CONTENT_LENGTH: { + builder.maxContentLength(Integer.parseInt(value)); + break; + } default: { Parser.parseStoreAttribute(reader, i, builder); break; diff --git a/persistence/rest/src/main/resources/schema/infinispan-cachestore-rest-config-9.2.xsd b/persistence/rest/src/main/resources/schema/infinispan-cachestore-rest-config-9.2.xsd index 9bbf8ba09c89..be4d7b43bd64 100644 --- a/persistence/rest/src/main/resources/schema/infinispan-cachestore-rest-config-9.2.xsd +++ b/persistence/rest/src/main/resources/schema/infinispan-cachestore-rest-config-9.2.xsd @@ -42,6 +42,11 @@ + + + The maximum allowed content length of a POST/PUT request. + + diff --git a/persistence/rest/src/test/java/org/infinispan/persistence/rest/configuration/XmlFileParsingTest.java b/persistence/rest/src/test/java/org/infinispan/persistence/rest/configuration/XmlFileParsingTest.java index 600a10b389c1..d759df051f2b 100644 --- a/persistence/rest/src/test/java/org/infinispan/persistence/rest/configuration/XmlFileParsingTest.java +++ b/persistence/rest/src/test/java/org/infinispan/persistence/rest/configuration/XmlFileParsingTest.java @@ -33,6 +33,7 @@ public void testRemoteCacheStore() throws Exception { assertEquals("localhost", store.host()); assertEquals("/rest/___defaultcache/", store.path()); assertEquals(18212, store.port()); + assertEquals(15000000, store.maxContentLength()); ConnectionPoolConfiguration connectionPool = store.connectionPool(); assertEquals(10000, connectionPool.connectionTimeout()); assertEquals(10, connectionPool.maxConnectionsPerHost()); diff --git a/persistence/rest/src/test/resources/rest-cl-config.xml b/persistence/rest/src/test/resources/rest-cl-config.xml index 9ee4f6491d7e..4314436b469e 100644 --- a/persistence/rest/src/test/resources/rest-cl-config.xml +++ b/persistence/rest/src/test/resources/rest-cl-config.xml @@ -3,8 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:infinispan:config:9.2 http://www.infinispan.org/schemas/infinispan-config-9.2.xsd urn:infinispan:config:store:rest:9.2 http://www.infinispan.org/schemas/infinispan-cachestore-rest-config-9.2.xsd" - xmlns="urn:infinispan:config:9.2" - xmlns:remote="urn:infinispan:config:store:rest:9.2" > + xmlns="urn:infinispan:config:9.2"> @@ -12,9 +11,10 @@ - + key-to-string-mapper="org.infinispan.persistence.keymappers.WrappedByteArrayOrPrimitiveMapper" + max-content-length="15000000"> + diff --git a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/Attribute.java b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/Attribute.java index ce1f1c85eb4d..11ed1e7a5cd0 100644 --- a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/Attribute.java +++ b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/Attribute.java @@ -51,6 +51,7 @@ public enum Attribute { LAZY_RETRIEVAL(ModelKeys.LAZY_RETRIEVAL), LOCK_TIMEOUT(ModelKeys.LOCK_TIMEOUT), REPLICATION_TIMEOUT(ModelKeys.REPLICATION_TIMEOUT), + MAX_CONTENT_LENGTH(ModelKeys.MAX_CONTENT_LENGTH), NAME(ModelKeys.NAME), QOP(ModelKeys.QOP), RECEIVE_BUFFER_SIZE(ModelKeys.RECEIVE_BUFFER_SIZE), diff --git a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/EndpointSubsystemReader.java b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/EndpointSubsystemReader.java index 3cd433592876..5f25e31e5330 100644 --- a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/EndpointSubsystemReader.java +++ b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/EndpointSubsystemReader.java @@ -295,6 +295,10 @@ private void parseRestConnector(XMLExtendedStreamReader reader, PathAddress subs name = value; break; } + case MAX_CONTENT_LENGTH: { + RestConnectorResource.MAX_CONTENT_LENGTH.parseAndSetParameter(value, connector, reader); + break; + } case SECURITY_DOMAIN: { if (namespace.since(Namespace.INFINISPAN_ENDPOINT_9_0)) { throw ParseUtils.unexpectedAttribute(reader, i); diff --git a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/ModelKeys.java b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/ModelKeys.java index e6dce71f9272..828063ca59ad 100644 --- a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/ModelKeys.java +++ b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/ModelKeys.java @@ -51,6 +51,7 @@ public class ModelKeys { public static final String AUTH_METHOD = "auth-method"; // string public static final String SECURITY_MODE = "security-mode"; // string public static final String EXTENDED_HEADERS = "extended-headers"; //enum + public static final String MAX_CONTENT_LENGTH = "max-content-length"; //int public static final String TOPOLOGY_STATE_TRANSFER_NAME = "TOPOLOGY_STATE_TRANSFER"; public static final String TOPOLOGY_STATE_TRANSFER = "topology-state-transfer"; diff --git a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestConnectorResource.java b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestConnectorResource.java index 9974990caf4e..72e9a2f90b06 100644 --- a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestConnectorResource.java +++ b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestConnectorResource.java @@ -65,7 +65,15 @@ public class RestConnectorResource extends CommonConnectorResource { .setRestartAllServices() .build(); - static final SimpleAttributeDefinition[] REST_ATTRIBUTES = { SOCKET_BINDING, CONTEXT_PATH, EXTENDED_HEADERS }; + static final SimpleAttributeDefinition MAX_CONTENT_LENGTH = + new SimpleAttributeDefinitionBuilder(ModelKeys.MAX_CONTENT_LENGTH, ModelType.INT, true) + .setAllowExpression(true) + .setXmlName(ModelKeys.MAX_CONTENT_LENGTH) + .setRestartAllServices() + .setDefaultValue(new ModelNode().set(RestServerConfigurationBuilder.DEFAULT_MAX_CONTENT_LENGTH)) + .build(); + + static final SimpleAttributeDefinition[] REST_ATTRIBUTES = { SOCKET_BINDING, CONTEXT_PATH, EXTENDED_HEADERS, MAX_CONTENT_LENGTH }; public RestConnectorResource(boolean isRuntimeRegistration) { super(REST_CONNECTOR_PATH, EndpointExtension.getResourceDescriptionResolver(ModelKeys.REST_CONNECTOR), RestSubsystemAdd.INSTANCE, RestSubsystemRemove.INSTANCE, isRuntimeRegistration); diff --git a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestService.java b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestService.java index 1bcaaed73054..4a89410bcc2f 100644 --- a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestService.java +++ b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestService.java @@ -66,20 +66,24 @@ public class RestService implements Service, EncryptableService { private final Set ignoredCaches; private RestServer restServer; private boolean clientAuth; + private final int maxContentLength; - public RestService(String serverName, RestAuthMethod authMethod, String contextPath, ExtendedHeaders extendedHeaders, Set ignoredCaches) { + public RestService(String serverName, RestAuthMethod authMethod, String contextPath, ExtendedHeaders extendedHeaders, Set ignoredCaches, + int maxContentLength) { this.serverName = serverName; this.authMethod = authMethod; this.contextPath = contextPath; this.extendedHeaders = extendedHeaders; this.ignoredCaches = ignoredCaches; + this.maxContentLength = maxContentLength; } /** {@inheritDoc} */ @Override public synchronized void start(StartContext startContext) throws StartException { RestServerConfigurationBuilder builder = new RestServerConfigurationBuilder(); - builder.name(serverName).extendedHeaders(extendedHeaders).ignoredCaches(ignoredCaches).contextPath(contextPath); + builder.name(serverName).extendedHeaders(extendedHeaders).ignoredCaches(ignoredCaches).contextPath(contextPath) + .maxContentLength(maxContentLength); EncryptableServiceHelper.fillSecurityConfiguration(this, builder.ssl()); diff --git a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestSubsystemAdd.java b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestSubsystemAdd.java index 5704abc21dd0..9f67dde819f7 100644 --- a/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestSubsystemAdd.java +++ b/server/integration/endpoint/src/main/java/org/infinispan/server/endpoint/subsystem/RestSubsystemAdd.java @@ -64,8 +64,9 @@ protected void performRuntime(OperationContext context, ModelNode operation, Mod ignoredCaches = config.get(ModelKeys.IGNORED_CACHES).asList() .stream().map(ModelNode::asString).collect(Collectors.toSet()); } + int maxContentLength = RestConnectorResource.MAX_CONTENT_LENGTH.resolveModelAttribute(context, config).asInt(); // Create the service - final RestService service = new RestService(getServiceName(config), restAuthMethod, cleanContextPath(contextPath), extendedHeaders, ignoredCaches); + final RestService service = new RestService(getServiceName(config), restAuthMethod, cleanContextPath(contextPath), extendedHeaders, ignoredCaches, maxContentLength); // Setup the various dependencies with injectors and install the service ServiceBuilder builder = context.getServiceTarget().addService(EndpointUtils.getServiceName(operation, "rest"), service); diff --git a/server/integration/endpoint/src/main/resources/org/infinispan/server/endpoint/subsystem/LocalDescriptions.properties b/server/integration/endpoint/src/main/resources/org/infinispan/server/endpoint/subsystem/LocalDescriptions.properties index 216c145a5016..f252c7c9eca1 100644 --- a/server/integration/endpoint/src/main/resources/org/infinispan/server/endpoint/subsystem/LocalDescriptions.properties +++ b/server/integration/endpoint/src/main/resources/org/infinispan/server/endpoint/subsystem/LocalDescriptions.properties @@ -45,6 +45,7 @@ rest-connector.cache-container=The cache container to use rest-connector.context-path=The context path on which the REST connector should be published rest-connector.socket-binding=The socket binding to use for this connector rest-connector.extended-headers=Allow retrieval of extended information about entries (NEVER, ON_DEMAND) +rest-connector.max-content-length=Maximum allowed content length websocket-connector=A WebSocket connector websocket-connector.add=Adds a WebSocket connector websocket-connector.remove=Removes a WebSocket connector diff --git a/server/integration/endpoint/src/main/resources/schema/jboss-infinispan-endpoint_9_2.xsd b/server/integration/endpoint/src/main/resources/schema/jboss-infinispan-endpoint_9_2.xsd index 9d0763cf7339..5e57324925ff 100644 --- a/server/integration/endpoint/src/main/resources/schema/jboss-infinispan-endpoint_9_2.xsd +++ b/server/integration/endpoint/src/main/resources/schema/jboss-infinispan-endpoint_9_2.xsd @@ -171,6 +171,11 @@ The list of ignored caches for this connector + + + Sets the maximum allowed content length. + + diff --git a/server/integration/endpoint/src/test/java/org/infinispan/server/endpoint/EndpointSubsystemTestCase.java b/server/integration/endpoint/src/test/java/org/infinispan/server/endpoint/EndpointSubsystemTestCase.java index 456fdb89f6e0..6826f00b92cf 100644 --- a/server/integration/endpoint/src/test/java/org/infinispan/server/endpoint/EndpointSubsystemTestCase.java +++ b/server/integration/endpoint/src/test/java/org/infinispan/server/endpoint/EndpointSubsystemTestCase.java @@ -71,7 +71,7 @@ public static Collection data() { Object[][] data = new Object[][] { { "endpoint-7.2.xml", 16, "schema/jboss-infinispan-endpoint_7_2.xsd", null }, { "endpoint-8.0.xml", 16, "schema/jboss-infinispan-endpoint_8_0.xsd", null }, - { "endpoint-9.0.xml", 38, "schema/jboss-infinispan-endpoint_9_0.xsd", new String[] { "/subsystem-templates/infinispan-endpoint.xml"} }, + { "endpoint-9.0.xml", 38, "schema/jboss-infinispan-endpoint_9_0.xsd", null }, { "endpoint-9.2.xml", 38, "schema/jboss-infinispan-endpoint_9_2.xsd", new String[] { "/subsystem-templates/infinispan-endpoint.xml"} }, }; return Arrays.asList(data); diff --git a/server/integration/endpoint/src/test/resources/org/infinispan/server/endpoint/endpoint-9.2.xml b/server/integration/endpoint/src/test/resources/org/infinispan/server/endpoint/endpoint-9.2.xml index 50d5dcdef96f..e437d69ea0a2 100644 --- a/server/integration/endpoint/src/test/resources/org/infinispan/server/endpoint/endpoint-9.2.xml +++ b/server/integration/endpoint/src/test/resources/org/infinispan/server/endpoint/endpoint-9.2.xml @@ -26,7 +26,7 @@ - + @@ -35,22 +35,22 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Attribute.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Attribute.java index a9148802df41..a05e2f7e8fa1 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Attribute.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/Attribute.java @@ -105,6 +105,7 @@ public enum Attribute { MARSHALLER(ModelKeys.MARSHALLER), MAX_BATCH_SIZE(ModelKeys.MAX_BATCH_SIZE), MAX_CONNECTIONS_PER_HOST(ModelKeys.MAX_CONNECTIONS_PER_HOST), + MAX_CONTENT_LENGTH(ModelKeys.MAX_CONTENT_LENGTH), MAX_ENTRIES(ModelKeys.MAX_ENTRIES), MAX_IDLE(ModelKeys.MAX_IDLE), MAX_RETRIES(ModelKeys.MAX_RETRIES), diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheConfigurationAdd.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheConfigurationAdd.java index 45ad4de09c30..8d57404b6d6d 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheConfigurationAdd.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/CacheConfigurationAdd.java @@ -74,6 +74,7 @@ import org.infinispan.persistence.remote.configuration.AuthenticationConfigurationBuilder; import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationBuilder; import org.infinispan.persistence.remote.configuration.SslConfigurationBuilder; +import org.infinispan.persistence.rest.RestStore; import org.infinispan.persistence.rest.configuration.RestStoreConfigurationBuilder; import org.infinispan.persistence.rest.metadata.MimeMetadataHelper; import org.infinispan.persistence.rocksdb.configuration.CompressionType; @@ -891,35 +892,20 @@ public void inject(OutboundSocketBinding value) { }; dependencies.add(new Dependency<>(OutboundSocketBinding.OUTBOUND_SOCKET_BINDING_BASE_SERVICE_NAME.append(outboundSocketBinding), OutboundSocketBinding.class, injector)); } - if (store.hasDefined(ModelKeys.APPEND_CACHE_NAME_TO_PATH)) { - builder.appendCacheNameToPath(store.require(ModelKeys.APPEND_CACHE_NAME_TO_PATH).asBoolean()); - } - if (store.hasDefined(ModelKeys.PATH)) { - builder.path(store.get(ModelKeys.PATH).asString()); - } + builder.appendCacheNameToPath(RestStoreConfigurationResource.APPEND_CACHE_NAME_TO_PATH.resolveModelAttribute(context, store).asBoolean()); + builder.path(RestStoreConfigurationResource.PATH.resolveModelAttribute(context, store).asString()); + builder.maxContentLength(RestStoreConfigurationResource.MAX_CONTENT_LENGTH.resolveModelAttribute(context, store).asInt()); builder.rawValues(true); builder.metadataHelper(MimeMetadataHelper.class); if (store.hasDefined(ModelKeys.CONNECTION_POOL)) { ModelNode pool = store.get(ModelKeys.CONNECTION_POOL); - if (pool.hasDefined(ModelKeys.CONNECTION_TIMEOUT)) { - builder.connectionPool().connectionTimeout(pool.require(ModelKeys.CONNECTION_TIMEOUT).asInt()); - } - if (pool.hasDefined(ModelKeys.MAX_CONNECTIONS_PER_HOST)) { - builder.connectionPool().maxConnectionsPerHost(pool.require(ModelKeys.MAX_CONNECTIONS_PER_HOST).asInt()); - } - if (pool.hasDefined(ModelKeys.MAX_TOTAL_CONNECTIONS)) { - builder.connectionPool().maxTotalConnections(pool.require(ModelKeys.MAX_TOTAL_CONNECTIONS).asInt()); - } - if (pool.hasDefined(ModelKeys.BUFFER_SIZE)) { - builder.connectionPool().bufferSize(pool.require(ModelKeys.BUFFER_SIZE).asInt()); - } - if (pool.hasDefined(ModelKeys.SOCKET_TIMEOUT)) { - builder.connectionPool().socketTimeout(pool.require(ModelKeys.SOCKET_TIMEOUT).asInt()); - } - if (pool.hasDefined(ModelKeys.TCP_NO_DELAY)) { - builder.connectionPool().tcpNoDelay(pool.require(ModelKeys.TCP_NO_DELAY).asBoolean()); - } + builder.connectionPool().bufferSize(RestStoreConfigurationResource.BUFFER_SIZE.resolveModelAttribute(context, pool).asInt()); + builder.connectionPool().connectionTimeout(RestStoreConfigurationResource.CONNECTION_TIMEOUT.resolveModelAttribute(context, pool).asInt()); + builder.connectionPool().maxConnectionsPerHost(RestStoreConfigurationResource.MAX_CONNECTIONS_PER_HOST.resolveModelAttribute(context, pool).asInt()); + builder.connectionPool().maxTotalConnections(RestStoreConfigurationResource.MAX_TOTAL_CONNECTIONS.resolveModelAttribute(context, pool).asInt()); + builder.connectionPool().socketTimeout(RestStoreConfigurationResource.SOCKET_TIMEOUT.resolveModelAttribute(context, pool).asInt()); + builder.connectionPool().tcpNoDelay(RestStoreConfigurationResource.TCP_NO_DELAY.resolveModelAttribute(context, pool).asBoolean()); } return builder; } else if (storeKey.equals(ModelKeys.STORE)) { diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLReader.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLReader.java index 083e565279e7..fd1e6a5e5b24 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLReader.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/InfinispanSubsystemXMLReader.java @@ -1789,6 +1789,10 @@ private void parseRestStore(XMLExtendedStreamReader reader, ModelNode cache, Map RestStoreConfigurationResource.PATH.parseAndSetParameter(value, store, reader); break; } + case MAX_CONTENT_LENGTH: { + RestStoreConfigurationResource.MAX_CONTENT_LENGTH.parseAndSetParameter(value, store, reader); + break; + } default: { name = this.parseStoreAttribute(name, reader, i, attribute, value, store); @@ -1827,33 +1831,33 @@ private void parseRestStore(XMLExtendedStreamReader reader, ModelNode cache, Map operations.putAll(additionalConfigurationOperations); } - private void parseRestConnectionPool(XMLExtendedStreamReader reader, ModelNode table) throws XMLStreamException { + private void parseRestConnectionPool(XMLExtendedStreamReader reader, ModelNode pool) throws XMLStreamException { for (int i = 0; i < reader.getAttributeCount(); i++) { String value = reader.getAttributeValue(i); Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case BUFFER_SIZE: { - RestStoreConfigurationResource.BUFFER_SIZE.parseAndSetParameter(value, table, reader); + RestStoreConfigurationResource.BUFFER_SIZE.parseAndSetParameter(value, pool, reader); break; } case CONNECTION_TIMEOUT: { - RestStoreConfigurationResource.CONNECTION_TIMEOUT.parseAndSetParameter(value, table, reader); + RestStoreConfigurationResource.CONNECTION_TIMEOUT.parseAndSetParameter(value, pool, reader); break; } case MAX_CONNECTIONS_PER_HOST: { - RestStoreConfigurationResource.MAX_CONNECTIONS_PER_HOST.parseAndSetParameter(value, table, reader); + RestStoreConfigurationResource.MAX_CONNECTIONS_PER_HOST.parseAndSetParameter(value, pool, reader); break; } case MAX_TOTAL_CONNECTIONS: { - RestStoreConfigurationResource.MAX_TOTAL_CONNECTIONS.parseAndSetParameter(value, table, reader); + RestStoreConfigurationResource.MAX_TOTAL_CONNECTIONS.parseAndSetParameter(value, pool, reader); break; } case SOCKET_TIMEOUT: { - RestStoreConfigurationResource.SOCKET_TIMEOUT.parseAndSetParameter(value, table, reader); + RestStoreConfigurationResource.SOCKET_TIMEOUT.parseAndSetParameter(value, pool, reader); break; } case TCP_NO_DELAY: { - RestStoreConfigurationResource.TCP_NO_DELAY.parseAndSetParameter(value, table, reader); + RestStoreConfigurationResource.TCP_NO_DELAY.parseAndSetParameter(value, pool, reader); break; } default: { diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/ModelKeys.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/ModelKeys.java index d88fcedb3fa1..3be2b879b081 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/ModelKeys.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/ModelKeys.java @@ -155,6 +155,7 @@ public class ModelKeys { static final String MARSHALLER = "marshaller"; static final String MAX_BATCH_SIZE = "max-batch-size"; static final String MAX_CONNECTIONS_PER_HOST = "max-connections-per-host"; + static final String MAX_CONTENT_LENGTH = "max-content-length"; static final String MAX_ENTRIES = "max-entries"; static final String MAX_IDLE = "max-idle"; static final String MAX_RETRIES = "max-retries"; @@ -278,5 +279,4 @@ public class ModelKeys { static final String TRANSPORT_THREAD_POOL = "transport-thread-pool"; static final String READ_BATCH = "read-batch"; static final String WRITE_THREADS = "write-threads"; - } diff --git a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/RestStoreConfigurationResource.java b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/RestStoreConfigurationResource.java index 96e706c685cf..769230388e3a 100644 --- a/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/RestStoreConfigurationResource.java +++ b/server/integration/infinispan/src/main/java/org/jboss/as/clustering/infinispan/subsystem/RestStoreConfigurationResource.java @@ -22,6 +22,8 @@ package org.jboss.as.clustering.infinispan.subsystem; +import org.infinispan.persistence.rest.configuration.ConnectionPoolConfiguration; +import org.infinispan.persistence.rest.configuration.RestStoreConfiguration; import org.jboss.as.controller.AttributeDefinition; import org.jboss.as.controller.ObjectListAttributeDefinition; import org.jboss.as.controller.ObjectTypeAttributeDefinition; @@ -55,8 +57,15 @@ public class RestStoreConfigurationResource extends BaseStoreConfigurationResour .setXmlName(Attribute.APPEND_CACHE_NAME_TO_PATH.getLocalName()) .setAllowExpression(true) .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) - .setDefaultValue(new ModelNode().set(false)) + .setDefaultValue(new ModelNode().set(RestStoreConfiguration.APPEND_CACHE_NAME_TO_PATH.getDefaultValue().booleanValue())) .build(); + static final SimpleAttributeDefinition MAX_CONTENT_LENGTH = + new SimpleAttributeDefinitionBuilder(ModelKeys.MAX_CONTENT_LENGTH, ModelType.INT, true) + .setXmlName(Attribute.MAX_CONTENT_LENGTH.getLocalName()) + .setAllowExpression(true) + .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) + .setDefaultValue(new ModelNode().set(RestStoreConfiguration.MAX_CONTENT_LENGTH.getDefaultValue().intValue())) + .build(); // connection pool attributes static final SimpleAttributeDefinition BUFFER_SIZE = new SimpleAttributeDefinitionBuilder(ModelKeys.BUFFER_SIZE, ModelType.INT, true) @@ -64,7 +73,7 @@ public class RestStoreConfigurationResource extends BaseStoreConfigurationResour .setMeasurementUnit(MeasurementUnit.BYTES) .setAllowExpression(true) .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) - .setDefaultValue(new ModelNode().set(8192)) + .setDefaultValue(new ModelNode().set(ConnectionPoolConfiguration.BUFFER_SIZE.getDefaultValue().intValue())) .build(); static final SimpleAttributeDefinition CONNECTION_TIMEOUT = new SimpleAttributeDefinitionBuilder(ModelKeys.CONNECTION_TIMEOUT, ModelType.INT, true) @@ -72,21 +81,21 @@ public class RestStoreConfigurationResource extends BaseStoreConfigurationResour .setMeasurementUnit(MeasurementUnit.MILLISECONDS) .setAllowExpression(true) .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) - .setDefaultValue(new ModelNode().set(60000)) + .setDefaultValue(new ModelNode().set(ConnectionPoolConfiguration.CONNECTION_TIMEOUT.getDefaultValue().intValue())) .build(); static final SimpleAttributeDefinition MAX_CONNECTIONS_PER_HOST = new SimpleAttributeDefinitionBuilder(ModelKeys.MAX_CONNECTIONS_PER_HOST, ModelType.INT, true) .setXmlName(Attribute.MAX_CONNECTIONS_PER_HOST.getLocalName()) .setAllowExpression(true) .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) - .setDefaultValue(new ModelNode().set(4)) + .setDefaultValue(new ModelNode().set(ConnectionPoolConfiguration.MAX_CONNECTIONS_PER_HOST.getDefaultValue().intValue())) .build(); static final SimpleAttributeDefinition MAX_TOTAL_CONNECTIONS = new SimpleAttributeDefinitionBuilder(ModelKeys.MAX_TOTAL_CONNECTIONS, ModelType.INT, true) .setXmlName(Attribute.MAX_TOTAL_CONNECTIONS.getLocalName()) .setAllowExpression(true) .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) - .setDefaultValue(new ModelNode().set(20)) + .setDefaultValue(new ModelNode().set(ConnectionPoolConfiguration.MAX_TOTAL_CONNECTIONS.getDefaultValue().intValue())) .build(); static final SimpleAttributeDefinition SOCKET_TIMEOUT = new SimpleAttributeDefinitionBuilder(ModelKeys.SOCKET_TIMEOUT, ModelType.INT, true) @@ -94,14 +103,14 @@ public class RestStoreConfigurationResource extends BaseStoreConfigurationResour .setMeasurementUnit(MeasurementUnit.MILLISECONDS) .setAllowExpression(true) .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) - .setDefaultValue(new ModelNode().set(60000)) + .setDefaultValue(new ModelNode().set(ConnectionPoolConfiguration.SOCKET_TIMEOUT.getDefaultValue().intValue())) .build(); static final SimpleAttributeDefinition TCP_NO_DELAY = new SimpleAttributeDefinitionBuilder(ModelKeys.TCP_NO_DELAY, ModelType.BOOLEAN, true) .setXmlName(Attribute.TCP_NO_DELAY.getLocalName()) .setAllowExpression(true) .setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES) - .setDefaultValue(new ModelNode().set(true)) + .setDefaultValue(new ModelNode().set(ConnectionPoolConfiguration.TCP_NO_DELAY.getDefaultValue().booleanValue())) .build(); static final ObjectTypeAttributeDefinition CONNECTION_POOL = ObjectTypeAttributeDefinition. Builder.of(ModelKeys.CONNECTION_POOL, BUFFER_SIZE, CONNECTION_TIMEOUT, MAX_CONNECTIONS_PER_HOST, MAX_TOTAL_CONNECTIONS, SOCKET_TIMEOUT, TCP_NO_DELAY). @@ -126,7 +135,7 @@ public class RestStoreConfigurationResource extends BaseStoreConfigurationResour setAllowNull(false). build(); - static final AttributeDefinition[] REST_STORE_ATTRIBUTES = {PATH, APPEND_CACHE_NAME_TO_PATH, CONNECTION_POOL, REMOTE_SERVERS}; + static final AttributeDefinition[] REST_STORE_ATTRIBUTES = {PATH, APPEND_CACHE_NAME_TO_PATH, MAX_CONTENT_LENGTH, CONNECTION_POOL, REMOTE_SERVERS}; public RestStoreConfigurationResource(CacheConfigurationResource parent) { super(REST_STORE_PATH, ModelKeys.REST_STORE, parent, REST_STORE_ATTRIBUTES); diff --git a/server/integration/infinispan/src/main/resources/org/jboss/as/clustering/infinispan/subsystem/LocalDescriptions.properties b/server/integration/infinispan/src/main/resources/org/jboss/as/clustering/infinispan/subsystem/LocalDescriptions.properties index 98c08ebbdac4..2c4fd84458f9 100644 --- a/server/integration/infinispan/src/main/resources/org/jboss/as/clustering/infinispan/subsystem/LocalDescriptions.properties +++ b/server/integration/infinispan/src/main/resources/org/jboss/as/clustering/infinispan/subsystem/LocalDescriptions.properties @@ -484,6 +484,7 @@ datagrid-infinispan.remote-store.encryption.remove= datagrid-infinispan.rest-store=The cache REST store configuration. datagrid-infinispan.rest-store.path=The path portion of the URI of the remote REST endpoint. datagrid-infinispan.rest-store.append-cache-name-to-path=Whether to append the name of the cache to the path. +datagrid-infinispan.rest-store.max-content-length=The maximum allowed size for requests. datagrid-infinispan.rest-store.connection-pool=The configuration of the HTTP connection pool datagrid-infinispan.rest-store.connection-pool.connection-timeout=A connection timeout for remote cache communication. datagrid-infinispan.rest-store.connection-pool.max-connections-per-host=The maximum number of connections per host. diff --git a/server/integration/infinispan/src/main/resources/schema/jboss-infinispan-core_9_2.xsd b/server/integration/infinispan/src/main/resources/schema/jboss-infinispan-core_9_2.xsd index 5cca43e7996c..1861bc60c584 100644 --- a/server/integration/infinispan/src/main/resources/schema/jboss-infinispan-core_9_2.xsd +++ b/server/integration/infinispan/src/main/resources/schema/jboss-infinispan-core_9_2.xsd @@ -1130,6 +1130,11 @@ The path portion of the URI of the remote REST endpoint. + + + The maximum allowed content length of a POST/PUT request. + + diff --git a/server/rest/src/main/java/org/infinispan/rest/Http11To2UpgradeHandler.java b/server/rest/src/main/java/org/infinispan/rest/Http11To2UpgradeHandler.java index 7b73fda22b69..94d4c69fc66d 100644 --- a/server/rest/src/main/java/org/infinispan/rest/Http11To2UpgradeHandler.java +++ b/server/rest/src/main/java/org/infinispan/rest/Http11To2UpgradeHandler.java @@ -24,11 +24,8 @@ */ @ChannelHandler.Sharable public class Http11To2UpgradeHandler extends ApplicationProtocolNegotiationHandler { - - private static final int MAX_PAYLOAD_SIZE = 5 * 1024 * 1024; private static final int MAX_INITIAL_LINE_SIZE = 4096; private static final int MAX_HEADER_SIZE = 8192; - private static final int MAX_CONTENT_SIZE = MAX_PAYLOAD_SIZE + MAX_INITIAL_LINE_SIZE + MAX_HEADER_SIZE; private final RestServer restServer; @@ -62,24 +59,25 @@ private void configureHttp2(ChannelPipeline pipeline) { } private void configureHttp1(ChannelPipeline pipeline) { - final HttpServerCodec httpCodec = new HttpServerCodec(MAX_INITIAL_LINE_SIZE, MAX_HEADER_SIZE, MAX_PAYLOAD_SIZE); + final HttpServerCodec httpCodec = new HttpServerCodec(MAX_INITIAL_LINE_SIZE, MAX_HEADER_SIZE, restServer.getConfiguration().maxContentLength()); pipeline.addLast(httpCodec); - pipeline.addLast(new HttpServerUpgradeHandler(httpCodec, new HttpServerUpgradeHandler.UpgradeCodecFactory() { - @Override - public HttpServerUpgradeHandler.UpgradeCodec newUpgradeCodec(CharSequence protocol) { - if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) { - return new Http2ServerUpgradeCodec(getHttp11To2ConnectionHandler()); - } else { - // if we don't understand the protocol, we don't want to upgrade - return null; - } + pipeline.addLast(new HttpServerUpgradeHandler(httpCodec, protocol -> { + if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) { + return new Http2ServerUpgradeCodec(getHttp11To2ConnectionHandler()); + } else { + // if we don't understand the protocol, we don't want to upgrade + return null; } })); - pipeline.addLast(new HttpObjectAggregator(MAX_CONTENT_SIZE)); + pipeline.addLast(new HttpObjectAggregator(maxContentLength())); pipeline.addLast("rest-handler", getHttp1Handler()); } + private int maxContentLength() { + return restServer.getConfiguration().maxContentLength() + MAX_INITIAL_LINE_SIZE + MAX_HEADER_SIZE; + } + /** * Creates a handler for HTTP/1.1 -> HTTP/2 upgrade * @return @@ -90,7 +88,7 @@ private HttpToHttp2ConnectionHandler getHttp11To2ConnectionHandler() { InboundHttp2ToHttpAdapter listener = new InboundHttp2ToHttpAdapterBuilder(connection) .propagateSettings(true) .validateHttpHeaders(false) - .maxContentLength(MAX_CONTENT_SIZE) + .maxContentLength(maxContentLength()) .build(); return new HttpToHttp2ConnectionHandlerBuilder() diff --git a/server/rest/src/main/java/org/infinispan/rest/configuration/RestServerConfiguration.java b/server/rest/src/main/java/org/infinispan/rest/configuration/RestServerConfiguration.java index 8ce979114dd8..975ed7944e7c 100644 --- a/server/rest/src/main/java/org/infinispan/rest/configuration/RestServerConfiguration.java +++ b/server/rest/src/main/java/org/infinispan/rest/configuration/RestServerConfiguration.java @@ -11,14 +11,16 @@ public class RestServerConfiguration extends ProtocolServerConfiguration { private final ExtendedHeaders extendedHeaders; private final String contextPath; + private final int maxContentLength; RestServerConfiguration(String defaultCacheName, String name, ExtendedHeaders extendedHeaders, String host, int port, Set ignoredCaches, SslConfiguration ssl, boolean startTransport, String contextPath, - AdminOperationsHandler adminOperationsHandler) { + AdminOperationsHandler adminOperationsHandler, int maxContentLength) { super(defaultCacheName, name, host, port, -1, -1, -1, ssl, false, -1, ignoredCaches, startTransport, adminOperationsHandler); this.extendedHeaders = extendedHeaders; this.contextPath = contextPath; + this.maxContentLength = maxContentLength; } public ExtendedHeaders extendedHeaders() { @@ -36,4 +38,8 @@ public Set getIgnoredCaches() { public String contextPath() { return contextPath; } + + public int maxContentLength() { + return maxContentLength; + } } diff --git a/server/rest/src/main/java/org/infinispan/rest/configuration/RestServerConfigurationBuilder.java b/server/rest/src/main/java/org/infinispan/rest/configuration/RestServerConfigurationBuilder.java index 8e14cb35b5f8..2839a8605979 100644 --- a/server/rest/src/main/java/org/infinispan/rest/configuration/RestServerConfigurationBuilder.java +++ b/server/rest/src/main/java/org/infinispan/rest/configuration/RestServerConfigurationBuilder.java @@ -18,14 +18,16 @@ public class RestServerConfigurationBuilder extends ProtocolServerConfigurationB public static final String DEFAULT_CONTEXT_PATH = "rest"; public static final int DEFAULT_PORT = 8080; - public static final String DEFAILT_NAME = "rest"; + public static final String DEFAULT_NAME = "rest"; + public static final int DEFAULT_MAX_CONTENT_LENGTH = 10 * 1024 * 1024; private ExtendedHeaders extendedHeaders = ExtendedHeaders.ON_DEMAND; private String contextPath = DEFAULT_CONTEXT_PATH; + private int maxContentLength = DEFAULT_MAX_CONTENT_LENGTH; public RestServerConfigurationBuilder() { super(DEFAULT_PORT); - name(DEFAILT_NAME); + name(DEFAULT_NAME); } public RestServerConfigurationBuilder extendedHeaders(ExtendedHeaders extendedHeaders) { @@ -38,6 +40,11 @@ public RestServerConfigurationBuilder contextPath(String contextPath) { return this; } + public RestServerConfigurationBuilder maxContentLength(int maxContentLength) { + this.maxContentLength = maxContentLength; + return this; + } + @Override public void validate() { // Nothing to do @@ -46,7 +53,7 @@ public void validate() { @Override public RestServerConfiguration create() { return new RestServerConfiguration(defaultCacheName, name, extendedHeaders, host, port, ignoredCaches, ssl.create(), - startTransport, contextPath, adminOperationsHandler); + startTransport, contextPath, adminOperationsHandler, maxContentLength); } @Override @@ -54,6 +61,7 @@ public Builder read(RestServerConfiguration template) { this.extendedHeaders = template.extendedHeaders(); this.host = template.host(); this.port = template.port(); + this.maxContentLength = template.maxContentLength(); return this; } diff --git a/server/rest/src/test/java/org/infinispan/rest/RestOperationsTest.java b/server/rest/src/test/java/org/infinispan/rest/RestOperationsTest.java index 1e2ba3cc035d..b9570cf4f064 100644 --- a/server/rest/src/test/java/org/infinispan/rest/RestOperationsTest.java +++ b/server/rest/src/test/java/org/infinispan/rest/RestOperationsTest.java @@ -7,11 +7,13 @@ import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.nio.ByteBuffer; import java.util.Optional; import org.assertj.core.api.Assertions; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.util.ByteBufferContentProvider; import org.eclipse.jetty.client.util.BytesContentProvider; import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.http.HttpHeader; @@ -839,6 +841,42 @@ public void shouldPutEntryWithTtlAndIdleTime() throws Exception { Assertions.assertThat(metadata.maxIdle()).isEqualTo(50 * 1000); } + @Test + public void shouldPutLargeObject() throws Exception { + //when + ByteBuffer payload = ByteBuffer.allocate(1_000_000); + ContentResponse response = client + .POST(String.format("http://localhost:%d/rest/%s/%s", restServer.getPort(), "default", "test")) + .content(new ByteBufferContentProvider(payload)) + .send(); + + InternalCacheEntry cacheEntry = (InternalCacheEntry) restServer.getCacheManager() + .getCache("default", false) + .getAdvancedCache() + .getCacheEntry("test"); + MimeMetadata metadata = ((MimeMetadata) cacheEntry.getMetadata()); + + //then + ResponseAssertion.assertThat(response).isOk(); + ResponseAssertion.assertThat(response).hasEtag(); + + Assertions.assertThat(cacheEntry.getValue().length).isEqualTo(1_000_000); + Assertions.assertThat(metadata.contentType()).isEqualTo("application/octet-stream"); + } + + @Test + public void shouldFailTooLargeObject() throws Exception { + //when + ByteBuffer payload = ByteBuffer.allocate(1_100_000); + ContentResponse response = client + .POST(String.format("http://localhost:%d/rest/%s/%s", restServer.getPort(), "default", "test")) + .content(new ByteBufferContentProvider(payload)) + .send(); + + //then + ResponseAssertion.assertThat(response).isPayloadTooLarge(); + } + static class TestClass implements Serializable { private String name; diff --git a/server/rest/src/test/java/org/infinispan/rest/assertion/ResponseAssertion.java b/server/rest/src/test/java/org/infinispan/rest/assertion/ResponseAssertion.java index 8c2ae53bc674..044f91f42e20 100644 --- a/server/rest/src/test/java/org/infinispan/rest/assertion/ResponseAssertion.java +++ b/server/rest/src/test/java/org/infinispan/rest/assertion/ResponseAssertion.java @@ -78,6 +78,11 @@ public ResponseAssertion isNotFound() { return this; } + public ResponseAssertion isPayloadTooLarge() { + Assertions.assertThat(response.getStatus()).isEqualTo(413); + return this; + } + public ResponseAssertion isNotModified() { Assertions.assertThat(response.getStatus()).isEqualTo(304); return this; diff --git a/server/rest/src/test/java/org/infinispan/rest/helper/RestServerHelper.java b/server/rest/src/test/java/org/infinispan/rest/helper/RestServerHelper.java index ac5fae56bf38..94023df96cc7 100644 --- a/server/rest/src/test/java/org/infinispan/rest/helper/RestServerHelper.java +++ b/server/rest/src/test/java/org/infinispan/rest/helper/RestServerHelper.java @@ -25,7 +25,7 @@ public class RestServerHelper { private RestServerHelper(EmbeddedCacheManager cacheManager) { this.cacheManager = cacheManager; - restServerConfigurationBuilder.host("localhost").port(0); + restServerConfigurationBuilder.host("localhost").port(0).maxContentLength(1_000_000); } public static RestServerHelper defaultRestServer(String... cachesDefined) {