1 package de.juplo.thymeproxy;
3 import de.juplo.thymeleaf.JuploDialect;
4 import java.util.HashMap;
5 import java.util.Locale;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9 import org.apache.http.HttpStatus;
10 import org.apache.http.impl.client.CloseableHttpClient;
11 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.boot.SpringApplication;
13 import org.springframework.boot.autoconfigure.SpringBootApplication;
14 import org.springframework.boot.autoconfigure.web.BasicErrorController;
15 import org.springframework.boot.autoconfigure.web.ErrorAttributes;
16 import org.springframework.boot.autoconfigure.web.ErrorController;
17 import org.springframework.boot.autoconfigure.web.ErrorProperties;
18 import org.springframework.boot.autoconfigure.web.ServerProperties;
19 import org.springframework.context.annotation.Bean;
20 import org.springframework.core.Ordered;
21 import org.springframework.core.env.Environment;
22 import org.springframework.http.MediaType;
23 import org.springframework.web.servlet.ModelAndView;
24 import org.springframework.web.servlet.View;
25 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
26 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
27 import org.springframework.web.servlet.mvc.UrlFilenameViewController;
28 import org.thymeleaf.exceptions.TemplateInputException;
29 import org.thymeleaf.resourceresolver.IResourceResolver;
30 import org.thymeleaf.resourceresolver.UrlResourceResolver;
31 import org.thymeleaf.spring4.view.ThymeleafViewResolver;
32 import org.thymeleaf.templateresolver.TemplateResolver;
35 @SpringBootApplication
36 public class Application extends WebMvcConfigurerAdapter
39 private ServerProperties properties;
43 public RegexUrlHandlerMapping proxiedHandlerMapping(
44 ProxyHttpRequestHandler proxy,
45 UrlFilenameViewController views
48 RegexUrlHandlerMapping mapping = new RegexUrlHandlerMapping();
49 mapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
50 Map<String, Object> mappings = new HashMap<>();
51 mappings.put("/thymeleaf/.*\\.html", proxy);
52 mappings.put("/img/.+", proxy);
53 mappings.put("/css/.+", proxy);
54 mappings.put("/js/.+", proxy);
55 mappings.put("/fonts/.+", proxy);
56 mappings.put("/.*\\.html", views);
57 mapping.setUrlMap(mappings);
62 public ProxyHttpRequestHandler proxyHttpRequestHandler(
63 CloseableHttpClient client,
67 ProxyHttpRequestHandler handler = new ProxyHttpRequestHandler();
68 handler.setClient(client);
69 handler.setOrigin(env.getProperty("thymeproxy.origin"));
70 handler.setTtl(30000l);
75 public UrlFilenameViewController urlFilenameViewController()
77 return new UrlFilenameViewController();
81 public TemplateResolver defaultTemplateResolver(
82 IResourceResolver resources,
86 TemplateResolver resolver = new TemplateResolver();
87 resolver.setResourceResolver(resources);
88 resolver.setPrefix("http://localhost:8080/thymeleaf/");
89 resolver.setSuffix(".html");
90 resolver.setTemplateMode("HTML5");
91 resolver.setCharacterEncoding("UTF-8");
92 resolver.setCacheable(Boolean.valueOf(env.getProperty("thymeproxy.cacheable")));
97 public TemplateResolver jsonTemplateResolver(
98 IResourceResolver resources,
102 TemplateResolver resolver = new TemplateResolver();
103 resolver.setResourceResolver(resources);
104 resolver.setPrefix("http://localhost:8080/thymeleaf/");
105 resolver.setSuffix(".json");
106 resolver.setTemplateMode("JSON");
107 resolver.setCharacterEncoding("UTF-8");
108 resolver.setCacheable(Boolean.valueOf(env.getProperty("thymeproxy.cacheable")));
113 public UrlResourceResolver thymeleafResourceResolver()
115 return new UrlResourceResolver();
119 public JuploDialect juploDialect()
121 return new JuploDialect();
125 public View error(ThymeleafViewResolver resolver) throws Exception
127 return resolver.resolveViewName("templates/500", Locale.getDefault());
131 public ErrorController errorController(ErrorAttributes errorAttributes)
133 return new CustomErrorController(errorAttributes, properties.getError());
138 public void addViewControllers(ViewControllerRegistry registry)
140 registry.addViewController("/").setViewName("forward:index.html");
144 public static void main(String[] args)
146 SpringApplication.run(Application.class, args);
150 static class CustomErrorController extends BasicErrorController
152 public final static String TEMPLATE_INPUT_EXCEPTION =
153 TemplateInputException.class.getCanonicalName();
156 CustomErrorController(
157 ErrorAttributes errorAttributes,
158 ErrorProperties errorProperties
161 super(errorAttributes, errorProperties);
166 public ModelAndView errorHtml(
167 HttpServletRequest request,
168 HttpServletResponse response
171 Map<String, Object> model =
174 isIncludeStackTrace(request, MediaType.TEXT_HTML)
179 switch ((String)model.get("exception"))
181 case "org.thymeleaf.exceptions.TemplateInputException":
182 response.setStatus(HttpStatus.SC_NOT_FOUND);
183 view = "templates/404";
187 response.setStatus(getStatus(request).value());
188 view = "templates/500";
192 return new ModelAndView(view, model);