在本文中,我们将演示如何使用 HttpClient 解除URL的绑定。
一个简单的例子就是当原始URL被缩短一次 - 通过诸如bit.ly的服务。
一个更复杂的例子是,URL被多次缩短,被不同的服务缩短,并且需要多次才能到达原始的完整URL。
让我们从简单的开始 - 取消暂停仅通过一次缩短的URL服务传递的URL。
首先我们需要的是一个不会自动遵循重定向的http客户端:
CloseableHttpClient client =
HttpClientBuilder.create().disableRedirectHandling().build();
这是必要的,因为我们需要手动拦截重定向响应并从中提取信息。
我们首先发送一个请求到缩短的网址 - 我们得到的回应将是一个301永久移动。
然后,我们需要提取指向下一个的位置标题,在这种情况下 - 最终的URL:
public String expandSingleLevel(String url) throws IOException {
HttpHead request = null;
try {
request = new HttpHead(url);
HttpResponse httpResponse = client.execute(request);
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode != 301 && statusCode != 302) {
return url;
}
Header[] headers = httpResponse.getHeaders(HttpHeaders.LOCATION);
Preconditions.checkState(headers.length == 1);
String newUrl = headers[0].getValue();
return newUrl;
} catch (IllegalArgumentException uriEx) {
return url;
} finally {
if (request != null) {
request.releaseConnection();
}
}
}
最后,一个简单的现场测试扩展一个URL:
@Test
public void givenShortenedOnce_whenUrlIsUnshortened_thenCorrectResult() throws IOException {
String expectedResult = "/rest-versioning";
String actualResult = expandSingleLevel("http://bit.ly/13jEoS1");
assertThat(actualResult, equalTo(expectedResult));
}
短网址的问题在于,它们可能会被完全不同的服务缩短多次。展开这样的网址需要多次传递才能访问原始网址。
我们将应用先前定义的expandSingleLevel基元操作来简单地遍历所有中间URL并达到最终目标:
public String expand(String urlArg) throws IOException {
String originalUrl = urlArg;
String newUrl = expandSingleLevel(originalUrl);
while (!originalUrl.equals(newUrl)) {
originalUrl = newUrl;
newUrl = expandSingleLevel(originalUrl);
}
return newUrl;
}
现在,通过扩展多个URL级别的新机制,我们定义一个测试并使其工作:
@Test
public void givenShortenedMultiple_whenUrlIsUnshortened_thenCorrectResult() throws IOException {
String expectedResult = "/rest-versioning";
String actualResult = expand("http://t.co/e4rDDbnzmk");
assertThat(actualResult, equalTo(expectedResult));
}
这一次,短网址 - http://t.co/e4rDDbnzmk - 实际上缩短了两次 - 一次通过bit.ly,第二次通过t.co服务 - 正确地扩展到原始URL。
最后,一些URL不能被扩展,因为它们形成了重定向循环。这种类型的问题会被HttpClient检测到,但是由于我们关闭了重定向的自动跟踪,因此不再这样做。
URL扩展机制的最后一步是检测重定向循环,并在发生这种循环时快速失败。
为了使其有效,我们需要使用前面定义的expandSingleLevel方法提供一些附加信息- 主要是我们还需要返回响应的状态代码和URL。
由于java不支持多个返回值,我们将把这些信息包装在一个org.apache.commons.lang3.tuple.Pair对象中 - 方法的新签名现在是:
public Pair<Integer, String> expandSingleLevelSafe(String url) throws IOException {}
最后,让我们在主扩展机制中包含重定向周期检测:
public String expandSafe(String urlArg) throws IOException {
String originalUrl = urlArg;
String newUrl = expandSingleLevelSafe(originalUrl).getRight();
List<String> alreadyVisited = Lists.newArrayList(originalUrl, newUrl);
while (!originalUrl.equals(newUrl)) {
originalUrl = newUrl;
Pair<Integer, String> statusAndUrl = expandSingleLevelSafe(originalUrl);
newUrl = statusAndUrl.getRight();
boolean isRedirect = statusAndUrl.getLeft() == 301 || statusAndUrl.getLeft() == 302;
if (isRedirect && alreadyVisited.contains(newUrl)) {
throw new IllegalStateException("Likely a redirect loop");
}
alreadyVisited.add(newUrl);
}
return newUrl;
}
就是这样 - expandSafe机制可以通过任意数量的URL缩短服务取消递交URL,同时在重定向循环中正确地失败。
本教程讨论了如何使用Apache HttpClient 扩展java中的短URL。
我们从一个简单的用例开始,只使用一次缩短的URL,然后实现一个更通用的机制,能够处理多个重定向级别并检测流程中的重定向循环。
https://www.leftso.com/article/397.html