diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/BaseHttpInboundEndpoint.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/BaseHttpInboundEndpoint.java index 3812e8ce18..4a8f88326d 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/BaseHttpInboundEndpoint.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/BaseHttpInboundEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 the original author or authors. + * Copyright 2017-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,7 +62,7 @@ public class BaseHttpInboundEndpoint extends MessagingGatewaySupport implements protected static final boolean ROME_TOOLS_PRESENT = ClassUtils.isPresent("com.rometools.rome.feed.atom.Feed", null); protected static final List NON_READABLE_BODY_HTTP_METHODS = - Arrays.asList(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS); + Arrays.asList(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.DELETE, HttpMethod.OPTIONS, HttpMethod.TRACE); protected final AtomicInteger activeCount = new AtomicInteger(); // NOSONAR diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java index ee3b1167ad..bcd2cd01a0 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -92,7 +92,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun assertThat(message).isNotNull(); assertThat(message.getPayload().getClass()).isEqualTo(LinkedMultiValueMap.class); LinkedMultiValueMap map = (LinkedMultiValueMap) message.getPayload(); - assertThat(map.get("foo").size()).isEqualTo(1); + assertThat(map.get("foo")).hasSize(1); assertThat(map.getFirst("foo")).isEqualTo("bar"); } @@ -193,6 +193,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun protected boolean doSend(Message message, long timeout) { throw new RuntimeException("Planned"); } + }; HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true); gateway.setBeanFactory(mock(BeanFactory.class)); @@ -234,11 +235,8 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun LinkedMultiValueMap map = (LinkedMultiValueMap) message.getPayload(); List fooValues = map.get("foo"); List barValues = map.get("bar"); - assertThat(fooValues.size()).isEqualTo(1); - assertThat(fooValues.get(0)).isEqualTo("123"); - assertThat(barValues.size()).isEqualTo(2); - assertThat(barValues.get(0)).isEqualTo("456"); - assertThat(barValues.get(1)).isEqualTo("789"); + assertThat(fooValues).containsExactly("123"); + assertThat(barValues).containsExactly("456", "789"); } @Test @@ -281,8 +279,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false); gateway.setBeanFactory(mock(BeanFactory.class)); ParameterizedTypeReference> parameterizedTypeReference = - new ParameterizedTypeReference>() { - + new ParameterizedTypeReference<>() { }; gateway.setRequestPayloadType(ResolvableType.forType(parameterizedTypeReference)); gateway.setRequestChannel(channel); @@ -314,14 +311,12 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun assertThat(bean).extracting(TestBean::getName).isEqualTo("T. Bean"); assertThat(bean).extracting(TestBean::getAge).isEqualTo(42); }); - } @Test public void INT2680DuplicateContentTypeHeader() throws Exception { - - final DirectChannel requestChannel = new DirectChannel(); + DirectChannel requestChannel = new DirectChannel(); requestChannel.subscribe(new AbstractReplyProducingMessageHandler() { @Override @@ -478,7 +473,35 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun verify(multipartResolver).isMultipart(any(HttpServletRequest.class)); } - private class ContentTypeCheckingMockHttpServletResponse extends MockHttpServletResponse { + @Test + public void deleteRequestBodyIgnored() throws Exception { + QueueChannel channel = new QueueChannel(); + HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false); + gateway.setBeanFactory(mock(BeanFactory.class)); + gateway.setRequestChannel(channel); + gateway.afterPropertiesSet(); + gateway.start(); + + MockHttpServletRequest request = new MockHttpServletRequest("DELETE", "/delete"); + request.setContent("This content is ignored for DELETE".getBytes()); + request.setParameter("one", "1"); + request.addParameter("two", "2"); + MockHttpServletResponse response = new MockHttpServletResponse(); + gateway.handleRequest(request, response); + Message message = channel.receive(0); + assertThat(message).isNotNull(); + assertThat(message.getPayload()).isNotNull(); + assertThat(message.getPayload().getClass()).isEqualTo(LinkedMultiValueMap.class); + @SuppressWarnings("unchecked") + LinkedMultiValueMap map = (LinkedMultiValueMap) message.getPayload(); + List oneValues = map.get("one"); + List twoValues = map.get("two"); + assertThat(oneValues).containsExactly("1"); + assertThat(twoValues).containsExactly("2"); + } + + + private static class ContentTypeCheckingMockHttpServletResponse extends MockHttpServletResponse { private final List contentTypeList = new ArrayList<>(); diff --git a/src/reference/antora/modules/ROOT/pages/http/inbound.adoc b/src/reference/antora/modules/ROOT/pages/http/inbound.adoc index 29ad436291..3b479f12c2 100644 --- a/src/reference/antora/modules/ROOT/pages/http/inbound.adoc +++ b/src/reference/antora/modules/ROOT/pages/http/inbound.adoc @@ -14,12 +14,12 @@ The easiest way to do this is to use Spring's https://docs.spring.io/spring/docs ---- Notice that the servlet name matches the bean name. -For more information on using the `HttpRequestHandlerServlet`, see https://docs.spring.io/spring/docs/current/spring-framework-reference/html/remoting.html[Remoting and web services using Spring], which is part of the Spring Framework Reference documentation. +For more information see the `HttpRequestHandlerServlet` Javadocs. If you are running within a Spring MVC application, then the aforementioned explicit servlet definition is not necessary. In that case, the bean name for your gateway can be matched against the URL path as you would for a Spring MVC Controller bean. For more information, see -https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc[Web MVC framework], which is part of the Spring Framework Reference documentation. +https://docs.spring.io/spring-framework/reference/web/webmvc.html[Web MVC framework], which is part of the Spring Framework Reference documentation. TIP: For a sample application and the corresponding configuration, see the https://github.com/spring-projects/spring-integration-samples[Spring Integration Samples] repository. It contains the https://github.com/spring-projects/spring-integration-samples/tree/main/basic/http[HTTP sample] application, which demonstrates Spring Integration's HTTP support. @@ -52,7 +52,7 @@ If the request has been wrapped as a `MultipartHttpServletRequest`, when you use NOTE: The HTTP inbound endpoint locates a `MultipartResolver` in the context if one has a bean name of `multipartResolver` (the same name expected by Spring's `DispatcherServlet`). If it does locate that bean, the support for multipart files is enabled on the inbound request mapper. Otherwise, it fails when it tries to map a multipart file request to a Spring Integration `Message`. -For more on Spring's support for `MultipartResolver`, see the https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-multipart[Spring Reference Manual]. +For more on Spring's support for `MultipartResolver`, see the https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-servlet/multipart.html[Spring Reference Manual]. [NOTE] ==== @@ -113,6 +113,6 @@ By default, the key for that map entry is 'reply', but you can override this def == Payload Validation Starting with version 5.2, the HTTP inbound endpoints can be supplied with a `Validator` to check a payload before sending into the channel. -This payload is already a result of conversion and extraction after `payloadExpression` to narrow a validation scope in regards to the valuable data. -The validation failure handling is fully the same what we have in Spring MVC https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-exceptionhandlers[Error Handling]. +This payload is already a result of conversion and extraction after `payloadExpression` to narrow a validation scope in regard to the valuable data. +The validation failure handling is fully the same what we have in Spring MVC https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-servlet/exceptionhandlers.html[Error Handling].