This commit is contained in:
Jesse Eichar 2014-09-24 06:54:03 +00:00
commit 774ce027d9
3 changed files with 125 additions and 47 deletions

View File

@ -203,6 +203,7 @@
<properties> <properties>
<slf4j.version>1.5.11</slf4j.version> <slf4j.version>1.5.11</slf4j.version>
<encoding>UTF-8</encoding>
</properties> </properties>
<dependencies> <dependencies>

View File

@ -25,15 +25,6 @@
package it.geosolutions.geoserver.rest; package it.geosolutions.geoserver.rest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager; import org.apache.commons.httpclient.HttpConnectionManager;
@ -52,6 +43,17 @@ import org.apache.commons.io.IOUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
/** /**
* Low level HTTP utilities. * Low level HTTP utilities.
*/ */
@ -87,8 +89,9 @@ public class HTTPUtils {
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
HttpConnectionManager connectionManager = client.getHttpConnectionManager(); HttpConnectionManager connectionManager = client.getHttpConnectionManager();
try { try {
setAuth(client, url, username, pw); String encodedUrl = encodeUrl(url);
httpMethod = new GetMethod(url); setAuth(client, encodedUrl, username, pw);
httpMethod = new GetMethod(encodedUrl);
connectionManager.getParams().setConnectionTimeout(5000); connectionManager.getParams().setConnectionTimeout(5000);
int status = client.executeMethod(httpMethod); int status = client.executeMethod(httpMethod);
if (status == HttpStatus.SC_OK) { if (status == HttpStatus.SC_OK) {
@ -117,6 +120,58 @@ public class HTTPUtils {
return null; return null;
} }
static String encodeUrl(String url) {
// perform some simple encoding to the path names. This takes care of cases where
// layers or workspaces have illegal http characters.
// it cannot fix all
String protocol, authority, path, query, fragment = null;
String[] protocolPathParts = url.split("://", 2);
if (protocolPathParts.length == 1) {
// unexpected format so just try out url
return url;
}
protocol = protocolPathParts[0];
String[] pathQueryParts = protocolPathParts[1].split("\\?", 2);
path = pathQueryParts[0];
if (pathQueryParts.length == 1) {
query = null;
} else {
query = pathQueryParts[1];
}
if (query == null) {
String[] fragmentParts = path.split("#", 2);
if (fragmentParts.length > 1) {
path = fragmentParts[0];
fragment = fragmentParts[1];
}
} else {
String[] fragmentParts = query.split("#", 2);
if (fragmentParts.length > 1) {
query = fragmentParts[0];
fragment = fragmentParts[1];
}
}
int firstSlash = path.indexOf('/');
if (firstSlash > -1) {
authority = path.substring(0, firstSlash);
path = path.substring(firstSlash);
} else {
authority = path;
path = null;
}
try {
return new URI(protocol, authority, path, query, fragment).toString();
} catch (URISyntaxException e) {
// fallback to original string
return url;
}
}
/** /**
* PUTs a File to the given URL. <BR> * PUTs a File to the given URL. <BR>
* Basic auth is used if both username and pw are not null. * Basic auth is used if both username and pw are not null.
@ -286,8 +341,9 @@ public class HTTPUtils {
RequestEntity requestEntity, String username, String pw) { RequestEntity requestEntity, String username, String pw) {
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
HttpConnectionManager connectionManager = client.getHttpConnectionManager(); HttpConnectionManager connectionManager = client.getHttpConnectionManager();
String encodedUrl = encodeUrl(url);
try { try {
setAuth(client, url, username, pw); setAuth(client, encodedUrl, username, pw);
connectionManager.getParams().setConnectionTimeout(5000); connectionManager.getParams().setConnectionTimeout(5000);
if (requestEntity != null) if (requestEntity != null)
httpMethod.setRequestEntity(requestEntity); httpMethod.setRequestEntity(requestEntity);
@ -304,15 +360,15 @@ public class HTTPUtils {
return response; return response;
default: default:
LOGGER.warn("Bad response: code[" + status + "]" + " msg[" + httpMethod.getStatusText() + "]" LOGGER.warn("Bad response: code[" + status + "]" + " msg[" + httpMethod.getStatusText() + "]"
+ " url[" + url + "]" + " method[" + httpMethod.getClass().getSimpleName() + " url[" + encodedUrl + "]" + " method[" + httpMethod.getClass().getSimpleName()
+ "]: " + IOUtils.toString(httpMethod.getResponseBodyAsStream())); + "]: " + IOUtils.toString(httpMethod.getResponseBodyAsStream()));
return null; return null;
} }
} catch (ConnectException e) { } catch (ConnectException e) {
LOGGER.info("Couldn't connect to [" + url + "]"); LOGGER.info("Couldn't connect to [" + encodedUrl + "]");
return null; return null;
} catch (IOException e) { } catch (IOException e) {
LOGGER.error("Error talking to " + url + " : " + e.getLocalizedMessage()); LOGGER.error("Error talking to " + encodedUrl + " : " + e.getLocalizedMessage());
return null; return null;
} finally { } finally {
if (httpMethod != null) if (httpMethod != null)
@ -326,9 +382,10 @@ public class HTTPUtils {
DeleteMethod httpMethod = null; DeleteMethod httpMethod = null;
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
HttpConnectionManager connectionManager = client.getHttpConnectionManager(); HttpConnectionManager connectionManager = client.getHttpConnectionManager();
String encodedUrl = encodeUrl(url);
try { try {
setAuth(client, url, user, pw); setAuth(client, encodedUrl, user, pw);
httpMethod = new DeleteMethod(url); httpMethod = new DeleteMethod(encodedUrl);
connectionManager.getParams().setConnectionTimeout(5000); connectionManager.getParams().setConnectionTimeout(5000);
int status = client.executeMethod(httpMethod); int status = client.executeMethod(httpMethod);
String response = ""; String response = "";
@ -343,16 +400,16 @@ public class HTTPUtils {
return true; return true;
} }
if (LOGGER.isDebugEnabled()) if (LOGGER.isDebugEnabled())
LOGGER.debug("(" + status + ") " + httpMethod.getStatusText() + " -- " + url); LOGGER.debug("(" + status + ") " + httpMethod.getStatusText() + " -- " + encodedUrl);
return true; return true;
} else { } else {
LOGGER.info("(" + status + ") " + httpMethod.getStatusText() + " -- " + url); LOGGER.info("(" + status + ") " + httpMethod.getStatusText() + " -- " + encodedUrl);
LOGGER.info("Response: '" + response + "'"); LOGGER.info("Response: '" + response + "'");
} }
} catch (ConnectException e) { } catch (ConnectException e) {
LOGGER.info("Couldn't connect to [" + url + "]"); LOGGER.info("Couldn't connect to [" + encodedUrl + "]");
} catch (IOException e) { } catch (IOException e) {
LOGGER.info("Error talking to [" + url + "]", e); LOGGER.info("Error talking to [" + encodedUrl + "]", e);
} finally { } finally {
if (httpMethod != null) if (httpMethod != null)
httpMethod.releaseConnection(); httpMethod.releaseConnection();
@ -375,12 +432,13 @@ public class HTTPUtils {
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
HttpConnectionManager connectionManager = client.getHttpConnectionManager(); HttpConnectionManager connectionManager = client.getHttpConnectionManager();
try { try {
setAuth(client, url, username, pw); String encodedUrl = encodeUrl(url);
httpMethod = new GetMethod(url); setAuth(client, encodedUrl, username, pw);
httpMethod = new GetMethod(encodedUrl);
connectionManager.getParams().setConnectionTimeout(2000); connectionManager.getParams().setConnectionTimeout(2000);
int status = client.executeMethod(httpMethod); int status = client.executeMethod(httpMethod);
if (status != HttpStatus.SC_OK) { if (status != HttpStatus.SC_OK) {
LOGGER.warn("PING failed at '" + url + "': (" + status + ") " + httpMethod.getStatusText()); LOGGER.warn("PING failed at '" + encodedUrl + "': (" + status + ") " + httpMethod.getStatusText());
return false; return false;
} else { } else {
return true; return true;
@ -412,8 +470,9 @@ public class HTTPUtils {
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
HttpConnectionManager connectionManager = client.getHttpConnectionManager(); HttpConnectionManager connectionManager = client.getHttpConnectionManager();
try { try {
setAuth(client, url, username, pw); String encodedUrl = encodeUrl(url);
httpMethod = new GetMethod(url); setAuth(client, encodedUrl, username, pw);
httpMethod = new GetMethod(encodedUrl);
connectionManager.getParams().setConnectionTimeout(2000); connectionManager.getParams().setConnectionTimeout(2000);
int status = client.executeMethod(httpMethod); int status = client.executeMethod(httpMethod);
switch (status) { switch (status) {
@ -422,7 +481,7 @@ public class HTTPUtils {
case HttpStatus.SC_NOT_FOUND: case HttpStatus.SC_NOT_FOUND:
return false; return false;
default: default:
throw new RuntimeException("Unhandled response status at '" + url + "': (" + status + ") " throw new RuntimeException("Unhandled response status at '" + encodedUrl + "': (" + status + ") "
+ httpMethod.getStatusText()); + httpMethod.getStatusText());
} }
} catch (ConnectException e) { } catch (ConnectException e) {
@ -438,7 +497,9 @@ public class HTTPUtils {
private static void setAuth(HttpClient client, String url, String username, String pw) private static void setAuth(HttpClient client, String url, String username, String pw)
throws MalformedURLException { throws MalformedURLException {
URL u = new URL(url);
String encodedUrl = encodeUrl(url);
URL u = new URL(encodedUrl);
if (username != null && pw != null) { if (username != null && pw != null) {
Credentials defaultcreds = new UsernamePasswordCredentials(username, pw); Credentials defaultcreds = new UsernamePasswordCredentials(username, pw);
client.getState().setCredentials(new AuthScope(u.getHost(), u.getPort()), defaultcreds); client.getState().setCredentials(new AuthScope(u.getHost(), u.getPort()), defaultcreds);
@ -449,7 +510,7 @@ public class HTTPUtils {
// authentication // authentication
} else { } else {
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Not setting credentials to access to " + url); LOGGER.debug("Not setting credentials to access to " + encodedUrl);
} }
} }
} }

View File

@ -0,0 +1,16 @@
package it.geosolutions.geoserver.rest;
import junit.framework.TestCase;
public class HTTPUtilsTest extends TestCase {
public void testEncodeUrl() throws Exception {
assertEquals("http://with%20spaces", HTTPUtils.encodeUrl("http://with spaces"));
assertEquals("http://with%20spaces?p1=v1", HTTPUtils.encodeUrl("http://with spaces?p1=v1"));
assertEquals("http://without/spaces?p1=v1", HTTPUtils.encodeUrl("http://without/spaces?p1=v1"));
assertEquals("http://without/spaces", HTTPUtils.encodeUrl("http://without/spaces"));
assertEquals("http://without/spaces#fragment", HTTPUtils.encodeUrl("http://without/spaces#fragment"));
assertEquals("http://without/spaces?p1=v1#fragment", HTTPUtils.encodeUrl("http://without/spaces?p1=v1#fragment"));
assertEquals("http://with%20spaces#fragment", HTTPUtils.encodeUrl("http://with spaces#fragment"));
assertEquals("brokenurl?p1=v1", HTTPUtils.encodeUrl("brokenurl?p1=v1"));
}
}