Polishing in HtmlUnitRequestBuilder

Order methods according to Spring Framework conventions.
Order request initialization by URI component.

See gh-27837
This commit is contained in:
rstoyanchev 2022-01-11 14:33:12 +00:00
parent 29fe109440
commit 9346c89f5c
1 changed files with 97 additions and 117 deletions

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -32,7 +31,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import com.gargoylesoftware.htmlunit.CookieManager;
import com.gargoylesoftware.htmlunit.FormEncodingType; import com.gargoylesoftware.htmlunit.FormEncodingType;
import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest; import com.gargoylesoftware.htmlunit.WebRequest;
@ -69,6 +67,7 @@ import org.springframework.web.util.UriComponentsBuilder;
* *
* @author Rob Winch * @author Rob Winch
* @author Sam Brannen * @author Sam Brannen
* @author Rossen Stoyanchev
* @since 4.2 * @since 4.2
* @see MockMvcWebConnection * @see MockMvcWebConnection
*/ */
@ -111,52 +110,58 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
} }
/**
* Set the contextPath to be used.
* <p>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 @Override
public MockHttpServletRequest buildRequest(ServletContext servletContext) { public MockHttpServletRequest buildRequest(ServletContext servletContext) {
Charset charset = getCharset();
String httpMethod = this.webRequest.getHttpMethod().name(); String httpMethod = this.webRequest.getHttpMethod().name();
UriComponents uriComponents = uriComponents(); UriComponents uri = UriComponentsBuilder.fromUriString(this.webRequest.getUrl().toExternalForm()).build();
String path = uriComponents.getPath();
MockHttpServletRequest request = MockHttpServletRequest request = new HtmlUnitMockHttpServletRequest(
new HtmlUnitMockHttpServletRequest(servletContext, httpMethod, (path != null ? path : "")); servletContext, httpMethod, (uri.getPath() != null ? uri.getPath() : ""));
parent(request, this.parentBuilder); 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.setProtocol("HTTP/1.1");
request.setQueryString(uriComponents.getQuery()); request.setScheme(uri.getScheme() != null ? uri.getScheme() : "");
String scheme = uriComponents.getScheme(); request.setServerName(uri.getHost() != null ? uri.getHost() : ""); // needs to be first for additional headers
request.setScheme(scheme != null ? scheme : ""); ports(uri, request);
authType(request);
contextPath(request, uri);
servletPath(uri, request);
request.setPathInfo(null); request.setPathInfo(null);
return postProcess(request);
}
private Charset getCharset() {
Charset charset = this.webRequest.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) { cookies(request);
if (this.parentPostProcessor != null) { this.webRequest.getAdditionalHeaders().forEach(request::addHeader);
request = this.parentPostProcessor.postProcessRequest(request); locales(request);
} params(request, uri);
if (this.forwardPostProcessor != null) { request.setQueryString(uri.getQuery());
request = this.forwardPostProcessor.postProcessRequest(request);
} return postProcess(request);
return request;
} }
private void parent(MockHttpServletRequest request, @Nullable RequestBuilder parent) { private void parent(MockHttpServletRequest request, @Nullable RequestBuilder parent) {
@ -208,50 +213,30 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
} }
} }
/** private void ports(UriComponents uriComponents, MockHttpServletRequest request) {
* Set the contextPath to be used. int serverPort = uriComponents.getPort();
* <p>The value may be null in which case the first path segment of the request.setServerPort(serverPort);
* URL is turned into the contextPath. Otherwise it must conform to if (serverPort == -1) {
* {@link HttpServletRequest#getContextPath()} which states it can be int portConnection = this.webRequest.getUrl().getDefaultPort();
* an empty string, or it must start with a "/" and not end with a "/". request.setLocalPort(serverPort);
* @param contextPath a valid contextPath request.setRemotePort(portConnection);
* @throws IllegalArgumentException if the contextPath is not a valid }
* {@link HttpServletRequest#getContextPath()} else {
*/ request.setRemotePort(serverPort);
public void setContextPath(@Nullable String contextPath) { }
MockMvcWebConnection.validateContextPath(contextPath);
this.contextPath = contextPath;
}
public void setForwardPostProcessor(RequestPostProcessor forwardPostProcessor) {
this.forwardPostProcessor = forwardPostProcessor;
} }
private void authType(MockHttpServletRequest request) { private void authType(MockHttpServletRequest request) {
String authorization = header("Authorization"); String authorization = getHeader("Authorization");
String[] authSplit = StringUtils.split(authorization, ": "); String[] authSplit = StringUtils.split(authorization, ": ");
if (authSplit != null) { if (authSplit != null) {
request.setAuthType(authSplit[0]); request.setAuthType(authSplit[0]);
} }
} }
private void content(MockHttpServletRequest request, Charset charset) { @Nullable
String requestBody = this.webRequest.getRequestBody(); private String getHeader(String headerName) {
if (requestBody == null) { return this.webRequest.getAdditionalHeaders().get(headerName);
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);
} }
private void contextPath(MockHttpServletRequest request, UriComponents uriComponents) { 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) { private void cookies(MockHttpServletRequest request) {
List<Cookie> cookies = new ArrayList<>(); List<Cookie> cookies = new ArrayList<>();
String cookieHeaderValue = header("Cookie"); String cookieHeaderValue = getHeader("Cookie");
if (cookieHeaderValue != null) { if (cookieHeaderValue != null) {
StringTokenizer tokens = new StringTokenizer(cookieHeaderValue, "=;"); StringTokenizer tokens = new StringTokenizer(cookieHeaderValue, "=;");
while (tokens.hasMoreTokens()) { while (tokens.hasMoreTokens()) {
@ -312,15 +323,6 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
} }
} }
@Nullable
private String header(String headerName) {
return this.webRequest.getAdditionalHeaders().get(headerName);
}
private void headers(MockHttpServletRequest request) {
this.webRequest.getAdditionalHeaders().forEach(request::addHeader);
}
private MockHttpSession httpSession(MockHttpServletRequest request, final String sessionid) { private MockHttpSession httpSession(MockHttpServletRequest request, final String sessionid) {
MockHttpSession session; MockHttpSession session;
synchronized (this.sessions) { synchronized (this.sessions) {
@ -341,11 +343,11 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
} }
private void addSessionCookie(MockHttpServletRequest request, String sessionid) { private void addSessionCookie(MockHttpServletRequest request, String sessionid) {
getCookieManager().addCookie(createCookie(request, sessionid)); this.webClient.getCookieManager().addCookie(createCookie(request, sessionid));
} }
private void removeSessionCookie(MockHttpServletRequest request, String sessionid) { private void removeSessionCookie(MockHttpServletRequest request, String sessionid) {
getCookieManager().removeCookie(createCookie(request, sessionid)); this.webClient.getCookieManager().removeCookie(createCookie(request, sessionid));
} }
private com.gargoylesoftware.htmlunit.util.Cookie createCookie(MockHttpServletRequest request, String sessionid) { private com.gargoylesoftware.htmlunit.util.Cookie createCookie(MockHttpServletRequest request, String sessionid) {
@ -354,7 +356,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
} }
private void locales(MockHttpServletRequest request) { private void locales(MockHttpServletRequest request) {
String locale = header("Accept-Language"); String locale = getHeader("Accept-Language");
if (locale == null) { if (locale == null) {
request.addPreferredLocale(Locale.getDefault()); request.addPreferredLocale(Locale.getDefault());
} }
@ -407,36 +409,18 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
} }
} }
private void servletPath(MockHttpServletRequest request, String requestPath) { private MockHttpServletRequest postProcess(MockHttpServletRequest request) {
String servletPath = requestPath.substring(request.getContextPath().length()); if (this.parentPostProcessor != null) {
request.setServletPath(servletPath); request = this.parentPostProcessor.postProcessRequest(request);
}
if (this.forwardPostProcessor != null) {
request = this.forwardPostProcessor.postProcessRequest(request);
}
return request;
} }
private void servletPath(UriComponents uriComponents, MockHttpServletRequest request) {
if ("".equals(request.getPathInfo())) {
request.setPathInfo(null);
}
String path = uriComponents.getPath();
servletPath(request, (path != null ? path : ""));
}
private void ports(UriComponents uriComponents, MockHttpServletRequest request) { /* Mergeable methods */
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 UriComponents uriComponents() {
URL url = this.webRequest.getUrl();
return UriComponentsBuilder.fromUriString(url.toExternalForm()).build();
}
@Override @Override
public boolean isMergeEnabled() { public boolean isMergeEnabled() {
@ -461,10 +445,6 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
return this; return this;
} }
private CookieManager getCookieManager() {
return this.webClient.getCookieManager();
}
/** /**
* An extension to {@link MockHttpServletRequest} that ensures that when a * An extension to {@link MockHttpServletRequest} that ensures that when a