4

Android クライアントが Apache HTTP クライアントを使用してサーバーにリクエストを送信するとき、同じ HTTP メソッドを使用して新しい URL (より具体的には、他のコンテキスト パス) にリダイレクトする必要があります。

httpd.conf で、ステータス コード 307 でこのルールを設定しました。

Redirect    307    /mybipper/reg           /mybipperapi/old/reg

ウィキペディアのステータス コードの説明によると、307 は次のようにする必要があります。

http://en.wikipedia.org/wiki/HTTP_307#3xx_Redirection

307 一時リダイレクト (HTTP/1.1 以降) この場合、別の URI で要求を繰り返す必要があります。ただし、今後のリクエストでは引き続き元の URI を使用できます。[2] 302 が歴史的にどのように実装されたかとは対照的に、元のリクエストを再発行するときにリクエスト メソッドを変更するべきではありません。たとえば、別の POST 要求を使用して POST 要求を繰り返す必要があります。

しかし、私のアクセス ログを見ると、HTTP クライアントはそれを尊重していないようで、ステータス コード 302 を返したかのように代わりに GET を実行しています。

172.29.9.120 - - [21/Sep/2012:14:02:11 +0300] "POST /mybipper/reg HTTP/1.1" 307 248
172.29.9.120 - - [21/Sep/2012:14:02:11 +0300] "GET /mybipperapi/old/reg HTTP/1.1" 400 1016

Apache HTTP クライアントの Web サイトによると、ステータス コード 307 をどのように処理するべきかは少し不明ですが、少なくともそこには記載されています。

http://hc.apache.org/httpclient-3.x/redirects.html

HTTP 1.1 プロトコルを正しく実装していない Apache HTTP クライアントを強く感じています。正しいですか、それとも何か誤解していますか?

私たちが使用する Apache HTTP クライアントは、Android SDK にバンドルされています。私がテストしていた電話には Android SDK 15 がありました。

http://developer.android.com/about/versions/android-4.0.3.html

4

3 に答える 3

4

DefaultRedirectStrategy、GET と HEAD の自動リダイレクトのみを許可します。POST も許可する (PUT や DELETE は許可しない) 場合は、次のLaxRedirectStrategyようにしてに切り替えることができます。

HttpClientBuilder hcb = HttpClients.custom();
hcb.setRedirectStrategy(new LaxRedirectStrategy());
HttpClient client = hcb.build(); 

PUT と DELETE にも従いたい場合 (ここで行っているように)、カスタム戦略を実装する必要があります (注: 2 つ目の Content-Length ヘッダーを追加しようとしているように見える HttpClient のバグに遭遇しました)。これを行うときは、手動で削除します.YMMV)。この戦略を使用することで、HttpClient は 308 リダイレクトもサポートします。これは、Apache チームがわざわざ含めることさえできなかったものです。

次のようなことができます。

hcb.setRedirectStrategy(new DefaultRedirectStrategy() {
        public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
            Args.notNull(request, "HTTP request");
            Args.notNull(response, "HTTP response");
            int statusCode = response.getStatusLine().getStatusCode();
            switch(statusCode) {
            case 301:
            case 307:
            case 302:
            case 308:
            case 303:
                return true;
            case 304:
            case 305:
            case 306:
            default:
                return false;
            }
        }

        public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
            URI uri = this.getLocationURI(request, response, context);
            String method = request.getRequestLine().getMethod();
            if(method.equalsIgnoreCase("HEAD")) {
                return new HttpHead(uri);
            } else if(method.equalsIgnoreCase("GET")) {
                return new HttpGet(uri);
            } else {
                int status = response.getStatusLine().getStatusCode();
                HttpUriRequest toReturn = null;
                if(status == 307 || status == 308) {
                    toReturn = RequestBuilder.copy(request).setUri(uri).build();
                    toReturn.removeHeaders("Content-Length"); //Workaround for an apparent bug in HttpClient
                } else {
                    toReturn = new HttpGet(uri);
                }
                return toReturn;
            }
        }
    });
于 2016-12-05T19:44:57.963 に答える
0

Cody の正解を拡張するには、PUT (またはその他の方法) 307 リダイレクトに従う必要がある場合は、代わりLaxRedirectStrategyにさらに簡単に拡張できます。

hcb.setRedirectStrategy(new LaxRedirectStrategy()
{
    protected boolean isRedirectable(String method)
    {
        return "PUT".equalsIgnoreCase(method)||super.isRedirectable(method);
    }
});

ただし、次の 308 の問題も解決されません。これは古い質問であることは知っていますが、今日も同じ問題に遭遇しました (Cody に感謝します)。

于 2019-04-17T14:17:08.837 に答える