Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - Handle status code 302 in POST request

I'm trying to send a post request in Flutter with DIO package.

Here is the request:

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

After the request i get:

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>

From this request i only need to get the sessionid cookie, but the function stop with unhandled exception.

like image 303
Dev9977 Avatar asked Sep 27 '18 12:09

Dev9977


4 Answers

I solved this way:

Add followRedirects: false and validateStatus: (status) { return status < 500;} to the request. Like this:

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

This way you can get from the 302 every headers and other.

like image 141
Dev9977 Avatar answered Nov 09 '22 00:11

Dev9977


i got a similar problem and i solved it with adding header with "Accept":"application/json" . henceforth it will only return json data otherwise it will prompt to redirect with html url.

like image 24
A.K.J.94 Avatar answered Nov 08 '22 23:11

A.K.J.94


The Dart HTTP client won't follow redirects for POSTs unless the response code is 303. It follows 302 redirects for GET or HEAD.

You could see if you can stop the server sending the redirect in response to a (presumably) valid login request, and send a 200 instead.

Or you could try sending the login request as a GET by encoding the form fields into the URL, for example:

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

You would have to URL encode any special characters in the parameters. Presumably, you'll want to use HTTPS too.

Finally, is the URL meant to end with /? It might be worth trying /accounts/login.

like image 6
Richard Heap Avatar answered Nov 08 '22 23:11

Richard Heap


Redirections for 302 are made in response to GET or HEAD requests, never for POST. Sometimes server sends 302 in response to POST (that was in my case). In this case Dio throws exception you can catch - remember to check if server status code is 302 or maybe it's another error.

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
     }
like image 2
Piotr Temp Avatar answered Nov 08 '22 22:11

Piotr Temp