package de.juplo.thymeproxy;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
+import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
{
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
- mapping.setUrlMap(Collections.singletonMap("*.html", handler));
+ Map<String, HttpRequestHandler> mappings = new HashMap<>();
+ mappings.put("/*.html", handler);
+ mappings.put("/*/", handler);
+ mappings.put("/*/*.html", handler);
+ mappings.put("/**/", handler);
+ mappings.put("/**/*.html", handler);
+ mapping.setUrlMap(mappings);
return mapping;
}
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
ServletException,
IOException
{
- String path =
+ LOG.debug("handling: {}", request.getRequestURI());
+
+ String path =
(String)
request.getAttribute(
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
}
String resource = builder.toString();
+ LOG.debug("requesting: {}", resource);
+ CloseableHttpResponse p_response = null;
try
{
HttpGet p_request = new HttpGet(resource);
- CloseableHttpResponse p_response = client.execute(p_request);
+
+ p_response = client.execute(p_request);
+
+ StatusLine status = p_response.getStatusLine();
+ int code = status.getStatusCode();
+ LOG.debug("response: {} - {}", code, status.getReasonPhrase());
setCacheControl(computeCacheControl(p_response));
prepareResponse(response);
- Header length = p_response.getLastHeader("Content-Length");
- if (length != null)
- response.addHeader(length.getName(), length.getValue());
+ /** Copy some headers, if present.. */
+ ProxyHttpRequestHandler.copyHeader(p_response, response, "Date");
+ ProxyHttpRequestHandler.copyHeader(p_response, response, "ETag");
+ ProxyHttpRequestHandler.copyHeader(p_response, response, "Last-Modified");
+ ProxyHttpRequestHandler.copyHeader(p_response, response, "Content-Length");
+ ProxyHttpRequestHandler.copyHeader(p_response, response, "Content-Type");
- int status = p_response.getStatusLine().getStatusCode();
- switch (status)
+ switch (code)
{
case HttpServletResponse.SC_FOUND:
case HttpServletResponse.SC_OK:
/** OK. Continue as normal... */
- response.setStatus(status);
+ response.setStatus(code);
HttpEntity entity = p_response.getEntity();
EntityUtils.consume(entity);
p_response.close();
- break;
+ return;
case HttpServletResponse.SC_NOT_FOUND:
case HttpServletResponse.SC_GONE:
/** The resource can not be resolved through this origin */
- response.sendError(status, p_response.getStatusLine().getReasonPhrase());
+ response.sendError(code, status.getReasonPhrase());
return;
case HttpServletResponse.SC_MOVED_PERMANENTLY:
// TODO: throw sensible exceptions, to communicate resolving-errors
throw new RuntimeException(e);
}
+ finally
+ {
+ if (p_response != null)
+ {
+ EntityUtils.consumeQuietly(p_response.getEntity());
+ p_response.close();
+ }
+ }
+ }
+
+ public static void copyHeader(
+ HttpResponse source,
+ HttpServletResponse target,
+ String name
+ )
+ {
+ Header header = source.getLastHeader(name);
+ if (header != null)
+ {
+ LOG.trace("copy header {}: {}", header.getName(), header.getValue());
+ target.addHeader(header.getName(), header.getValue());
+ }
}
public CacheControl computeCacheControl(HttpResponse response)
public ProxyHttpRequestHandler setOrigin(String origin)
{
- this.origin = origin;
+ if (origin.endsWith("/"))
+ this.origin = origin;
+ else
+ this.origin = origin + "/";
return this;
}
*
* @see org.springframework.web.util.UrlPathHelper#setAlwaysUseFullPath
*/
- public void setAlwaysUseFullPath(boolean alwaysUseFullPath)
+ public ProxyHttpRequestHandler setAlwaysUseFullPath(boolean alwaysUseFullPath)
{
this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
+ return this;
}
/**
*
* @see org.springframework.web.util.UrlPathHelper#setUrlDecode
*/
- public void setUrlDecode(boolean urlDecode)
+ public ProxyHttpRequestHandler setUrlDecode(boolean urlDecode)
{
this.urlPathHelper.setUrlDecode(urlDecode);
+ return this;
}
/**
* @see
* org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean)
*/
- public void setRemoveSemicolonContent(boolean removeSemicolonContent)
+ public ProxyHttpRequestHandler setRemoveSemicolonContent(boolean removeSemicolonContent)
{
this.urlPathHelper.setRemoveSemicolonContent(removeSemicolonContent);
+ return this;
}
/**
* @see
* org.springframework.web.servlet.handler.AbstractUrlHandlerMapping#setUrlPathHelper
*/
- public void setUrlPathHelper(UrlPathHelper urlPathHelper)
+ public ProxyHttpRequestHandler setUrlPathHelper(UrlPathHelper urlPathHelper)
{
Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
this.urlPathHelper = urlPathHelper;
- }
-
- /**
- * Return the UrlPathHelper to use for the resolution of lookup paths.
- */
- protected UrlPathHelper getUrlPathHelper()
- {
- return this.urlPathHelper;
+ return this;
}
}