mirror of https://github.com/halo-dev/halo
Add custom RequestMappingHandlerMapping for enable static resources access (#558)
parent
028268c698
commit
49494abbbd
|
@ -15,15 +15,20 @@ import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
|
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
|
||||||
|
import org.springframework.data.web.SortHandlerMethodArgumentResolver;
|
||||||
import org.springframework.format.FormatterRegistry;
|
import org.springframework.format.FormatterRegistry;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
import org.springframework.util.PathMatcher;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
|
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
||||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
|
||||||
import run.halo.app.config.properties.HaloProperties;
|
import run.halo.app.config.properties.HaloProperties;
|
||||||
|
@ -32,11 +37,9 @@ import run.halo.app.factory.StringToEnumConverterFactory;
|
||||||
import run.halo.app.model.support.HaloConst;
|
import run.halo.app.model.support.HaloConst;
|
||||||
import run.halo.app.security.resolver.AuthenticationArgumentResolver;
|
import run.halo.app.security.resolver.AuthenticationArgumentResolver;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||||
import static run.halo.app.model.support.HaloConst.HALO_ADMIN_RELATIVE_PATH;
|
import static run.halo.app.model.support.HaloConst.HALO_ADMIN_RELATIVE_PATH;
|
||||||
|
@ -50,16 +53,23 @@ import static run.halo.app.utils.HaloUtils.*;
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebMvc
|
|
||||||
@ComponentScan(basePackages = "run.halo.app.controller")
|
@ComponentScan(basePackages = "run.halo.app.controller")
|
||||||
@PropertySource(value = "classpath:application.yaml", ignoreResourceNotFound = true, encoding = "UTF-8")
|
@PropertySource(value = "classpath:application.yaml", ignoreResourceNotFound = true, encoding = "UTF-8")
|
||||||
public class WebMvcAutoConfiguration implements WebMvcConfigurer {
|
public class WebMvcAutoConfiguration extends WebMvcConfigurationSupport {
|
||||||
|
|
||||||
private static final String FILE_PROTOCOL = "file:///";
|
private static final String FILE_PROTOCOL = "file:///";
|
||||||
|
|
||||||
|
private final PageableHandlerMethodArgumentResolver pageableResolver;
|
||||||
|
|
||||||
|
private final SortHandlerMethodArgumentResolver sortResolver;
|
||||||
|
|
||||||
private final HaloProperties haloProperties;
|
private final HaloProperties haloProperties;
|
||||||
|
|
||||||
public WebMvcAutoConfiguration(HaloProperties haloProperties) {
|
public WebMvcAutoConfiguration(PageableHandlerMethodArgumentResolver pageableResolver,
|
||||||
|
SortHandlerMethodArgumentResolver sortResolver,
|
||||||
|
HaloProperties haloProperties) {
|
||||||
|
this.pageableResolver = pageableResolver;
|
||||||
|
this.sortResolver = sortResolver;
|
||||||
this.haloProperties = haloProperties;
|
this.haloProperties = haloProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +90,8 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
|
||||||
@Override
|
@Override
|
||||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||||
resolvers.add(new AuthenticationArgumentResolver());
|
resolvers.add(new AuthenticationArgumentResolver());
|
||||||
|
resolvers.add(pageableResolver);
|
||||||
|
resolvers.add(sortResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,4 +202,54 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
|
||||||
resolver.setContentType("text/html; charset=UTF-8");
|
resolver.setContentType("text/html; charset=UTF-8");
|
||||||
registry.viewResolver(resolver);
|
registry.viewResolver(resolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
|
||||||
|
return new HaloRequestMappingHandlerMapping(haloProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
|
||||||
|
|
||||||
|
private final Set<String> blackPatterns = new HashSet<>(16);
|
||||||
|
|
||||||
|
private final PathMatcher pathMatcher;
|
||||||
|
|
||||||
|
private final HaloProperties haloProperties;
|
||||||
|
|
||||||
|
public HaloRequestMappingHandlerMapping(HaloProperties haloProperties) {
|
||||||
|
this.haloProperties = haloProperties;
|
||||||
|
this.initBlackPatterns();
|
||||||
|
pathMatcher = new AntPathMatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
|
||||||
|
log.debug("Looking path: [{}]", lookupPath);
|
||||||
|
for (String blackPattern : blackPatterns) {
|
||||||
|
if (this.pathMatcher.match(blackPattern, lookupPath)) {
|
||||||
|
log.info("Skipped path [{}] with pattern: [{}]", lookupPath, blackPattern);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.lookupHandlerMethod(lookupPath, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initBlackPatterns() {
|
||||||
|
String uploadUrlPattern = ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
|
||||||
|
String adminPathPattern = ensureBoth(haloProperties.getAdminPath(), URL_SEPARATOR) + "**";
|
||||||
|
|
||||||
|
|
||||||
|
blackPatterns.add("/themes/**");
|
||||||
|
blackPatterns.add("/js/**");
|
||||||
|
blackPatterns.add("/images/**");
|
||||||
|
blackPatterns.add("/fonts/**");
|
||||||
|
blackPatterns.add("/css/**");
|
||||||
|
blackPatterns.add("/assets/**");
|
||||||
|
blackPatterns.add("/swagger-ui.html");
|
||||||
|
blackPatterns.add("/csrf");
|
||||||
|
blackPatterns.add("/webjars/**");
|
||||||
|
blackPatterns.add(uploadUrlPattern);
|
||||||
|
blackPatterns.add(adminPathPattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ public class ContentArchiveController {
|
||||||
|
|
||||||
private final StringCacheStore cacheStore;
|
private final StringCacheStore cacheStore;
|
||||||
|
|
||||||
|
|
||||||
public ContentArchiveController(PostService postService,
|
public ContentArchiveController(PostService postService,
|
||||||
OptionService optionService,
|
OptionService optionService,
|
||||||
StringCacheStore cacheStore) {
|
StringCacheStore cacheStore) {
|
||||||
|
@ -41,14 +42,14 @@ public class ContentArchiveController {
|
||||||
this.cacheStore = cacheStore;
|
this.cacheStore = cacheStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "{url}/password")
|
@GetMapping(value = "{url:.*}/password")
|
||||||
public String password(@PathVariable("url") String url,
|
public String password(@PathVariable("url") String url,
|
||||||
Model model) {
|
Model model) {
|
||||||
model.addAttribute("url", url);
|
model.addAttribute("url", url);
|
||||||
return "common/template/post_password";
|
return "common/template/post_password";
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "{url}/password")
|
@PostMapping(value = "{url:.*}/password")
|
||||||
@CacheLock(traceRequest = true, expired = 2)
|
@CacheLock(traceRequest = true, expired = 2)
|
||||||
public String password(@PathVariable("url") String url,
|
public String password(@PathVariable("url") String url,
|
||||||
@RequestParam(value = "password") String password) {
|
@RequestParam(value = "password") String password) {
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class ContentContentController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("{prefix}/page/{page}")
|
@GetMapping("{prefix}/page/{page:\\d+}")
|
||||||
public String content(@PathVariable("prefix") String prefix,
|
public String content(@PathVariable("prefix") String prefix,
|
||||||
@PathVariable(value = "page") Integer page,
|
@PathVariable(value = "page") Integer page,
|
||||||
Model model) {
|
Model model) {
|
||||||
|
@ -89,7 +89,7 @@ public class ContentContentController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("{prefix}/{url}")
|
@GetMapping("{prefix}/{url:.+}")
|
||||||
public String content(@PathVariable("prefix") String prefix,
|
public String content(@PathVariable("prefix") String prefix,
|
||||||
@PathVariable("url") String url,
|
@PathVariable("url") String url,
|
||||||
@RequestParam(value = "token", required = false) String token,
|
@RequestParam(value = "token", required = false) String token,
|
||||||
|
@ -115,7 +115,7 @@ public class ContentContentController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("{prefix}/{url}/page/{page}")
|
@GetMapping("{prefix}/{url}/page/{page:\\d+}")
|
||||||
public String content(@PathVariable("prefix") String prefix,
|
public String content(@PathVariable("prefix") String prefix,
|
||||||
@PathVariable("url") String url,
|
@PathVariable("url") String url,
|
||||||
@PathVariable("page") Integer page,
|
@PathVariable("page") Integer page,
|
||||||
|
@ -132,7 +132,7 @@ public class ContentContentController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @GetMapping("{year:^[^A-Za-z]*$}/{month:^[^A-Za-z]*$}/{url}")
|
@GetMapping("{year:\\d+}/{month:\\d+}/{url:.+}")
|
||||||
public String content(@PathVariable("year") Integer year,
|
public String content(@PathVariable("year") Integer year,
|
||||||
@PathVariable("month") Integer month,
|
@PathVariable("month") Integer month,
|
||||||
@PathVariable("url") String url,
|
@PathVariable("url") String url,
|
||||||
|
@ -147,7 +147,7 @@ public class ContentContentController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @GetMapping("{year:^[^A-Za-z]*$}/{month:^[^A-Za-z]*$}/{day:^[^A-Za-z]*$}/{url}")
|
@GetMapping("{year:\\d+}/{month:\\d+}/{day:\\d+}/{url:.+}")
|
||||||
public String content(@PathVariable("year") Integer year,
|
public String content(@PathVariable("year") Integer year,
|
||||||
@PathVariable("month") Integer month,
|
@PathVariable("month") Integer month,
|
||||||
@PathVariable("day") Integer day,
|
@PathVariable("day") Integer day,
|
||||||
|
|
Loading…
Reference in New Issue