web-dev-qa-db-ja.com

Androidリダイレクトを処理するボレー

最近、ネットワークリクエストにGoogleのVolley libを使用し始めました。私のリクエストの1つはリダイレクトでエラー301を受け取りますので、私の質問はリダイレクトをなんとか自動で処理できるか、parseNetworkErrorで手動で処理する必要があるか、何らかの種類のRetryPolicyhereを使用する必要がありますか?

ありがとう。

27
Niko

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を呼び出します

  • RetryPolicyRequestを設定する必要もあります(これについてはDefaultRetryPolicyを参照してください)

21
Niko

Url.replace( "http"、 "https");のようにURLを置き換えます。

たとえば、URLが次のようになっている場合: " http://graph.facebook ......."よりも次のようになります: " https:// graph。 facebook .......」

わたしにはできる

37
Mucahit

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の更新を続けることができ、物事が壊れる心配はありません。

13
slott

他の多くの人と同じように、私はボレーがリダイレクトを自動的に追跡しなかった理由について単に混乱していました。ソースコードを見ると、VolleyはリダイレクトURLを正しく設定しますが、リクエストの再試行ポリシーで少なくとも1回「再試行」を指定しない限り、実際にはリダイレクトURLを追跡しません。不可解なことに、デフォルトの再試行ポリシーはmaxNumRetriesを0に設定します。そのため、1回の再試行(デフォルトから10秒のタイムアウトと1xのバックオフをコピー)で再試行ポリシーを設定します。

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

または、301または302のイベントでのみ「再試行」するRetryPolicyのカスタム実装を作成できます。

これが誰かを助けることを願っています!

6
yuval

Volleyは、パッチなしでリダイレクトをサポートします。別のフォークは不要です

説明:Volleyは内部でHttpClientを使用します。特に指定されない限り、デフォルトでは301/302に従います

From: http://hc.Apache.org/httpcomponents-client-4.2.x/tutorial/html/httpagent.html

ClientPNames.HANDLE_REDIRECTS = 'http.protocol.handle-redirects':リダイレクトを自動的に処理するかどうかを定義します。このパラメーターには、Java.lang.Boolean型の値が必要です。このパラメーターが設定されていない場合、HttpClientはリダイレクトを自動的に処理します。

4
Eugene

oK、ここのゲームには少し遅れていますが、最近この同じ側面を達成しようとしているので、 https://stackoverflow.com/a/17483037/2423312 はあなたがボレーを分岐し、それを維持し、ここで答えを喜んで与えられることを考えると、最高のもの: https://stackoverflow.com/a/27566737/2423312 -私はわからないこれがどのように機能したか。これはスポットです: https://stackoverflow.com/a/28454312/2423312 。しかし、実際にはNetworkDipatcherのキューに新しいリクエストオブジェクトを追加するため、何らかの方法で呼び出し元に通知する必要があります。one dirty wayリクエストオブジェクトを変更せずにこれを行うことができます+フィールド「mURL」を変更します。これはIS DEPENDENT VOLLEY'Sの実装についてRetryPolicy.Javaインターフェイスとクラスの拡張方法Request.Java CLASS ARE、here you go:歓迎の反射

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

個人的には、ボレーのクローンを作成したいです。さらに、ボレーの例BasicNetworkクラスはリダイレクトで失敗するように設計されているようです: https://github.com/google/volley/blob/ddfb86659df59e72​​93df9277da216d73c34aa800/src/test/Java/com/Android /volley/toolbox/BasicNetworkTest.Java#L156 なので、リダイレクトに頼りすぎていると思うので、気軽に提案/編集してください。常に良い方法を探しています。

2
uLYsseus

ほとんどの@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メソッドをオーバーライドしてうまく機能しました。

それが誰にも役立つことを願っています。

1

リクエストに問題がありましたが、https URLでvolley:1.1.1を使用しています。さらに掘り下げると、リダイレクト(永続リダイレクト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);
}
0
Varun Kumar