Permalink
Browse files

support pluggable url mangling

Url mangling is useful when integrating with geoserver. If a proxy url
is set, that's the one that should be used during url generation.
  • Loading branch information...
1 parent 65c9d47 commit 685ec71a659409f0885e576a33faed9790a9d6b5 @rmarianski committed Oct 17, 2012
@@ -0,0 +1,12 @@
+package org.geowebcache.util;
+
+import org.apache.commons.lang.StringUtils;
+
+public class NullURLMangler implements URLMangler {
+
+ public String buildURL(String baseURL, String contextPath, String path) {
+ return StringUtils.strip(baseURL, "/") + "/" + StringUtils.strip(contextPath, "/") + "/"
+ + StringUtils.stripStart(path, "/");
+ }
+
+}
@@ -33,6 +33,8 @@
import java.util.Map.Entry;
import java.util.TimeZone;
+import javax.servlet.http.HttpServletRequest;
+
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -443,4 +445,17 @@ public static String disableHTMLTags(String str) {
}
return ret;
}
+
+ /**
+ * Generate the base url of the request, minus the context path
+ * @param req servlet request
+ * @return Base url of request, minus the context path
+ */
+ public static String getServletBaseURL(HttpServletRequest req) {
+ if (req.getServerPort() == 80 || req.getServerPort() == 443) {
+ return req.getScheme() + "://" + req.getServerName();
+ } else {
+ return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort();
+ }
+ }
}
@@ -0,0 +1,24 @@
+/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
+ * This code is licensed under the GPL 2.0 license, availible at the root
+ * application directory.
+ */
+package org.geowebcache.util;
+
+/**
+ * subset copied from org.geoserver.ows.URLMangler
+ *
+ * This hook allows others to plug in custom url generation.
+ *
+ */
+public interface URLMangler {
+
+ /**
+ * Allows for a custom url generation strategy
+ * @param baseURL the base url - contains the url up to the domain and port
+ * @param contextPath the servlet context path, like /geoserver/gwc
+ * @param path the remaining path after the context path
+ * @return the full generated url from the pieces
+ */
+ public String buildURL(String baseURL, String contextPath, String path);
+
+}
@@ -0,0 +1,29 @@
+package org.geowebcache.util;
+
+import junit.framework.TestCase;
+
+public class NullURLManglerTest extends TestCase {
+
+ private URLMangler urlMangler;
+
+ @Override
+ protected void setUp() throws Exception {
+ urlMangler = new NullURLMangler();
+ }
+
+ public void testBuildURL() {
+ String url = urlMangler.buildURL("http://foo.example.com", "/foo", "/bar");
+ assertEquals("http://foo.example.com/foo/bar", url);
+ }
+
+ public void testBuildTrailingSlashes() throws Exception {
+ String url = urlMangler.buildURL("http://foo.example.com/", "/foo/", "/bar");
+ assertEquals("http://foo.example.com/foo/bar", url);
+ }
+
+ public void testBuildNoLeadingSlashes() throws Exception {
+ String url = urlMangler.buildURL("http://foo.example.com/", "foo/", "bar");
+ assertEquals("http://foo.example.com/foo/bar", url);
+ }
+
+}
@@ -36,6 +36,7 @@
import org.geowebcache.rest.XstreamRepresentation;
import org.geowebcache.service.HttpErrorCodeException;
import org.geowebcache.util.ServletUtils;
+import org.geowebcache.util.URLMangler;
import org.json.JSONException;
import org.json.JSONObject;
import org.restlet.data.CharacterSet;
@@ -71,6 +72,13 @@
private TileLayerDispatcher layerDispatcher;
+ private URLMangler urlMangler;
+
+ // set by spring
+ public void setUrlMangler(URLMangler urlMangler) {
+ this.urlMangler = urlMangler;
+ }
+
@Override
public void handle(Request request, Response response) {
Method met = request.getMethod();
@@ -120,11 +128,11 @@ protected void doGet(Request req, Response resp) throws RestletException {
Representation representation;
if (layerName == null) {
- String restRoot = req.getResourceRef().getParentRef().toString();
- if (restRoot.endsWith("/")) {
- restRoot = restRoot.substring(0, restRoot.length() - 1);
- }
- representation = listLayers(formatExtension, restRoot);
+ String restRoot = req.getRootRef().toString();
+ String contextPath = req.getRootRef().getPath();
+ String baseURL = restRoot.substring(0, restRoot.length() - contextPath.length());
+ String prefix = req.getResourceRef().getParentRef().getPath();
+ representation = listLayers(formatExtension, baseURL, prefix);
} else {
try {
layerName = URLDecoder.decode(layerName, "UTF-8");
@@ -138,9 +146,10 @@ protected void doGet(Request req, Response resp) throws RestletException {
/**
* @param extension
* @param rootPath
+ * @param contextPath
* @return
*/
- Representation listLayers(String extension, final String restRoot) {
+ Representation listLayers(String extension, final String rootPath, final String contextPath) {
if (null == extension) {
extension = "xml";
@@ -190,7 +199,8 @@ public void marshal(Object source, HierarchicalStreamWriter writer,
writer.startNode("atom:link");
writer.addAttribute("xmlns:atom", "http://www.w3.org/2005/Atom");
writer.addAttribute("rel", "alternate");
- String href = restRoot + "/layers/" + ServletUtils.URLEncode(name) + ".xml";
+ String href = urlMangler.buildURL(rootPath, contextPath, "/layers/"
+ + ServletUtils.URLEncode(name) + ".xml");
writer.addAttribute("href", href);
writer.addAttribute("type", MediaType.TEXT_XML.toString());
@@ -41,6 +41,7 @@
import org.geowebcache.layer.TileLayer;
import org.geowebcache.layer.TileLayerDispatcher;
import org.geowebcache.rest.RestletException;
+import org.geowebcache.util.NullURLMangler;
import org.geowebcache.util.ServletUtils;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
@@ -90,6 +91,7 @@ protected void setUp() throws Exception {
tlr = new TileLayerRestlet();
tlr.setXMLConfiguration(xmlConfig);
tlr.setTileLayerDispatcher(tld);
+ tlr.setUrlMangler(new NullURLMangler());
}
public void testGetXml() throws Exception {
@@ -130,8 +132,9 @@ public void testGetInvalid() throws Exception {
public void testGetList() throws Exception {
- final String rootPath = "http://my.gwc.org/rest";
- Representation rep = tlr.listLayers("xml", rootPath);
+ final String rootPath = "http://my.gwc.org";
+ final String contextPath = "/rest";
+ Representation rep = tlr.listLayers("xml", rootPath, contextPath);
assertNotNull(rep);
assertEquals(CharacterSet.UTF_8, rep.getCharacterSet());
@@ -159,7 +162,7 @@ public void testGetList() throws Exception {
String xpath = "/layers/layer[" + xpathIndex + "]/name";
assertXpathEvaluatesTo(layerName, xpath, dom);
- String href = rootPath + "/layers/" + ServletUtils.URLEncode(layerName) + ".xml";
+ String href = rootPath + contextPath + "/layers/" + ServletUtils.URLEncode(layerName) + ".xml";
xpath = "/layers/layer[" + xpathIndex + "]/link/@href";
String actual = xpathEngine.evaluate(xpath, dom);
// System.err.println("-------- " + actual);
@@ -26,6 +26,7 @@
import org.geowebcache.layer.TileLayerDispatcher;
import org.geowebcache.layer.meta.LayerMetaInformation;
import org.geowebcache.mime.MimeType;
+import org.geowebcache.util.URLMangler;
/**
* Basic implementation of the TMS documents. Not all of GWCs more advanced
@@ -40,17 +41,24 @@
GridSetBroker gsb;
String baseUrl;
+
+ private final String contextPath;
+
+ private final URLMangler urlMangler;
- protected TMSDocumentFactory(TileLayerDispatcher tld, GridSetBroker gsb, String baseUrl) {
+ protected TMSDocumentFactory(TileLayerDispatcher tld, GridSetBroker gsb, String baseUrl,
+ String contextPath, URLMangler urlMangler) {
this.tld = tld;
this.gsb = gsb;
this.baseUrl = baseUrl;
+ this.contextPath = contextPath;
+ this.urlMangler = urlMangler;
}
protected String getTileMapServiceDoc() {
StringBuilder str = new StringBuilder();
str.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
- str.append("<TileMapService version=\"1.0.0\" services=\""+baseUrl+"\">\n");
+ str.append("<TileMapService version=\"1.0.0\" services=\""+urlMangler.buildURL(baseUrl, contextPath, "")+"\">\n");
// TODO can have these set through Spring
str.append(" <Title>Tile Map Service</Title>\n");
str.append(" <Abstract>A Tile Map Service served by GeoWebCache</Abstract>\n");
@@ -109,7 +117,7 @@ private void tileMapsForLayer(StringBuilder str, TileLayer layer) {
protected String getTileMapDoc(TileLayer layer, GridSubset gridSub, GridSetBroker gsb, MimeType mimeType) {
StringBuilder str = new StringBuilder();
str.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
- str.append("<TileMap version=\"1.0.0\" tilemapservice=\""+ baseUrl + "/service/tms/1.0.0\">\n");
+ str.append("<TileMap version=\"1.0.0\" tilemapservice=\""+ urlMangler.buildURL(baseUrl, contextPath, "/service/tms/1.0.0") + "\">\n");
str.append(" <Title>").append(tileMapTitle(layer)).append("</Title>\n");
str.append(" <Abstract>").append(tileMapDescription(layer)).append("</Abstract>\n");
// <KeywordList></KeywordList>
@@ -166,7 +174,7 @@ private String profileForGridSet(GridSet gridSet) {
private String tileMapUrl(TileLayer tl, GridSubset gridSub, MimeType mimeType) {
// TODO add XML escaping
- return baseUrl + "/service/tms/1.0.0/" + tileMapName(tl,gridSub,mimeType);
+ return urlMangler.buildURL(baseUrl, contextPath, "/service/tms/1.0.0/" + tileMapName(tl,gridSub,mimeType));
}
private String tileMapUrl(TileLayer tl, GridSubset gridSub, MimeType mimeType, int z) {
@@ -36,6 +36,7 @@
import org.geowebcache.stats.RuntimeStats;
import org.geowebcache.storage.StorageBroker;
import org.geowebcache.util.ServletUtils;
+import org.geowebcache.util.URLMangler;
public class TMSService extends Service {
@@ -47,29 +48,27 @@
private GridSetBroker gsb;
- private String baseUrl;
-
private RuntimeStats stats;
-
+
+ private URLMangler urlMangler;
+
/**
* Protected no-argument constructor to allow run-time instrumentation
*/
protected TMSService() {
super(SERVICE_TMS);
}
- public TMSService(StorageBroker sb, TileLayerDispatcher tld, GridSetBroker gsb, RuntimeStats stats) {
+ public TMSService(StorageBroker sb, TileLayerDispatcher tld, GridSetBroker gsb,
+ RuntimeStats stats, URLMangler urlMangler) {
super(SERVICE_TMS);
this.sb = sb;
this.tld = tld;
this.gsb = gsb;
this.stats = stats;
+ this.urlMangler = urlMangler;
}
- public void setBaseURL(String baseUrl) {
- this.baseUrl = baseUrl;
- }
-
@Override
public ConveyorTile getConveyor(HttpServletRequest request,
HttpServletResponse response) throws GeoWebCacheException {
@@ -139,15 +138,13 @@ public void handleRequest(Conveyor conv)
int paramsLength = params.length;
- String base = this.baseUrl;
+ String reqUrl = conv.servletReq.getRequestURL().toString();
+ String servletBase = ServletUtils.getServletBaseURL(conv.servletReq);
+ int prefixIdx = servletBase.length();
+ int suffixIdx = reqUrl.indexOf("/service/tms/1.0.0");
+ String context = reqUrl.substring(prefixIdx, suffixIdx);
- if(base == null) {
- String reqUrl = conv.servletReq.getRequestURL().toString();
- int idx = reqUrl.indexOf("/service/tms/1.0.0");
- base = reqUrl.substring(0, idx);
- }
-
- TMSDocumentFactory tdf = new TMSDocumentFactory(tld,gsb, base);
+ TMSDocumentFactory tdf = new TMSDocumentFactory(tld, gsb, servletBase, context, urlMangler);
String ret = null;
@@ -181,8 +178,6 @@ public void handleRequest(Conveyor conv)
} catch (IOException e) {
// TODO log error
}
-
-
}
-
-}
+
+}
@@ -176,4 +176,6 @@
<bean id="gwcProxyDispatcher"
class="org.geowebcache.proxy.ProxyDispatcher"/>
+ <bean id="gwcURLMangler" class="org.geowebcache.util.NullURLMangler" />
+
</beans>
@@ -20,6 +20,7 @@
<bean id="gwcTileLayerRestlet" class="org.geowebcache.rest.layers.TileLayerRestlet">
<property name="XMLConfiguration" ref="gwcXmlConfig"/>
<property name="tileLayerDispatcher" ref="gwcTLDispatcher"/>
+ <property name="urlMangler" ref="gwcURLMangler"/>
</bean>
<bean id="gwcBoundsRestlet" class="org.geowebcache.rest.bounds.BoundsRestlet">
<property name="tileLayerDispatcher" ref="gwcTLDispatcher"/>
@@ -10,8 +10,7 @@
<constructor-arg ref="gwcTLDispatcher"/>
<constructor-arg ref="gwcGridSetBroker"/>
<constructor-arg ref="gwcRuntimeStats"/>
- <!-- Optionally you can set the base URL for the service -->
- <!-- <property name="baseURL" value="http://localhost:8080/geowebcache" /> -->
+ <constructor-arg ref="gwcURLMangler"/>
</bean>
</beans>

0 comments on commit 685ec71

Please sign in to comment.