最後のリダイレクトURLをキャプチャする方法 - HttpClientを4
-
12-09-2019 - |
質問
私は、HTML出力を得るためにHTTPGETを呼び出して、むしろ簡単なのHttpClient 4のコードを持っています。 HTMLスクリプトと画像位置とのリターンはすべて(例えば<img src="/images/foo.jpg"/>
)ローカルに設定するので、私は絶対(<img src="http://foo.com/images/foo.jpg"/>
)にこれらを作るためにURLを呼び出す必要がある今、問題が来る - 通話中に1または2 302があるかもしれないので、元のURLがリダイレクトもはやHTMLの場所を反映していません。
どのようにしてもよい(またはしない場合があります)がありますか?
何かを見つけることができませんでした。 -私はHttpGet#getAllHeaders()
とHttpResponse#getAllHeaders()
を見ました。
編集:HttpGet#getURI()
は、元の呼び出し元のアドレスを返します。
解決
それはあなたが呼び出すことによって取得することができ、現在のURLになります。
HttpGet#getURI();
EDIT:あなたがリダイレクトを行っているかについては言及しませんでした。それは、我々は302自分自身を扱うので、私たちのために働くます。
あなたがDefaultRedirectHandlerを使用しているように、が鳴ります。我々はそれを行うために使用されます。これは、現在のURLを取得するために、種類のトリッキーです。あなたはあなた自身のコンテキストを使用する必要があります。ここでは、関連するコードスニペットがある、
HttpGet httpget = new HttpGet(url);
HttpContext context = new BasicHttpContext();
HttpResponse response = httpClient.execute(httpget, context);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
throw new IOException(response.getStatusLine().toString());
HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute(
ExecutionContext.HTTP_REQUEST);
HttpHost currentHost = (HttpHost) context.getAttribute(
ExecutionContext.HTTP_TARGET_HOST);
String currentUrl = (currentReq.getURI().isAbsolute()) ? currentReq.getURI().toString() : (currentHost.toURI() + currentReq.getURI());
デフォルトのリダイレクトが私たちのために動作しませんでしたので、私たちは変わったが、私は問題が何であったか忘れてしまっています。
他のヒント
LaxRedirectStrategy
またはDefaultRedirectStrategy
の任意のサブクラスを使用している場合は、のHttpClient 4で、これは推奨される方法(DefaultRedirectStrategy
のソースコードを参照してください)
HttpContext context = new BasicHttpContext();
HttpResult<T> result = client.execute(request, handler, context);
URI finalUrl = request.getURI();
RedirectLocations locations = (RedirectLocations) context.getAttribute(DefaultRedirectStrategy.REDIRECT_LOCATIONS);
if (locations != null) {
finalUrl = locations.getAll().get(locations.getAll().size() - 1);
}
HttpClientを4.3.xので、上記のコードは次のように簡略化することができる。
HttpClientContext context = HttpClientContext.create();
HttpResult<T> result = client.execute(request, handler, context);
URI finalUrl = request.getURI();
List<URI> locations = context.getRedirectLocations();
if (locations != null) {
finalUrl = locations.get(locations.size() - 1);
}
HttpGet httpGet = new HttpHead("<put your URL here>");
HttpClient httpClient = HttpClients.createDefault();
HttpClientContext context = HttpClientContext.create();
httpClient.execute(httpGet, context);
List<URI> redirectURIs = context.getRedirectLocations();
if (redirectURIs != null && !redirectURIs.isEmpty()) {
for (URI redirectURI : redirectURIs) {
System.out.println("Redirect URI: " + redirectURI);
}
URI finalURI = redirectURIs.get(redirectURIs.size() - 1);
}
私見を方法ZZコーダの溶液に基づく改良は、単に最後のリダイレクト位置を追跡するResponseInterceptorを使用することです。あなたは、例えば情報を失うことはありませんその方法ハッシュタグの後。応答インターセプタがなければ、あなたはハッシュタグを失います。例: http://j.mp/OxbI23する
private static HttpClient createHttpClient() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManager[] trustAllCerts = new TrustManager[] { new TrustAllTrustManager() };
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("https", 443, sslSocketFactory));
schemeRegistry.register(new Scheme("http", 80, new PlainSocketFactory()));
HttpParams params = new BasicHttpParams();
ClientConnectionManager cm = new org.apache.http.impl.conn.SingleClientConnManager(schemeRegistry);
// some pages require a user agent
AbstractHttpClient httpClient = new DefaultHttpClient(cm, params);
HttpProtocolParams.setUserAgent(httpClient.getParams(), "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1");
httpClient.setRedirectStrategy(new RedirectStrategy());
httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
@Override
public void process(HttpResponse response, HttpContext context)
throws HttpException, IOException {
if (response.containsHeader("Location")) {
Header[] locations = response.getHeaders("Location");
if (locations.length > 0)
context.setAttribute(LAST_REDIRECT_URL, locations[0].getValue());
}
}
});
return httpClient;
}
private String getUrlAfterRedirects(HttpContext context) {
String lastRedirectUrl = (String) context.getAttribute(LAST_REDIRECT_URL);
if (lastRedirectUrl != null)
return lastRedirectUrl;
else {
HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
HttpHost currentHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
String currentUrl = (currentReq.getURI().isAbsolute()) ? currentReq.getURI().toString() : (currentHost.toURI() + currentReq.getURI());
return currentUrl;
}
}
public static final String LAST_REDIRECT_URL = "last_redirect_url";
ちょうどZZコーダーの解決策のようにそれを使用します:
HttpResponse response = httpClient.execute(httpGet, context);
String url = getUrlAfterRedirects(context);
私は最後のURLを見つけるための簡単な方法は、DefaultRedirectHandlerを使用することだと思います。
package ru.test.test;
import java.net.URI;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.impl.client.DefaultRedirectHandler;
import org.apache.http.protocol.HttpContext;
public class MyRedirectHandler extends DefaultRedirectHandler {
public URI lastRedirectedUri;
@Override
public boolean isRedirectRequested(HttpResponse response, HttpContext context) {
return super.isRedirectRequested(response, context);
}
@Override
public URI getLocationURI(HttpResponse response, HttpContext context)
throws ProtocolException {
lastRedirectedUri = super.getLocationURI(response, context);
return lastRedirectedUri;
}
}
コードは、このハンドラを使用します。
DefaultHttpClient httpclient = new DefaultHttpClient();
MyRedirectHandler handler = new MyRedirectHandler();
httpclient.setRedirectHandler(handler);
HttpGet get = new HttpGet(url);
HttpResponse response = httpclient.execute(get);
HttpEntity entity = response.getEntity();
lastUrl = url;
if(handler.lastRedirectedUri != null){
lastUrl = handler.lastRedirectedUri.toString();
}
バージョン2.3でアンドロイドはまだ以下リダイレクト(HTTPコード302)をサポートしていません。私はちょうど場所のヘッダを読み、もう一度ダウンロードします:
if (statusCode != HttpStatus.SC_OK) {
Header[] headers = response.getHeaders("Location");
if (headers != null && headers.length != 0) {
String newUrl = headers[headers.length - 1].getValue();
// call again the same downloading method with new URL
return downloadBitmap(newUrl);
} else {
return null;
}
}
いいえ円はここに保護をリダイレクトしませんので注意してください。もっと上のブログによる 302はAndroidHttpClientする にリダイレクトフォローP>
これは私がリダイレクトURLを取得するために管理する方法です。
Header[] arr = httpResponse.getHeaders("Location");
for (Header head : arr){
String whatever = arr.getValue();
}
それとも、あなたが唯一のリダイレクト先があることを確信している場合は、次の操作を行います。
httpResponse.getFirstHeader("Location").getValue();