001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.test.web.client; 018 019import java.io.IOException; 020import java.net.URI; 021import java.nio.charset.StandardCharsets; 022import java.util.List; 023 024import org.springframework.http.HttpHeaders; 025import org.springframework.http.HttpMethod; 026import org.springframework.http.HttpStatus; 027import org.springframework.http.client.ClientHttpRequest; 028import org.springframework.http.client.ClientHttpRequestFactory; 029import org.springframework.http.client.ClientHttpResponse; 030import org.springframework.mock.http.client.MockClientHttpRequest; 031import org.springframework.mock.http.client.MockClientHttpResponse; 032import org.springframework.mock.web.MockHttpServletResponse; 033import org.springframework.test.web.servlet.MockMvc; 034import org.springframework.util.Assert; 035 036import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request; 037 038 039/** 040 * A {@link ClientHttpRequestFactory} for requests executed via {@link MockMvc}. 041 * 042 * <p>As of 5.0 this class also implements 043 * {@link org.springframework.http.client.AsyncClientHttpRequestFactory 044 * AsyncClientHttpRequestFactory}. However note that 045 * {@link org.springframework.web.client.AsyncRestTemplate} and related classes 046 * have been deprecated at the same time. 047 * 048 * @author Rossen Stoyanchev 049 * @since 3.2 050 */ 051@SuppressWarnings("deprecation") 052public class MockMvcClientHttpRequestFactory 053 implements ClientHttpRequestFactory, org.springframework.http.client.AsyncClientHttpRequestFactory { 054 055 private final MockMvc mockMvc; 056 057 058 public MockMvcClientHttpRequestFactory(MockMvc mockMvc) { 059 Assert.notNull(mockMvc, "MockMvc must not be null"); 060 this.mockMvc = mockMvc; 061 } 062 063 064 @Override 065 public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) { 066 return new MockClientHttpRequest(httpMethod, uri) { 067 @Override 068 public ClientHttpResponse executeInternal() throws IOException { 069 return getClientHttpResponse(httpMethod, uri, getHeaders(), getBodyAsBytes()); 070 } 071 }; 072 } 073 074 @Override 075 public org.springframework.http.client.AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod method) { 076 return new org.springframework.mock.http.client.MockAsyncClientHttpRequest(method, uri) { 077 @Override 078 protected ClientHttpResponse executeInternal() throws IOException { 079 return getClientHttpResponse(method, uri, getHeaders(), getBodyAsBytes()); 080 } 081 }; 082 } 083 084 private ClientHttpResponse getClientHttpResponse( 085 HttpMethod httpMethod, URI uri, HttpHeaders requestHeaders, byte[] requestBody) { 086 087 try { 088 MockHttpServletResponse servletResponse = this.mockMvc 089 .perform(request(httpMethod, uri).content(requestBody).headers(requestHeaders)) 090 .andReturn() 091 .getResponse(); 092 093 HttpStatus status = HttpStatus.valueOf(servletResponse.getStatus()); 094 byte[] body = servletResponse.getContentAsByteArray(); 095 MockClientHttpResponse clientResponse = new MockClientHttpResponse(body, status); 096 clientResponse.getHeaders().putAll(getResponseHeaders(servletResponse)); 097 return clientResponse; 098 } 099 catch (Exception ex) { 100 byte[] body = ex.toString().getBytes(StandardCharsets.UTF_8); 101 return new MockClientHttpResponse(body, HttpStatus.INTERNAL_SERVER_ERROR); 102 } 103 } 104 105 private HttpHeaders getResponseHeaders(MockHttpServletResponse response) { 106 HttpHeaders headers = new HttpHeaders(); 107 for (String name : response.getHeaderNames()) { 108 List<String> values = response.getHeaders(name); 109 for (String value : values) { 110 headers.add(name, value); 111 } 112 } 113 return headers; 114 } 115 116}