【问题标题】:Android volley to handle redirectAndroid volley 处理重定向
【发布时间】:2013-07-03 03:33:44
【问题描述】:

我最近开始使用 Google 的 Volley lib 来处理我的网络请求。我的一个请求收到错误 301 进行重定向,所以我的问题是可以自动以某种方式凌空处理重定向,还是我必须在 parseNetworkError 中手动处理它或使用某种 RetryPolicyhere?

谢谢。

【问题讨论】:

  • 如果您对相反的情况感兴趣(不希望 volley 自动处理重定向),请查看stackoverflow.com/a/25887160/369317
  • 谢谢@DenisKniazhev!这正是我在谷歌上搜索的内容:D

标签: android android-volley


【解决方案1】:

像这样替换你的网址 url.replace("http", "https");

例如: 如果您的网址看起来像这样:“http://graph.facebook.......” 应该是这样的:“https://graph.facebook.......”

对我有用

【讨论】:

  • 在 stackoverflow 中说非英语不好。但是“Kime ne amk?”。
  • 哈哈......这就像一个魅力!我在另一个项目中遇到了与 HttpURLConnection 类似的问题。同样的修复也适用于此。
  • 这是题外话。服务器甚至可能不提供 SSL。这是一次性的推测,碰巧奏效了。
【解决方案2】:

我修复了它捕获 http 状态 301 或 302、读取重定向 url 并将其设置为请求然后抛出触发重试的期望。

编辑:这是我修改的 volley lib 中的主要键:

  • 为类Request添加了方法public void setUrl(final String url)

  • 在 BasicNetwork 类中添加了 // 处理缓存验证 if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY) || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) 之后的重定向检查,在那里我使用 responseHeaders.get("location") 读取重定向 url,使用请求对象调用 setUrl 并抛出错误

  • 错误获取被捕获并调用attemptRetryOnException

  • 您还需要为Request 设置RetryPolicy(参见DefaultRetryPolicy

【讨论】:

  • 您是否为此修改了 Volley 源代码,或者 API 是否已经支持它?请为遇到相同问题的其他人分享代码示例
  • 我编辑了我的答案以向他们展示重定向的关键点。
  • 请参阅github.com/samkirton/android-volley 以获得带有重定向修复的截击分叉。
  • 非常感谢您的解释和源代码,因为我没有发现任何其他工作。我的问题出在 NetworkImageView 上,而您的答案解决了一切
  • responseHeaders.get("Location") 不是 responseHeaders.get("location")
【解决方案3】:

如果您不想修改 Volley 库,您可以捕获 301 并手动重新发送请求。

在您的 GsonRequest 类中实现 DeliverError 并使用标头中的新 Location url 创建一个新的 Request 对象,并将其插入到请求队列中。

类似这样的:

@Override
public void deliverError(final VolleyError error) {
    Log.d(TAG, "deliverError");

    final int status = error.networkResponse.statusCode;
    // Handle 30x 
    if(HttpURLConnection.HTTP_MOVED_PERM == status || status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_SEE_OTHER) {
        final String location = error.networkResponse.headers.get("Location");
        Log.d(TAG, "Location: " + location);
        final GsonRequest<T> request = new GsonRequest<T>(method, location, jsonRequest, this.requestContentType, this.clazz, this.ttl, this.listener, this.errorListener);
        // Construct a request clone and change the url to redirect location.
        RequestManager.getRequestQueue().add(request);
    }
}

这样您就可以不断更新 Volley,而不必担心出现问题。

【讨论】:

  • 谢谢,您节省了我的时间。
【解决方案4】:

和许多其他人一样,我只是对为什么 Volley 没有自动跟踪重定向感到困惑。通过查看源代码,我发现虽然 Volley 会自行正确设置重定向 URL,但它实际上不会遵循它,除非请求的重试策略指定“重试”至少一次。莫名其妙地,默认重试策略将maxNumRetries 设置为 0。因此解决方法是设置重试策略,重试 1 次(从默认值复制 10 秒超时和 1 倍回退):

request.setRetryPolicy(new DefaultRetryPolicy(10000, 1, 1.0f))

供参考,这里是源代码:

/**
 * Constructs a new retry policy.
 * @param initialTimeoutMs The initial timeout for the policy.
 * @param maxNumRetries The maximum number of retries.
 * @param backoffMultiplier Backoff multiplier for the policy.
 */
public DefaultRetryPolicy(int initialTimeoutMs, int maxNumRetries, float backoffMultiplier) {
    mCurrentTimeoutMs = initialTimeoutMs;
    mMaxNumRetries = maxNumRetries;
    mBackoffMultiplier = backoffMultiplier;
}

或者,您可以创建 RetryPolicy 的自定义实现,仅在出现 301 或 302 时“重试”。

希望这对某人有所帮助!

【讨论】:

  • 仅供参考:默认重试策略设置为 0 以“防止一些潜在问题”:github.com/mcxiaoke/android-volley/commit/…
  • FYI FYI,重定向不起作用的另一个可能线索是官方上游回购中的这个“最近”(2015/12/04)修复,显然没有进入非官方下游 github 镜像回购:android.googlesource.com/platform/frameworks/volley/+/…
  • 恕我直言,请注意 request.setRetryPolicy(new DefaultRetryPolicy(10000, 1, 1.0f));不会神奇地处理重定向。创建自定义实现是解决问题的一半,在这种情况下没有显示错误处理。
【解决方案5】:

Volley 支持重定向,无需任何补丁,无需单独的分叉

说明: Volley 内部使用HttpClient,除非另有说明,否则默认情况下遵循 301/302

发件人:http://hc.apache.org/httpcomponents-client-4.2.x/tutorial/html/httpagent.html

ClientPNames.HANDLE_REDIRECTS='http.protocol.handle-redirects':定义是否应自动处理重定向。此参数需要 java.lang.Boolean 类型的值。如果未设置此参数,HttpClient 将自动处理重定向。

【讨论】:

  • 对我来说,它会自动处理一些,但有些会报告意外响应 302 并失败。
  • 'Volley 内部使用 HttpClient' - 这不准确,它仅在 API
  • 我在 Lollipop 和最新的 Volley 上,我收到“BasicNetwork.performRequest: Unexpected response code 301 for ...”。所以有些东西不起作用。我可以在 Request.deliverError 中处理这个问题,但我希望它是透明的。
  • HttpURLConnection的follow redirect只是一个指标,实际上它并不能帮助你做“真正的”http重定向,你还是需要手动处理。
【解决方案6】:

最后合并@niko 和@slott 回答的大部分内容:

// Request impl class
// ...

    @Override
    public void deliverError(VolleyError error) {
        super.deliverError(error);

        Log.e(TAG, error.getMessage(), error);

        final int status = error.networkResponse.statusCode;
        // Handle 30x
        if (status == HttpURLConnection.HTTP_MOVED_PERM ||
                status == HttpURLConnection.HTTP_MOVED_TEMP ||
                status == HttpURLConnection.HTTP_SEE_OTHER) {
            final String location = error.networkResponse.headers.get("Location");
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "Location: " + location);
            }
            // TODO: create new request with new location
            // TODO: enqueue new request
        }
    }

    @Override
    public String getUrl() {
        String url = super.getUrl();

        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            url = "http://" + url; // use http by default
        }

        return url;
    }

