diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java index e897ae5aa80..e25422230ee 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -18,7 +18,6 @@ package org.springframework.test.web.servlet.htmlunit; import java.io.File; import java.io.IOException; -import java.net.URL; import java.net.URLDecoder; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -32,7 +31,6 @@ import java.util.Map; import java.util.Set; import java.util.StringTokenizer; -import com.gargoylesoftware.htmlunit.CookieManager; import com.gargoylesoftware.htmlunit.FormEncodingType; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebRequest; @@ -69,6 +67,7 @@ import org.springframework.web.util.UriComponentsBuilder; * * @author Rob Winch * @author Sam Brannen + * @author Rossen Stoyanchev * @since 4.2 * @see MockMvcWebConnection */ @@ -111,52 +110,58 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { } + /** + * Set the contextPath to be used. + *
The value may be null in which case the first path segment of the + * URL is turned into the contextPath. Otherwise it must conform to + * {@link HttpServletRequest#getContextPath()} which states it can be + * an empty string, or it must start with a "/" and not end with a "/". + * @param contextPath a valid contextPath + * @throws IllegalArgumentException if the contextPath is not a valid + * {@link HttpServletRequest#getContextPath()} + */ + public void setContextPath(@Nullable String contextPath) { + MockMvcWebConnection.validateContextPath(contextPath); + this.contextPath = contextPath; + } + + public void setForwardPostProcessor(RequestPostProcessor forwardPostProcessor) { + this.forwardPostProcessor = forwardPostProcessor; + } + + @Override public MockHttpServletRequest buildRequest(ServletContext servletContext) { - Charset charset = getCharset(); String httpMethod = this.webRequest.getHttpMethod().name(); - UriComponents uriComponents = uriComponents(); - String path = uriComponents.getPath(); + UriComponents uri = UriComponentsBuilder.fromUriString(this.webRequest.getUrl().toExternalForm()).build(); - MockHttpServletRequest request = - new HtmlUnitMockHttpServletRequest(servletContext, httpMethod, (path != null ? path : "")); + MockHttpServletRequest request = new HtmlUnitMockHttpServletRequest( + servletContext, httpMethod, (uri.getPath() != null ? uri.getPath() : "")); parent(request, this.parentBuilder); - String host = uriComponents.getHost(); - request.setServerName(host != null ? host : ""); // needs to be first for additional headers - authType(request); - request.setCharacterEncoding(charset.name()); - content(request, charset); - contextPath(request, uriComponents); - contentType(request); - cookies(request); - headers(request); - locales(request); - servletPath(uriComponents, request); - params(request, uriComponents); - ports(uriComponents, request); + request.setProtocol("HTTP/1.1"); - request.setQueryString(uriComponents.getQuery()); - String scheme = uriComponents.getScheme(); - request.setScheme(scheme != null ? scheme : ""); + request.setScheme(uri.getScheme() != null ? uri.getScheme() : ""); + request.setServerName(uri.getHost() != null ? uri.getHost() : ""); // needs to be first for additional headers + ports(uri, request); + authType(request); + contextPath(request, uri); + servletPath(uri, request); request.setPathInfo(null); - return postProcess(request); - } - - private Charset getCharset() { Charset charset = this.webRequest.getCharset(); - return (charset != null ? charset : StandardCharsets.ISO_8859_1); - } + charset = (charset != null ? charset : StandardCharsets.ISO_8859_1); + request.setCharacterEncoding(charset.name()); + content(request, charset); + contentType(request); - private MockHttpServletRequest postProcess(MockHttpServletRequest request) { - if (this.parentPostProcessor != null) { - request = this.parentPostProcessor.postProcessRequest(request); - } - if (this.forwardPostProcessor != null) { - request = this.forwardPostProcessor.postProcessRequest(request); - } - return request; + cookies(request); + this.webRequest.getAdditionalHeaders().forEach(request::addHeader); + locales(request); + params(request, uri); + request.setQueryString(uri.getQuery()); + + return postProcess(request); } private void parent(MockHttpServletRequest request, @Nullable RequestBuilder parent) { @@ -208,50 +213,30 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { } } - /** - * Set the contextPath to be used. - *
The value may be null in which case the first path segment of the
- * URL is turned into the contextPath. Otherwise it must conform to
- * {@link HttpServletRequest#getContextPath()} which states it can be
- * an empty string, or it must start with a "/" and not end with a "/".
- * @param contextPath a valid contextPath
- * @throws IllegalArgumentException if the contextPath is not a valid
- * {@link HttpServletRequest#getContextPath()}
- */
- public void setContextPath(@Nullable String contextPath) {
- MockMvcWebConnection.validateContextPath(contextPath);
- this.contextPath = contextPath;
- }
-
- public void setForwardPostProcessor(RequestPostProcessor forwardPostProcessor) {
- this.forwardPostProcessor = forwardPostProcessor;
+ private void ports(UriComponents uriComponents, MockHttpServletRequest request) {
+ int serverPort = uriComponents.getPort();
+ request.setServerPort(serverPort);
+ if (serverPort == -1) {
+ int portConnection = this.webRequest.getUrl().getDefaultPort();
+ request.setLocalPort(serverPort);
+ request.setRemotePort(portConnection);
+ }
+ else {
+ request.setRemotePort(serverPort);
+ }
}
private void authType(MockHttpServletRequest request) {
- String authorization = header("Authorization");
+ String authorization = getHeader("Authorization");
String[] authSplit = StringUtils.split(authorization, ": ");
if (authSplit != null) {
request.setAuthType(authSplit[0]);
}
}
- private void content(MockHttpServletRequest request, Charset charset) {
- String requestBody = this.webRequest.getRequestBody();
- if (requestBody == null) {
- return;
- }
- request.setContent(requestBody.getBytes(charset));
- }
-
- private void contentType(MockHttpServletRequest request) {
- String contentType = header("Content-Type");
- if (contentType == null) {
- FormEncodingType encodingType = this.webRequest.getEncodingType();
- if (encodingType != null) {
- contentType = encodingType.getName();
- }
- }
- request.setContentType(contentType != null ? contentType : MediaType.ALL_VALUE);
+ @Nullable
+ private String getHeader(String headerName) {
+ return this.webRequest.getAdditionalHeaders().get(headerName);
}
private void contextPath(MockHttpServletRequest request, UriComponents uriComponents) {
@@ -273,10 +258,36 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
}
}
+ private void servletPath(UriComponents uriComponents, MockHttpServletRequest request) {
+ String path = uriComponents.getPath();
+ String requestPath = (path != null ? path : "");
+ String servletPath = requestPath.substring(request.getContextPath().length());
+ request.setServletPath(servletPath);
+ }
+
+ private void content(MockHttpServletRequest request, Charset charset) {
+ String requestBody = this.webRequest.getRequestBody();
+ if (requestBody == null) {
+ return;
+ }
+ request.setContent(requestBody.getBytes(charset));
+ }
+
+ private void contentType(MockHttpServletRequest request) {
+ String contentType = getHeader("Content-Type");
+ if (contentType == null) {
+ FormEncodingType encodingType = this.webRequest.getEncodingType();
+ if (encodingType != null) {
+ contentType = encodingType.getName();
+ }
+ }
+ request.setContentType(contentType != null ? contentType : MediaType.ALL_VALUE);
+ }
+
private void cookies(MockHttpServletRequest request) {
List