All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl Maven / Gradle / Ivy


package com.jayway.restassured.module.mockmvc.internal;

import com.jayway.restassured.authentication.NoAuthScheme;
import com.jayway.restassured.builder.MultiPartSpecBuilder;
import com.jayway.restassured.filter.Filter;
import com.jayway.restassured.filter.log.RequestLoggingFilter;
import com.jayway.restassured.internal.RequestSpecificationImpl;
import com.jayway.restassured.internal.ResponseParserRegistrar;
import com.jayway.restassured.internal.ResponseSpecificationImpl;
import com.jayway.restassured.internal.filter.FilterContextImpl;
import com.jayway.restassured.internal.http.Method;
import com.jayway.restassured.internal.util.SafeExceptionRethrower;
import com.jayway.restassured.module.mockmvc.config.RestAssuredMockMvcConfig;
import com.jayway.restassured.module.mockmvc.intercept.MockHttpServletRequestBuilderInterceptor;
import com.jayway.restassured.module.mockmvc.response.MockMvcResponse;
import com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSender;
import com.jayway.restassured.response.Cookie;
import com.jayway.restassured.response.Cookies;
import com.jayway.restassured.response.Header;
import com.jayway.restassured.response.Headers;
import com.jayway.restassured.specification.ResponseSpecification;
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 java.io.*;
import java.net.URI;
import java.net.URL;
import java.util.*;

import static com.jayway.restassured.internal.support.PathSupport.mergeAndRemoveDoubleSlash;
import static com.jayway.restassured.module.mockmvc.internal.ConfigConverter.convertToRestAssuredConfig;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.springframework.http.HttpMethod.*;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED;

class MockMvcRequestSenderImpl implements MockMvcRequestSender {
    private final MockMvc mockMvc;
    private final Map params;
    private final Map queryParams;
    private final Map formParams;
    private final RestAssuredMockMvcConfig config;
    private final Object requestBody;
    private final String requestContentType;
    private final Headers headers;
    private final Cookies cookies;
    private final List multiParts;
    private final RequestLoggingFilter requestLoggingFilter;
    private final List resultHandlers;
    private final MockHttpServletRequestBuilderInterceptor interceptor;
    private final String basePath;
    private final ResponseSpecification responseSpecification;

