Android凌空处理重定向

时间:2013-07-05 05:55:08

标签: android android-volley

我最近开始使用Google的Volley lib来处理我的网络请求。我的一个请求获得重定向错误301,所以我的问题是,可以自动地以某种方式自动处理重定向,还是我必须在parseNetworkError中手动处理它,或者在这里使用某种RetryPolicy

感谢。

8 个答案:

答案 0 :(得分:36)

将您的网址替换为url.replace(" http"," https");

例如: 如果您的网址看起来像这样:" http://graph.facebook ......."比 它应该像:" https://graph.facebook ......."

它对我有用

答案 1 :(得分:21)

我修复了它捕获http状态301或302,读取重定向网址并将其设置为请求然后投掷预期触发重试。

编辑:以下是我修改过的volley lib中的主要键:

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

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

  • 错误抓取并调用attemptRetryOnException

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

答案 2 :(得分:13)

如果您不想修改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,而不必担心事情会发生。

答案 3 :(得分:6)

和其他许多人一样,我很担心为什么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的情况下“重试”。

希望这有助于某人!

答案 4 :(得分:4)

Volley支持没有任何补丁的重定向,不需要单独的fork

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

来自:http://hc.apache.org/httpcomponents-client-4.2.x/tutorial/html/httpagent.html

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

答案 5 :(得分:2)

好吧,我在这里游戏有点晚了,但我最近一直试图实现同样的方面,所以https://stackoverflow.com/a/17483037/2423312是最好的,因为你愿意分叉并维持它和答案在这里:https://stackoverflow.com/a/27566737/2423312 - 我不确定这是如何工作的。尽管如此:https://stackoverflow.com/a/28454312/2423312。但它实际上是在NetworkDipatcher的队列中添加了一个新的请求对象,所以你必须以某种方式通知调用者, 一个脏的方式 您可以通过不修改请求对象+更改字段来执行此操作&#34; mURL&#34;,请注意,这与您实施VOLLEY RetryPolicy.java有关界面以及你的课程如何延伸Request.java课程,你走了:欢迎反思

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

就个人而言,我更喜欢克隆凌空。加上看起来像凌空的示例BasicNetwork类被设计为在重定向时失败:https://github.com/google/volley/blob/ddfb86659df59e7293df9277da216d73c34aa800/src/test/java/com/android/volley/toolbox/BasicNetworkTest.java#L156所以我猜他们不会过分依赖重定向,随意建议/编辑。一直在寻找好方法..

答案 6 :(得分:1)

最终合并大多数@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 :(得分:0)

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

所以简而言之,最新版的凌空一切似乎都不错。我的效用函数在这里-

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);
}