io.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2019 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 io.restassured.module.mockmvc.internal;
import io.restassured.RestAssured;
import io.restassured.authentication.NoAuthScheme;
import io.restassured.builder.MultiPartSpecBuilder;
import io.restassured.filter.Filter;
import io.restassured.filter.log.RequestLoggingFilter;
import io.restassured.filter.time.TimingFilter;
import io.restassured.http.Cookie;
import io.restassured.http.Cookies;
import io.restassured.http.Header;
import io.restassured.http.Headers;
import io.restassured.http.Method;
import io.restassured.internal.RequestSpecificationImpl;
import io.restassured.internal.ResponseParserRegistrar;
import io.restassured.internal.ResponseSpecificationImpl;
import io.restassured.internal.filter.FilterContextImpl;
import io.restassured.internal.log.LogRepository;
import io.restassured.internal.support.PathSupport;
import io.restassured.internal.util.SafeExceptionRethrower;
import io.restassured.module.mockmvc.config.RestAssuredMockMvcConfig;
import io.restassured.module.mockmvc.intercept.MockHttpServletRequestBuilderInterceptor;
import io.restassured.module.mockmvc.response.MockMvcResponse;
import io.restassured.module.mockmvc.specification.MockMvcRequestAsyncConfigurer;
import io.restassured.module.mockmvc.specification.MockMvcRequestAsyncSender;
import io.restassured.module.mockmvc.specification.MockMvcRequestSender;
import io.restassured.module.spring.commons.BodyHelper;
import io.restassured.module.spring.commons.HeaderHelper;
import io.restassured.module.spring.commons.ParamApplier;
import io.restassured.module.spring.commons.config.AsyncConfig;
import io.restassured.module.spring.commons.config.ConfigConverter;
import io.restassured.specification.ResponseSpecification;
import org.apache.commons.codec.Charsets;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultHandler;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.security.Principal;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static io.restassured.internal.common.assertion.AssertParameter.notNull;
import static io.restassured.internal.common.classpath.ClassPathResolver.existInCP;
import static io.restassured.internal.support.PathSupport.mergeAndRemoveDoubleSlash;
import static io.restassured.module.mockmvc.internal.SpringSecurityClassPathChecker.isSpringSecurityInClasspath;
import static io.restassured.module.mockmvc.util.ReflectionUtil.invokeConstructor;
import static io.restassured.module.mockmvc.util.ReflectionUtil.invokeMethod;
import static io.restassured.module.spring.commons.HeaderHelper.mapToArray;
import static io.restassured.module.spring.commons.RequestLogger.logParamsAndHeaders;
import static io.restassured.module.spring.commons.RequestLogger.logRequestBody;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trimToNull;
import static org.springframework.http.HttpMethod.DELETE;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.HEAD;
import static org.springframework.http.HttpMethod.OPTIONS;
import static org.springframework.http.HttpMethod.PATCH;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpMethod.PUT;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch;
class MockMvcRequestSenderImpl implements MockMvcRequestSender, MockMvcRequestAsyncConfigurer, MockMvcRequestAsyncSender {
private static final String ATTRIBUTE_NAME_URL_TEMPLATE = "org.springframework.restdocs.urlTemplate";
private static final String CONTENT_TYPE = "Content-Type";
private static final boolean isSpring6OrLater = existInCP("org.springframework.aot.AotDetector");
private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
private final MockMvc mockMvc;
private final Map params;
private final Map namedPathParams;
private final Map queryParams;
private final Map formParams;
private final Map attributes;
private final RestAssuredMockMvcConfig config;
private final Object requestBody;
private Headers headers;
private final Cookies cookies;
private final List multiParts;
private final RequestLoggingFilter requestLoggingFilter;
private final List resultHandlers;
private final List requestPostProcessors;
private final MockHttpServletRequestBuilderInterceptor interceptor;
private final String basePath;
private final ResponseSpecification responseSpecification;
private final Object authentication;
private final LogRepository logRepository;
private final boolean isAsyncRequest;
private final Map sessionAttributes;
MockMvcRequestSenderImpl(MockMvc mockMvc, Map params, Map namedPathParams, Map queryParams, Map formParams, Map attributes,
RestAssuredMockMvcConfig config, Object requestBody, Headers headers, Cookies cookies, Map sessionAttributes,
List multiParts, RequestLoggingFilter requestLoggingFilter, List resultHandlers,
List requestPostProcessors, MockHttpServletRequestBuilderInterceptor interceptor, String basePath, ResponseSpecification responseSpecification,
Object authentication, LogRepository logRepository) {
this(mockMvc, params, namedPathParams, queryParams, formParams, attributes, config, requestBody, headers, cookies, sessionAttributes, multiParts, requestLoggingFilter, resultHandlers, requestPostProcessors, interceptor,
basePath, responseSpecification, authentication, logRepository, false);
}
private MockMvcRequestSenderImpl(MockMvc mockMvc, Map params, Map namedPathParams, Map queryParams, Map formParams, Map attributes,
RestAssuredMockMvcConfig config, Object requestBody, Headers headers, Cookies cookies, Map sessionAttributes,
List multiParts, RequestLoggingFilter requestLoggingFilter, List resultHandlers,
List requestPostProcessors, MockHttpServletRequestBuilderInterceptor interceptor, String basePath, ResponseSpecification responseSpecification,
Object authentication, LogRepository logRepository, boolean isAsyncRequest) {
this.mockMvc = mockMvc;
this.params = params;
this.namedPathParams = namedPathParams;
this.queryParams = queryParams;
this.formParams = formParams;
this.attributes = attributes;
this.config = config;
this.requestBody = requestBody;
this.headers = headers;
this.cookies = cookies;
this.sessionAttributes = sessionAttributes;
this.multiParts = multiParts;
this.requestLoggingFilter = requestLoggingFilter;
this.resultHandlers = resultHandlers;
this.requestPostProcessors = requestPostProcessors;
this.interceptor = interceptor;
this.basePath = basePath;
this.responseSpecification = responseSpecification;
this.authentication = authentication;
this.logRepository = logRepository;
this.isAsyncRequest = isAsyncRequest;
}
private Object assembleHeaders(MockHttpServletResponse response) {
Collection headerNames = response.getHeaderNames();
List headers = new ArrayList<>();
for (String headerName : headerNames) {
List headerValues = response.getHeaders(headerName);
for (String headerValue : headerValues) {
headers.add(new Header(headerName, headerValue));
}
}
return new Headers(headers);
}
private Cookies convertCookies(Object[] servletCookies) {
List cookies = new ArrayList<>();
for (Object servletCookie : servletCookies) {
Cookie.Builder cookieBuilder = new Cookie.Builder(
invokeMethod(servletCookie, "getName"),
invokeMethod(servletCookie, "getValue")
);
String comment = invokeMethod(servletCookie, "getComment");
if (comment != null) {
cookieBuilder.setComment(comment);
}
String domain = invokeMethod(servletCookie, "getDomain");
if (domain != null) {
cookieBuilder.setDomain(domain);
}
String path = invokeMethod(servletCookie, "getPath");
if (path != null) {
cookieBuilder.setPath(path);
}
int getMaxAge = invokeMethod(servletCookie, "getMaxAge");
cookieBuilder.setMaxAge(getMaxAge);
cookieBuilder.setVersion(invokeMethod(servletCookie, "getVersion"));
cookieBuilder.setSecured(invokeMethod(servletCookie, "getSecure"));
cookieBuilder.setHttpOnly(invokeMethod(servletCookie, "isHttpOnly"));
// Attempt to copy properties from org.springframework.mock.web.MockCookie
try {
String sameSite = invokeMethod(servletCookie, "getSameSite");
if(sameSite != null) {
cookieBuilder.setSameSite(sameSite);
}
} catch(IllegalArgumentException e) {
// Do nothing as only found on MockCookie
}
try {
ZonedDateTime expires = invokeMethod(servletCookie, "getExpires");
if(expires != null) {
cookieBuilder.setExpiryDate(Date.from(expires.toInstant()));
}
} catch(IllegalArgumentException e) {
// Do nothing as only found on MockCookie
}
cookies.add(cookieBuilder.build());
}
return new Cookies(cookies);
}
@SuppressWarnings("unchecked")
private MockMvcResponse performRequest(MockHttpServletRequestBuilder requestBuilder) {
MockHttpServletResponse response;
if (interceptor != null) {
interceptor.intercept(requestBuilder);
}
if (isSpringSecurityInClasspath() && authentication instanceof org.springframework.security.core.Authentication) {
org.springframework.security.core.context.SecurityContextHolder.getContext().setAuthentication((org.springframework.security.core.Authentication) authentication);
}
if (authentication instanceof Principal) {
requestBuilder.principal((Principal) authentication);
}
for (RequestPostProcessor requestPostProcessor : requestPostProcessors) {
requestBuilder.with(requestPostProcessor);
}
MockMvcRestAssuredResponseImpl restAssuredResponse;
try {
final long start = System.currentTimeMillis();
ResultActions perform = mockMvc.perform(requestBuilder);
final long responseTime = System.currentTimeMillis() - start;
if (!resultHandlers.isEmpty()) {
for (ResultHandler resultHandler : resultHandlers) {
perform.andDo(resultHandler);
}
}
MvcResult mvcResult = getMvcResult(perform, isAsyncRequest);
response = mvcResult.getResponse();
restAssuredResponse = new MockMvcRestAssuredResponseImpl(perform, logRepository);
restAssuredResponse.setConfig(ConfigConverter.convertToRestAssuredConfig(config));
restAssuredResponse.setDecoderConfig(config.getDecoderConfig());
restAssuredResponse.setContent(response.getContentAsByteArray());
restAssuredResponse.setContentType(response.getContentType());
restAssuredResponse.setHasExpectations(false);
restAssuredResponse.setStatusCode(response.getStatus());
restAssuredResponse.setResponseHeaders(assembleHeaders(response));
restAssuredResponse.setRpr(getRpr());
restAssuredResponse.setStatusLine(assembleStatusLine(response, mvcResult.getResolvedException()));
restAssuredResponse.setFilterContextProperties(new HashMap() {{
put(TimingFilter.RESPONSE_TIME_MILLISECONDS, responseTime);
}});
restAssuredResponse.setCookies(convertCookies(invokeMethod(response, "getCookies")));
if (responseSpecification != null) {
responseSpecification.validate(ResponseConverter.toStandardResponse(restAssuredResponse));
}
} catch (Exception e) {
return SafeExceptionRethrower.safeRethrow(e);
} finally {
if (isSpringSecurityInClasspath()) {
org.springframework.security.core.context.SecurityContextHolder.clearContext();
}
}
return restAssuredResponse;
}
private MvcResult getMvcResult(ResultActions perform, boolean isAsyncRequest) throws Exception {
MvcResult mvcResult;
if (isAsyncRequest) {
MvcResult startedAsyncRequestProcessing = perform.andExpect(MockMvcResultMatchers.request().asyncStarted()).andReturn();
startedAsyncRequestProcessing.getAsyncResult(config.getAsyncConfig().timeoutInMs());
mvcResult = mockMvc.perform(asyncDispatch(startedAsyncRequestProcessing)).andReturn();
} else {
mvcResult = perform.andReturn();
}
return mvcResult;
}
private ResponseParserRegistrar getRpr() {
if (responseSpecification instanceof ResponseSpecificationImpl) {
return ((ResponseSpecificationImpl) responseSpecification).getRpr();
}
return new ResponseParserRegistrar();
}
private String assembleStatusLine(MockHttpServletResponse response, Exception resolvedException) {
StringBuilder builder = new StringBuilder();
builder.append(response.getStatus());
if (isNotBlank(response.getErrorMessage())) {
builder.append(" ").append(response.getErrorMessage());
} else if (resolvedException != null) {
builder.append(" ").append(resolvedException.getMessage());
}
return builder.toString();
}
private MockMvcResponse sendRequest(HttpMethod method, String path, Object[] unnamedPathParams) {
notNull(path, "Path");
verifyNoBodyAndMultipartTogether();
final String baseUri = buildBaseUri(path);
final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri);
applyQueryParams(uriComponentsBuilder);
applyPathParams(uriComponentsBuilder, baseUri, unnamedPathParams);
final String uri = uriComponentsBuilder.build().toUriString();
final MockHttpServletRequestBuilder request = applyMultiPartsAndGetRequest(method, uri, unnamedPathParams);
String requestContentType = HeaderHelper.findContentType(headers, (List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy