web-dev-qa-db-ja.com

Flutter-POSTリクエストでステータスコード302を処理する

FlutterでpostリクエストをDIOパッケージで送信しようとしています。

これがリクエストです:

getSessionId() async {

  var csrf = await getCsrftoken();

  var dio = new Dio(new Options(
      baseUrl: "http://xxxxxxx/accounts/login/",
      connectTimeout: 5000,
      receiveTimeout: 100000,
      // 5s
      headers: {
        'Cookie': "csrftoken=" + csrf
      },
      contentType: ContentType.JSON,
      // Transform the response data to a String encoded with UTF8.
      // The default value is [ResponseType.JSON].
      responseType: ResponseType.PLAIN
  ));

  var response;
  response = await dio.post("http://xxxxxxx/accounts/login/",
    data: {
      "username": "xxxxx",
      "password": "xxxxx",
      "csrfmiddlewaretoken" : csrf
    },
    options: new Options(
        contentType: ContentType.parse("application/x-www-form-urlencoded")),
  );

  print("StatusCode: ");
  print(response.statusCode);
  print("Response cookie: ");   //THESE ARE NOT PRINTED
  print(response.headers);
}

リクエストの後、私は次のようになります:

E/flutter ( 4567): [ERROR:flutter/Shell/common/Shell.cc(181)] Dart Error: Unhandled exception:
    E/flutter ( 4567): DioError [DioErrorType.RESPONSE]: Http status error [302]
    E/flutter ( 4567): #0      getSessionId (file:///C:/get_order/lib/main.Dart:36:14)
    E/flutter ( 4567): <asynchronous suspension>

このリクエストから、sessionid Cookieを取得するだけで済みますが、関数は未処理の例外で停止します。

4
Dev9977

私はこのように解決しました:

_followRedirects: false_およびvalidateStatus: (status) { return status < 500;}をリクエストに追加します。このような:

_var response = await Dio().post("http://myurl",
    options: Options(
        followRedirects: false,
        validateStatus: (status) { return status < 500; }
    ),
);
_

このようにして、_302_ headersなどから取得できます。

8
Dev9977

応答コードが303でない限り、Dart HTTPクライアントはPOSTに対して リダイレクトに従う を行いません。GETまたはHEADの場合は302リダイレクトに従います。

(おそらく)有効なログイン要求に応答してリダイレクトを送信するサーバーを停止し、代わりに200を送信できるかどうかを確認できます。

または、フォームフィールドをURLにエンコードして、ログインリクエストをGETとして送信してみることもできます。次に例を示します。

http://xxxxxxx/accounts/login/?username=xxxx&password=yyyy&csrfmiddlewaretoken=zzzz

パラメータに特殊文字をURLエンコードする必要があります。おそらく、あなたもHTTPSを使いたくなるでしょう。

最後に、URLの末尾は/ですか? /accounts/loginを試す価値があるかもしれません。

3
Richard Heap

302のリダイレクトは、GETまたはHEADリクエストに応答して行われますが、POSTに対しては行われません。サーバーがPOSTに応答して302を送信する場合があります)この場合、Dioがキャッチできる例外をスローします。サーバーのステータスコードが302かどうか、または別のエラーかどうかを確認してください。

try{
    await dio.post( _urlLogin,
      data:{...},
      options: Options(
        contentType: ContentType.parse("application/x-www-form-urlencoded"),          
      )
  );
}on DioError catch(error){
    if(error.response.statusCode == 302){
    // do your stuff here
     }
1
Piotr Temp

私の場合、この問題はpostメソッドのヘッダー付きのcookieを送信することで解決されました

問題は、APIがJSONデータではなくHTMLログインページを使用して私に応答していたことです。

また、si/logを実行すると、応答ヘッダーにcookieキーが表示されます-

とステータスエラーコードは302でした

0
YahYa