Merge branch '2.1.x'

Closes gh-17994
pull/17998/head
Andy Wilkinson 5 years ago
commit bbec7b0f37

@ -18,8 +18,8 @@ package org.springframework.boot.web.embedded.undertow;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -33,6 +33,7 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
@ -95,6 +96,8 @@ import org.springframework.util.Assert;
public class UndertowServletWebServerFactory extends AbstractServletWebServerFactory public class UndertowServletWebServerFactory extends AbstractServletWebServerFactory
implements ConfigurableUndertowWebServerFactory, ResourceLoaderAware { implements ConfigurableUndertowWebServerFactory, ResourceLoaderAware {
private static final Pattern ENCODED_SLASH = Pattern.compile("%2F", Pattern.LITERAL);
private static final Set<Class<?>> NO_CLASSES = Collections.emptySet(); private static final Set<Class<?>> NO_CLASSES = Collections.emptySet();
private Set<UndertowBuilderCustomizer> builderCustomizers = new LinkedHashSet<>(); private Set<UndertowBuilderCustomizer> builderCustomizers = new LinkedHashSet<>();
@ -583,14 +586,15 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac
private URLResource getMetaInfResource(URL resourceJar, String path) { private URLResource getMetaInfResource(URL resourceJar, String path) {
try { try {
URL resourceUrl = new URL(resourceJar + "META-INF/resources" + path); String urlPath = URLEncoder.encode(ENCODED_SLASH.matcher(path).replaceAll("/"), "UTF-8");
URL resourceUrl = new URL(resourceJar + "META-INF/resources" + urlPath);
URLResource resource = new URLResource(resourceUrl, path); URLResource resource = new URLResource(resourceUrl, path);
if (resource.getContentLength() < 0) { if (resource.getContentLength() < 0) {
return null; return null;
} }
return resource; return resource;
} }
catch (MalformedURLException ex) { catch (Exception ex) {
return null; return null;
} }
} }

@ -98,6 +98,10 @@ class ApplicationBuilder {
resourcesJarStream.putNextEntry(new ZipEntry("META-INF/resources/nested-meta-inf-resource.txt")); resourcesJarStream.putNextEntry(new ZipEntry("META-INF/resources/nested-meta-inf-resource.txt"));
resourcesJarStream.write("nested".getBytes()); resourcesJarStream.write("nested".getBytes());
resourcesJarStream.closeEntry(); resourcesJarStream.closeEntry();
resourcesJarStream.putNextEntry(
new ZipEntry("META-INF/resources/nested-reserved-!#$%&()*+,:=?@[]-meta-inf-resource.txt"));
resourcesJarStream.write("encoded-name".getBytes());
resourcesJarStream.closeEntry();
return resourcesJar; return resourcesJar;
} }
} }

@ -40,6 +40,16 @@ public class EmbeddedServletContainerJarDevelopmentIntegrationTests {
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
} }
@TestTemplate
public void metaInfResourceFromDependencyWithNameThatContainsReservedCharactersIsAvailableViaHttp(
RestTemplate rest) {
ResponseEntity<String> entity = rest.getForEntity(
"/nested-reserved-%21%23%24%25%26%28%29%2A%2B%2C%3A%3D%3F%40%5B%5D-meta-inf-resource.txt",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).isEqualTo("encoded-name");
}
@TestTemplate @TestTemplate
public void metaInfResourceFromDependencyIsAvailableViaServletContext(RestTemplate rest) { public void metaInfResourceFromDependencyIsAvailableViaServletContext(RestTemplate rest) {
ResponseEntity<String> entity = rest.getForEntity("/servletContext?/nested-meta-inf-resource.txt", ResponseEntity<String> entity = rest.getForEntity("/servletContext?/nested-meta-inf-resource.txt",

@ -40,6 +40,15 @@ public class EmbeddedServletContainerJarPackagingIntegrationTests {
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
} }
@TestTemplate
public void nestedMetaInfResourceWithNameThatContainsReservedCharactersIsAvailableViaHttp(RestTemplate rest) {
ResponseEntity<String> entity = rest.getForEntity(
"/nested-reserved-%21%23%24%25%26%28%29%2A%2B%2C%3A%3D%3F%40%5B%5D-meta-inf-resource.txt",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).isEqualTo("encoded-name");
}
@TestTemplate @TestTemplate
public void nestedMetaInfResourceIsAvailableViaServletContext(RestTemplate rest) { public void nestedMetaInfResourceIsAvailableViaServletContext(RestTemplate rest) {
ResponseEntity<String> entity = rest.getForEntity("/servletContext?/nested-meta-inf-resource.txt", ResponseEntity<String> entity = rest.getForEntity("/servletContext?/nested-meta-inf-resource.txt",

@ -47,6 +47,16 @@ public class EmbeddedServletContainerWarDevelopmentIntegrationTests {
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
} }
@TestTemplate
public void metaInfResourceFromDependencyWithNameThatContainsReservedCharactersIsAvailableViaHttp(
RestTemplate rest) {
ResponseEntity<String> entity = rest.getForEntity(
"/nested-reserved-%21%23%24%25%26%28%29%2A%2B%2C%3A%3D%3F%40%5B%5D-meta-inf-resource.txt",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).isEqualTo("encoded-name");
}
@TestTemplate @TestTemplate
public void metaInfResourceFromDependencyIsAvailableViaServletContext(RestTemplate rest) { public void metaInfResourceFromDependencyIsAvailableViaServletContext(RestTemplate rest) {
ResponseEntity<String> entity = rest.getForEntity("/servletContext?/nested-meta-inf-resource.txt", ResponseEntity<String> entity = rest.getForEntity("/servletContext?/nested-meta-inf-resource.txt",

@ -47,6 +47,15 @@ public class EmbeddedServletContainerWarPackagingIntegrationTests {
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
} }
@TestTemplate
public void nestedMetaInfResourceWithNameThatContainsReservedCharactersIsAvailableViaHttp(RestTemplate rest) {
ResponseEntity<String> entity = rest.getForEntity(
"/nested-reserved-%21%23%24%25%26%28%29%2A%2B%2C%3A%3D%3F%40%5B%5D-meta-inf-resource.txt",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).isEqualTo("encoded-name");
}
@TestTemplate @TestTemplate
public void nestedMetaInfResourceIsAvailableViaServletContext(RestTemplate rest) { public void nestedMetaInfResourceIsAvailableViaServletContext(RestTemplate rest) {
ResponseEntity<String> entity = rest.getForEntity("/servletContext?/nested-meta-inf-resource.txt", ResponseEntity<String> entity = rest.getForEntity("/servletContext?/nested-meta-inf-resource.txt",

Loading…
Cancel
Save