    MockMvcRequestSenderImpl(MockMvc mockMvc, Map params, Map queryParams, Map formParams,
                             RestAssuredMockMvcConfig config, Object requestBody, String requestContentType, Headers headers, Cookies cookies,
                             List multiParts, RequestLoggingFilter requestLoggingFilter, List resultHandlers,
                             MockHttpServletRequestBuilderInterceptor interceptor, String basePath, ResponseSpecification responseSpecification) {
        this.mockMvc = mockMvc;
        this.params = params;
        this.queryParams = queryParams;
        this.formParams = formParams;
        this.config = config;
        this.requestBody = requestBody;
        this.requestContentType = requestContentType;
        this.headers = headers;
        this.cookies = cookies;
        this.multiParts = multiParts;
        this.requestLoggingFilter = requestLoggingFilter;
        this.resultHandlers = resultHandlers;
        this.interceptor = interceptor;
        this.basePath = basePath;
        this.responseSpecification = responseSpecification;
    }

    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 MockMvcResponse performRequest(MockHttpServletRequestBuilder requestBuilder) { MockHttpServletResponse response; if (mockMvc == null) { throw new IllegalStateException("You haven't configured a MockMVC instance. You can do this statically\n\nRestAssured.mockMvc = ..\nRestAssured.standaloneSetup(..);\nRestAssured.webAppContextSetup(..);\n\nor using the DSL:\n\ngiven().\n\t\tmockMvc(..). ..\n"); } if (interceptor != null) { interceptor.intercept(requestBuilder); } MockMvcRestAssuredResponseImpl restAssuredResponse; try { ResultActions perform = mockMvc.perform(requestBuilder); if (!resultHandlers.isEmpty()) { for (ResultHandler resultHandler : resultHandlers) { perform.andDo(resultHandler); } } MvcResult mvcResult = perform.andReturn(); response = mvcResult.getResponse(); restAssuredResponse = new MockMvcRestAssuredResponseImpl(perform); restAssuredResponse.setConfig(convertToRestAssuredConfig(config)); restAssuredResponse.setContent(response.getContentAsString()); restAssuredResponse.setContentType(response.getContentType()); restAssuredResponse.setHasExpectations(false); restAssuredResponse.setStatusCode(response.getStatus()); restAssuredResponse.setResponseHeaders(assembleHeaders(response)); restAssuredResponse.setRpr(getRpr()); restAssuredResponse.setStatusLine(assembleStatusLine(response, mvcResult.getResolvedException())); if (responseSpecification != null) { responseSpecification.validate(ResponseConverter.toStandardResponse(restAssuredResponse)); } } catch (Exception e) { return SafeExceptionRethrower.safeRethrow(e); } return restAssuredResponse; } private ResponseParserRegistrar getRpr() { if (responseSpecification != null && 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 Object[] mapToArray(Map map) { if (map == null) { return new Object[0]; } return map.values().toArray(new Object[map.values().size()]); } private MockMvcResponse sendRequest(HttpMethod method, String path, Object[] pathParams) { if (requestBody != null && !multiParts.isEmpty()) { throw new IllegalStateException("You cannot specify a request body and a multi-part body in the same request. Perhaps you want to change the body to a multi part?"); } if (isNotBlank(basePath)) { path = mergeAndRemoveDoubleSlash(basePath, path); } final MockHttpServletRequestBuilder request; if (multiParts.isEmpty()) { request = MockMvcRequestBuilders.request(method, path, pathParams); } else if (method != POST) { throw new IllegalArgumentException("Currently multi-part file data uploading only works for " + POST); } else { request = MockMvcRequestBuilders.fileUpload(path, pathParams); } if (!params.isEmpty()) { new ParamApplier(params) { @Override protected void applyParam(String paramName, String[] paramValues) { request.param(paramName, paramValues); } }.applyParams(); if (method == POST && !isInMultiPartMode(request)) { request.contentType(APPLICATION_FORM_URLENCODED); } } if (!queryParams.isEmpty()) { new ParamApplier(queryParams) { @Override protected void applyParam(String paramName, String[] paramValues) { // Spring MVC cannot distinguish query from params afaik. request.param(paramName, paramValues); } }.applyParams(); } if (!formParams.isEmpty()) { if (method == GET) { throw new IllegalArgumentException("Cannot use form parameters in a GET request"); } new ParamApplier(formParams) { @Override protected void applyParam(String paramName, String[] paramValues) { request.param(paramName, paramValues); } }.applyParams(); boolean isInMultiPartMode = isInMultiPartMode(request); if (!isInMultiPartMode) { request.contentType(APPLICATION_FORM_URLENCODED); } } if (StringUtils.isNotBlank(requestContentType)) { request.contentType(MediaType.parseMediaType(requestContentType)); } if (headers.exist()) { for (Header header : headers) { request.header(header.getName(), header.getValue()); } } if (cookies.exist()) { for (Cookie cookie : cookies) { javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); if (cookie.hasComment()) { servletCookie.setComment(cookie.getComment()); } if (cookie.hasDomain()) { servletCookie.setDomain(cookie.getDomain()); } if (cookie.hasMaxAge()) { servletCookie.setMaxAge(cookie.getMaxAge()); } if (cookie.hasPath()) { servletCookie.setPath(cookie.getPath()); } if (cookie.hasVersion()) { servletCookie.setVersion(cookie.getVersion()); } request.cookie(servletCookie); } } if (!multiParts.isEmpty()) { MockMultipartHttpServletRequestBuilder multiPartRequest = (MockMultipartHttpServletRequestBuilder) request; for (MockMvcMultiPart multiPart : multiParts) { MockMultipartFile multipartFile; String fileName = multiPart.getFileName(); String controlName = multiPart.getControlName(); String mimeType = multiPart.getMimeType(); if (multiPart.isByteArray()) { multipartFile = new MockMultipartFile(controlName, fileName, mimeType, (byte[]) multiPart.getContent()); } else if (multiPart.isFile() || multiPart.isInputStream()) { InputStream inputStream; if (multiPart.isFile()) { try { inputStream = new FileInputStream((File) multiPart.getContent()); } catch (FileNotFoundException e) { return SafeExceptionRethrower.safeRethrow(e); } } else { inputStream = (InputStream) multiPart.getContent(); } try { multipartFile = new MockMultipartFile(controlName, fileName, mimeType, inputStream); } catch (IOException e) { return SafeExceptionRethrower.safeRethrow(e); } } else { // String multipartFile = new MockMultipartFile(controlName, fileName, mimeType, ((String) multiPart.getContent()).getBytes()); } multiPartRequest.file(multipartFile); } } if (requestBody != null) { if (requestBody instanceof byte[]) { request.content((byte[]) requestBody); } else { request.content(requestBody.toString()); } } logRequestIfApplicable(method, path, pathParams); return performRequest(request); } private boolean isInMultiPartMode(MockHttpServletRequestBuilder request) { return request instanceof MockMultipartHttpServletRequestBuilder; } private void logRequestIfApplicable(HttpMethod method, String path, Object[] pathParams) { if (requestLoggingFilter == null) { return; } final RequestSpecificationImpl reqSpec = new RequestSpecificationImpl("", 8080, path, new NoAuthScheme(), Collections.emptyList(), requestContentType, null, true, convertToRestAssuredConfig(config)); if (params != null) { new ParamLogger(params) { protected void logParam(String paramName, Object paramValue) { reqSpec.param(paramName, paramValue); } }.logParams(); } if (queryParams != null) { new ParamLogger(queryParams) { protected void logParam(String paramName, Object paramValue) { reqSpec.queryParam(paramName, paramValue); } }.logParams(); } if (formParams != null) { new ParamLogger(formParams) { protected void logParam(String paramName, Object paramValue) { reqSpec.formParam(paramName, paramValue); } }.logParams(); } if (headers != null) { for (Header header : headers) { reqSpec.header(header); } } if (cookies != null) { for (Cookie cookie : cookies) { reqSpec.cookie(cookie); } } if (requestBody != null) { if (requestBody instanceof byte[]) { reqSpec.body((byte[]) requestBody); } else { reqSpec.body(requestBody); } } if (multiParts != null) { for (MockMvcMultiPart multiPart : multiParts) { reqSpec.multiPart(new MultiPartSpecBuilder(multiPart.getContent()). controlName(multiPart.getControlName()). fileName(multiPart.getFileName()). mimeType(multiPart.getMimeType()). build()); } } requestLoggingFilter.filter(reqSpec, null, new FilterContextImpl(path, path, Method.valueOf(method.toString()), null, Collections.emptyList())); } public MockMvcResponse get(String path, Object... pathParams) { return sendRequest(GET, path, pathParams); } public MockMvcResponse get(String path, Map pathParams) { return get(path, mapToArray(pathParams)); } public MockMvcResponse post(String path, Object... pathParams) { return sendRequest(POST, path, pathParams); } public MockMvcResponse post(String path, Map pathParams) { return post(path, mapToArray(pathParams)); } public MockMvcResponse put(String path, Object... pathParams) { return sendRequest(PUT, path, pathParams); } public MockMvcResponse put(String path, Map pathParams) { return put(path, mapToArray(pathParams)); } public MockMvcResponse delete(String path, Object... pathParams) { return sendRequest(DELETE, path, pathParams); } public MockMvcResponse delete(String path, Map pathParams) { return delete(path, mapToArray(pathParams)); } public MockMvcResponse head(String path, Object... pathParams) { return sendRequest(HEAD, path, pathParams); } public MockMvcResponse head(String path, Map pathParams) { return head(path, mapToArray(pathParams)); } public MockMvcResponse patch(String path, Object... pathParams) { return sendRequest(PATCH, path, pathParams); } public MockMvcResponse patch(String path, Map pathParams) { return patch(path, mapToArray(pathParams)); } public MockMvcResponse options(String path, Object... pathParams) { return sendRequest(OPTIONS, path, pathParams); } public MockMvcResponse options(String path, Map pathParams) { return options(path, mapToArray(pathParams)); } public MockMvcResponse get(URI uri) { return get(uri.toString()); } public MockMvcResponse post(URI uri) { return post(uri.toString()); } public MockMvcResponse put(URI uri) { return put(uri.toString()); } public MockMvcResponse delete(URI uri) { return delete(uri.toString()); } public MockMvcResponse head(URI uri) { return head(uri.toString()); } public MockMvcResponse patch(URI uri) { return patch(uri.toString()); } public MockMvcResponse options(URI uri) { return options(uri.toString()); } public MockMvcResponse get(URL url) { return get(url.toString()); } public MockMvcResponse post(URL url) { return post(url.toString()); } public MockMvcResponse put(URL url) { return put(url.toString()); } public MockMvcResponse delete(URL url) { return delete(url.toString()); } public MockMvcResponse head(URL url) { return head(url.toString()); } public MockMvcResponse patch(URL url) { return patch(url.toString()); } public MockMvcResponse options(URL url) { return options(url.toString()); } public MockMvcResponse get() { return get(""); } public MockMvcResponse post() { return post(""); } public MockMvcResponse put() { return put(""); } public MockMvcResponse delete() { return delete(""); } public MockMvcResponse head() { return head(""); } public MockMvcResponse patch() { return patch(""); } public MockMvcResponse options() { return options(""); } private abstract static class ParamApplier { private Map map; protected ParamApplier(Map parameters) { this.map = parameters; } public void applyParams() { for (Map.Entry listEntry : map.entrySet()) { Object value = listEntry.getValue(); String[] stringValues; if (value instanceof Collection) { Collection col = (Collection) value; stringValues = new String[col.size()]; int index = 0; for (Object val : col) { stringValues[index] = val == null ? null : val.toString(); index++; } } else { stringValues = new String[1]; stringValues[0] = value == null ? null : value.toString(); } applyParam(listEntry.getKey(), stringValues); } } protected abstract void applyParam(String paramName, String[] paramValues); } private abstract static class ParamLogger { private Map map; protected ParamLogger(Map parameters) { this.map = parameters; } public void logParams() { for (Map.Entry stringListEntry : map.entrySet()) { Object value = stringListEntry.getValue(); Collection values; if (value instanceof Collection) { values = (Collection) value; } else { values = new ArrayList(); values.add(value); } for (Object theValue : values) { logParam(stringListEntry.getKey(), theValue); } } } protected abstract void logParam(String paramName, Object paramValue); } }