/* * Copyright 2013-2017 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. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.integration.http; import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.isNull; import java.net.URI; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; import java.util.TimeZone; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.PropertyAccessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.PollableChannel; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; /** * @author Artem Bilan * @author Gary Russell * @since 3.0 */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @DirtiesContext public class HttpProxyScenarioTests { private final HandlerAdapter handlerAdapter = new HttpRequestHandlerAdapter(); @Autowired private HandlerMapping handlerMapping; @Autowired @Qualifier("proxyGateway.handler") private HttpRequestExecutingMessageHandler handler; @Autowired @Qualifier("proxyGatewaymp.handler") private HttpRequestExecutingMessageHandler handlermp; @Autowired private PollableChannel checkHeadersChannel; @Test public void testHttpProxyScenario() throws Exception { DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); Calendar c = Calendar.getInstance(); c.set(Calendar.MILLISECOND, 0); final long ifModifiedSince = c.getTimeInMillis(); String ifModifiedSinceValue = dateFormat.format(ifModifiedSince); c.add(Calendar.DATE, -1); long ifUnmodifiedSince = c.getTimeInMillis(); final String ifUnmodifiedSinceValue = dateFormat.format(ifUnmodifiedSince); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test"); request.setQueryString("foo=bar&FOO=BAR"); request.addHeader("If-Modified-Since", ifModifiedSinceValue); request.addHeader("If-Unmodified-Since", ifUnmodifiedSinceValue); request.addHeader("Connection", "Keep-Alive"); request.setContentType("text/plain"); Object handler = this.handlerMapping.getHandler(request).getHandler(); assertNotNull(handler); MockHttpServletResponse response = new MockHttpServletResponse(); RestTemplate template = Mockito.spy(new RestTemplate()); final String contentDispositionValue = "attachment; filename=\"test.txt\""; Mockito.doAnswer(invocation -> { URI uri = invocation.getArgument(0); assertEquals(new URI("http://testServer/test?foo=bar&FOO=BAR"), uri); HttpEntity<?> httpEntity = (HttpEntity<?>) invocation.getArguments()[2]; HttpHeaders httpHeaders = httpEntity.getHeaders(); assertEquals(ifModifiedSince, httpHeaders.getIfModifiedSince()); assertEquals(ifUnmodifiedSinceValue, httpHeaders.getFirst("If-Unmodified-Since")); assertEquals("Keep-Alive", httpHeaders.getFirst("Connection")); MultiValueMap<String, String> responseHeaders = new LinkedMultiValueMap<String, String>(httpHeaders); responseHeaders.set("Connection", "close"); responseHeaders.set("Content-Disposition", contentDispositionValue); return new ResponseEntity<>(responseHeaders, HttpStatus.OK); }).when(template).exchange(Mockito.any(URI.class), Mockito.any(HttpMethod.class), Mockito.any(HttpEntity.class), (Class<?>) isNull()); PropertyAccessor dfa = new DirectFieldAccessor(this.handler); dfa.setPropertyValue("restTemplate", template); RequestAttributes attributes = new ServletRequestAttributes(request); RequestContextHolder.setRequestAttributes(attributes); this.handlerAdapter.handle(request, response, handler); assertNull(response.getHeaderValue("If-Modified-Since")); assertNull(response.getHeaderValue("If-Unmodified-Since")); assertEquals("close", response.getHeaderValue("Connection")); assertEquals(contentDispositionValue, response.getHeader("Content-Disposition")); assertEquals("text/plain", response.getContentType()); Message<?> message = this.checkHeadersChannel.receive(2000); MessageHeaders headers = message.getHeaders(); assertEquals(ifModifiedSince, headers.get("If-Modified-Since")); assertEquals(ifUnmodifiedSince, headers.get("If-Unmodified-Since")); RequestContextHolder.resetRequestAttributes(); } @Test public void testHttpMultipartProxyScenario() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("POST", "/testmp"); request.addHeader("Connection", "Keep-Alive"); request.setContentType("multipart/form-data;boundary=----WebKitFormBoundarywABD2xqC1FLBijlQ"); request.setContent("foo".getBytes()); Object handler = this.handlerMapping.getHandler(request).getHandler(); assertNotNull(handler); MockHttpServletResponse response = new MockHttpServletResponse(); RestTemplate template = Mockito.spy(new RestTemplate()); Mockito.doAnswer(invocation -> { URI uri = invocation.getArgument(0); assertEquals(new URI("http://testServer/testmp"), uri); HttpEntity<?> httpEntity = (HttpEntity<?>) invocation.getArguments()[2]; HttpHeaders httpHeaders = httpEntity.getHeaders(); assertEquals("Keep-Alive", httpHeaders.getFirst("Connection")); assertEquals("multipart/form-data;boundary=----WebKitFormBoundarywABD2xqC1FLBijlQ", httpHeaders.getContentType().toString()); HttpEntity<?> entity = (HttpEntity<?>) invocation.getArguments()[2]; assertThat(entity.getBody(), instanceOf(byte[].class)); assertEquals("foo", new String((byte[]) entity.getBody())); MultiValueMap<String, String> responseHeaders = new LinkedMultiValueMap<String, String>(httpHeaders); responseHeaders.set("Connection", "close"); responseHeaders.set("Content-Type", "text/plain"); return new ResponseEntity<Object>(responseHeaders, HttpStatus.OK); }).when(template).exchange(Mockito.any(URI.class), Mockito.any(HttpMethod.class), Mockito.any(HttpEntity.class), (Class<?>) isNull()); PropertyAccessor dfa = new DirectFieldAccessor(this.handlermp); dfa.setPropertyValue("restTemplate", template); RequestAttributes attributes = new ServletRequestAttributes(request); RequestContextHolder.setRequestAttributes(attributes); this.handlerAdapter.handle(request, response, handler); assertEquals("close", response.getHeaderValue("Connection")); assertEquals("text/plain", response.getContentType()); RequestContextHolder.resetRequestAttributes(); } }