【问题标题】:Android Apache HttpClient calls response interceptor with incorrect HttpContextAndroid Apache HttpClient 使用不正确的 HttpContext 调用响应拦截器
【发布时间】:2014-10-24 03:09:25
【问题描述】:

我在我的 Android 应用中使用 "com.loopj.android:android-async-http:1.4.5"。设置是每个 API 端点都有一个以下 HttpDataSource 类的实例(例如:http://myhost.com/some/service/{pathParam});因此有多个 AsyncHttpClient 实例(以及 Apache HttpClient);这可能会导致我的问题。

import java.io.IOException;
import java.net.URI;

import android.util.Log;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;

public class HttpDataSource {
  private final AsyncHttpClient asyncHttpClient;

  public HttpDataSource() {
    asyncHttpClient = new AsyncHttpClient();
    asyncHttpClient.setUserAgent(UserAgentFactory.createUserAgent());
    asyncHttpClient.setEnableRedirects(true);

    addRedirectListener();
  }

  protected void get(final String url, final RequestParams requestParams, final HttpResponseHandler responseHandler) {
    // Method not important; constructs headers for conditional GETs
    final Header[] headers = checkForMetaData(url);

    asyncHttpClient.get(null, url, headers, requestParams, new AsyncHttpResponseHandler() {
      @Override
      public void onSuccess(final int statusCode, final Header[] headers, final byte[] responseBody) {
        // we do some work then pass on to the responseHandler
        responseHandler.onSuccess(statusCode, headers, responseBody);
      }

      @Override
      public void onFailure(final int statusCode, final Header[] headers, final byte[] responseBody,
          final Throwable error) {
        // we do some work then pass on to the responseHandler
        responseHandler.onFailure(statusCode, headers, responseBody, error);
      }
    });
  }

  private void addRedirectListener() {
    getHttpClient().addResponseInterceptor(new HttpResponseInterceptor() {
      @Override
      public void process(final HttpResponse httpResponse, final HttpContext httpContext)
          throws HttpException, IOException {
        if (httpResponse.getStatusLine().getStatusCode() == 302) {
          final URI reqUri = ((HttpUriRequest) httpContext.getAttribute(ExecutionContext.HTTP_REQUEST)).getURI();
          final HttpHost currentHost = (HttpHost) httpContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);

          final String url = (reqUri.isAbsolute()) ? reqUri.toString() : (currentHost.toURI() + reqUri.getPath());

          Log.e("HttpDataSource", "Got 302 for '" + url + "'");
        }
      }
    });
  }

  private DefaultHttpClient getHttpClient() {
    return ((DefaultHttpClient) asyncHttpClient.getHttpClient());
  }
}

当我对不同的 URL(例如:http://myhost.com/some/service/barhttp://myhost.com/some/service/foo)进行并发 GET 时,重定向侦听器会触发两次,但使用相同的 HttpContext 对象,我认为这是错误的。日志是:

HttpDataSource﹕ Got 302 for 'http://myhost.com/some/service/foo'
HttpDataSource﹕ Got 302 for 'http://myhost.com/some/service/foo'

我怀疑问题出在 Apache HttpClient,而不是 Loop4J 的 AsyncHttpClient,因为 AsyncHttpClient 有一个 HttpClient 实例,您希望它是“实例安全的”。

当并发请求被触发时,如何为返回 302 的 URL 获取正确的 HttpContext 对象?

【问题讨论】:

    标签: android apache-httpclient-4.x android-async-http


    【解决方案1】:
    client.setEnableRedirects(true);
    

    【讨论】:

    • 代码清单中没有名为“client”的变量。在 HttpDataSource 构造函数中,还为 Apache HTTP 客户端实例启用了启用重定向。
    • YourClinent.getClient().setEnableRedirects(true);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-20
    • 2012-06-22
    • 2014-12-10
    • 1970-01-01
    • 2017-10-24
    相关资源
    最近更新 更多