34

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

谢谢。

4

8 回答 8

35

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

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

这个对我有用

于 2014-12-19T13:01:42.417 回答
21

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

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

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

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

  • 错误被捕获并调用attemptRetryOnException

  • 您还需要RetryPolicy设置Request(see DefaultRetryPolicyfor this)

于 2013-07-05T07:07:35.637 回答
17

如果您不想修改 Volley lib,您可以捕获 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,而不必担心出现问题。

于 2015-02-11T12:25:34.653 回答
7

像许多其他人一样,我只是对为什么 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 事件中“重试”的自定义实现。

希望这对某人有帮助!

于 2016-02-29T23:23:12.727 回答
4

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

说明: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 将自动处理重定向。

于 2014-04-17T18:25:39.600 回答
4

最终合并了大多数@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方法。

希望它可以帮助某人。

于 2017-08-31T04:35:39.813 回答
2

好的,我在这里玩游戏有点晚了,但我最近一直在尝试实现同样的方面,所以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/ddfb86659df59e72​​93df9277da216d73c34aa800/src/test/java/com/android/volley/toolbox/BasicNetworkTest.java#L156所以我猜想他们并没有过多地依赖重定向,请随时建议/编辑。一直在寻找好方法..

于 2017-03-19T01:06:30.657 回答
0

我正在使用带有 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);
}
于 2018-07-31T15:57:13.433 回答