Allow ResourceController to handle resource paths of arbitrary depth
File paths with slashes seem reasonable, so this change adds support for those. Unfortunately, but unavoidably this requires some manipulation of the servlet request, until changes can be made in Spring MVC. See https://jira.spring.io/browse/SPR-14193. Fixes gh-376
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -20,11 +20,14 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -32,6 +35,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.prepareEnvironment;
|
||||
import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.resolvePlaceholders;
|
||||
@@ -61,10 +65,25 @@ public class ResourceController {
|
||||
this.environmentRepository = environmentRepository;
|
||||
}
|
||||
|
||||
@RequestMapping("/{name}/{profile}/{label}/{path:.*}")
|
||||
public synchronized String resolve(@PathVariable String name,
|
||||
@RequestMapping("/{name}/{profile}/{label}/**")
|
||||
public String resolve(@PathVariable String name,
|
||||
@PathVariable String profile, @PathVariable String label,
|
||||
@PathVariable String path) throws IOException {
|
||||
HttpServletRequest request) throws IOException {
|
||||
String pattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
if (pattern == null) {
|
||||
throw new IllegalStateException("Required request attribute '" +
|
||||
HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE + "' is not set");
|
||||
}
|
||||
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
if (path == null) {
|
||||
throw new IllegalStateException("Required request attribute '" +
|
||||
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");
|
||||
}
|
||||
path = new AntPathMatcher().extractPathWithinPattern(pattern, path);
|
||||
return resolve(name, profile, label, path);
|
||||
}
|
||||
|
||||
synchronized String resolve(String name, String profile, String label, String path) throws IOException {
|
||||
if (label != null && label.contains("(_)")) {
|
||||
// "(_)" is uncommon in a git branch name, but "/" cannot be matched
|
||||
// by Spring MVC
|
||||
@@ -81,10 +100,25 @@ public class ResourceController {
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{name}/{profile}/{label}/{path:.*}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
@RequestMapping(value = "/{name}/{profile}/{label}/**", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public synchronized byte[] binary(@PathVariable String name,
|
||||
@PathVariable String profile, @PathVariable String label,
|
||||
@PathVariable String path) throws IOException {
|
||||
HttpServletRequest request) throws IOException {
|
||||
String pattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
if (pattern == null) {
|
||||
throw new IllegalStateException("Required request attribute '" +
|
||||
HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE + "' is not set");
|
||||
}
|
||||
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
if (path == null) {
|
||||
throw new IllegalStateException("Required request attribute '" +
|
||||
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");
|
||||
}
|
||||
path = new AntPathMatcher().extractPathWithinPattern(pattern, path);
|
||||
return binary(name, profile, label, path);
|
||||
}
|
||||
|
||||
synchronized byte[] binary(String name, String profile, String label, String path) throws IOException {
|
||||
if (label != null && label.contains("(_)")) {
|
||||
// "(_)" is uncommon in a git branch name, but "/" cannot be matched
|
||||
// by Spring MVC
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -86,6 +86,13 @@ public class ResourceControllerTests {
|
||||
assertEquals("foo: dev_bar/spam", resource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourceWithSlash() throws Exception {
|
||||
this.environmentRepository.setSearchLocations("classpath:/test");
|
||||
String resource = this.controller.resolve("foo", "bar", "dev", "spam/foo.txt");
|
||||
assertEquals("foo: dev_bar/spam", resource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void labelWithSlashForBinary() throws Exception {
|
||||
this.environmentRepository.setSearchLocations("classpath:/test");
|
||||
@@ -93,4 +100,11 @@ public class ResourceControllerTests {
|
||||
assertEquals("foo: dev_bar/spam", new String(resource));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourceWithSlashForBinary() throws Exception {
|
||||
this.environmentRepository.setSearchLocations("classpath:/test");
|
||||
byte[] resource = this.controller.binary("foo", "bar", "dev", "spam/foo.txt");
|
||||
assertEquals("foo: dev_bar/spam", new String(resource));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user