Search code examples
flutterdartpostpostmanx-www-form-urlencoded

How to POST to google form by Flutter. The response is always 400 (POSTMAN'S result is 200 OK)


I tried to POST to google form with flutter, but the response is always 400. When I use POSTMAN, it succeeds. I cannot understand why it fails with flutter.

I tried http package and dio package, but the result is always 400. What is the problem? If there is a suggestion for solving this, please tell me.

The code I tried is as follows.

  1. http package (http: ^0.12.2)
void _request() async {
    String url =
        'https://docs.google.com/forms/u/0/d/e/1FAIpQLSc5aAwiiLJ2qJhF-ngGFfRl8m8yEJs8gTipY7pnNQkxGcJ_1w/formResponse';

    Map<String, String> headers = {
      "Content-Type": "application/x-www-form-urlencoded",
    };
    String body = json.encode(
      {
        'entry.844954850': 'bug',
        'entry.479013015': 'dsfa',
      },
    );
    http.Response resp = await http.post(url, headers: headers, body: body);
    if (resp.statusCode != 200) {
      print('Failed to post ${resp.statusCode}');
    } else {
      print(resp.body);
    }
  }

The result is

I/flutter ( 5834): Failed to post 400
  1. Dio package (dio: ^3.0.10)
Future _request_dio() async {
    final dio = Dio();
    final url =
        'https://docs.google.com/forms/u/0/d/e/1FAIpQLSc5aAwiiLJ2qJhF-ngGFfRl8m8yEJs8gTipY7pnNQkxGcJ_1w/formResponse';

    String body = json.encode(
      {
        'entry.844954850': 'bug',
        'entry.479013015': 'dsfa',
      },
    );

    var data = await dio
        .post(
      url,
      data: body,
      options: Options(contentType: Headers.formUrlEncodedContentType),
    )
        .then((response) {
      print(response.data);
      return response.data;
    }).catchError((err) {
      print(err);
      return null;
    });
  }

The result is

I/flutter ( 5834): DioError [DioErrorType.RESPONSE]: Http status error [400]

When I use POSTMAN and succeeded, following HTTP codes are used in POSTMAN.

POST /forms/u/0/d/e/1FAIpQLSc5aAwiiLJ2qJhF-ngGFfRl8m8yEJs8gTipY7pnNQkxGcJ_1w/formResponse HTTP/1.1
Host: docs.google.com
Content-Type: application/x-www-form-urlencoded
Cookie: S=spreadsheet_forms=yClaqeCIC2953sdlxK8fzZb97ycQG4UFviYCNtUBFtg; NID=204=vu3hzpnGl1iqwJCJgR_bPkjmqdx4uvEQYIfxgZWm9sc6KJjoOSZDFpMrSn0AtlmqjJeFb0JkX6MJnpIHtYXgXebI7CbKJy4JI_1hOfFe8fiMjM6qEbKw4BhNjaDzHyKTk6uoU4mpG34i01A2rEbch7xCs6Z_cvwfPhNvFWH_xGI

entry.844954850=bug&entry.479013015=fsda

The flutter doctor's result is

C:\src\flutter\bin\flutter.bat doctor --verbose
[√] Flutter (Channel stable, 1.20.4, on Microsoft Windows [Version 10.0.18363.1082], locale ja-JP)
    • Flutter version 1.20.4 at C:\src\flutter
    • Framework revision fba99f6cf9 (5 days ago), 2020-09-14 15:32:52 -0700
    • Engine revision d1bc06f032
    • Dart version 2.9.2

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at C:\Users\user\AppData\Local\Android\sdk
    • Platform android-30, build-tools 30.0.1
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    • All Android licenses accepted.

[√] Android Studio (version 4.0)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 48.1.2
    • Dart plugin version 193.7547
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)


Solution

  • After reproduce your case in Postman with form-data: postman

    and for control, i'm using curl for testing :

    curl --location --request POST 'https://docs.google.com/forms/u/0/d/e/1FAIpQLSc5aAwiiLJ2qJhF-ngGFfRl8m8yEJs8gTipY7pnNQkxGcJ_1w/formResponse' \
        --form 'entry.844954850=bug' \
        --form 'entry.479013015=dsfa'
    

    now i can reproduce this Post request in flutter:

    void _request() async {
      String url =
          'https://docs.google.com/forms/u/0/d/e/1FAIpQLSc5aAwiiLJ2qJhF-ngGFfRl8m8yEJs8gTipY7pnNQkxGcJ_1w/formResponse';
    
      Map<String, String> headers = {
        "Content-Type": "application/x-www-form-urlencoded",
      };
      // String body = json.encode(...)      //------------> Before
      Map<String, String> requestBody = <String, String>{ // After
        'entry.844954850': 'bug',
        'entry.479013015': 'dsfa'
      };
    
      http.Response resp =
          await http.post(url, headers: headers, body: requestBody);
      print(resp);
      if (resp.statusCode != 200) {
        print('Failed to post ${resp.statusCode}');
      } else {
        print(resp.body);
      }
    }
    

    status code in debug mode:

    result

    For dio, it's same replace json and your request is formatted correctly.