它很好地覆盖了StringRequest 方法。

希望它可以帮助某人。

【讨论】:

    【解决方案7】:

    好的,我在这里玩游戏有点晚了,但我最近一直在尝试实现相同的方面,所以https://stackoverflow.com/a/17483037/2423312 是最好的,因为你愿意分叉并保持它和答案在这里:https://stackoverflow.com/a/27566737/2423312 - 我不确定这是如何工作的。不过这个是正确的:https://stackoverflow.com/a/28454312/2423312。但它实际上是在NetworkDipatcher 的队列中添加了一个新的请求对象,所以你还必须以某种方式通知调用者,一种肮脏的方式您可以通过不修改请求对象 + 更改字段“mURL”来做到这一点,请注意,这取决于您对 VOLLEY 的RetryPolicy.java 接口的实现以及您的课程如何扩展Request.java 课程,这里是:欢迎反思

    Class volleyRequestClass = request.getClass().getSuperclass();
                            Field urlField = volleyRequestClass.getDeclaredField("mUrl");
                            urlField.setAccessible(true);
                            urlField.set(request, newRedirectURL);
    

    我个人更喜欢克隆凌空。 Plus 看起来像 volley 的示例 BasicNetwork 类被设计为在重定向失败:https://github.com/google/volley/blob/ddfb86659df59e7293df9277da216d73c34aa800/src/test/java/com/android/volley/toolbox/BasicNetworkTest.java#L156 所以我想他们并没有过多地依赖重定向,请随时建议/编辑。一直在寻找好方法..

    【讨论】:

      【解决方案8】:

      我正在使用带有 https url 的 volley:1.1.1,尽管请求存在一些问题。在深入挖掘时,我发现我的请求方法由于重定向(永久重定向 301)而从 POST 更改为 GET。我正在使用 nginx 并且在服务器块中我有一个导致问题的重写规则。

      总之,最新版本的 volley 看起来一切都很好。我的实用函数在这里-

      public void makePostRequest(String url, JSONObject body, final AjaxCallback ajaxCallback) {
          try {
              JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,
                      url, body, new Response.Listener<JSONObject>() {
      
                  @Override
                  public void onResponse(JSONObject response) {
                      Log.d(LOG, response.toString());
                      ajaxCallback.onSuccess(response);
                  }
              }, new Response.ErrorListener() {
                  @Override
                  public void onErrorResponse(VolleyError error) {
                      Log.e(LOG, error.toString());
                      ajaxCallback.onError(error);
                  }
              });
              singleton.getRequestQueue().add(jsonObjectRequest);
          } catch(Exception e) {
              Log.d(LOG, "Exception makePostRequest");
              e.printStackTrace();
          }
      }
      
      // separate file
      public interface AjaxCallback {
          void onSuccess(JSONObject response);
          void onError(VolleyError error);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-09
        • 2015-10-07
        相关资源
        最近更新 更多