flutterflutter-http

flutter http.post causes the web client to crash


When I attempt a basic http post, I can see that the server is returning a normal 400. But the client seems to just crash with an error I can't make sense of. I have the following code

static Future<TradApiServerResponse> submitPhone(
  String phone, String code) async {
    http.Response response = await http.post(
      Uri.parse("$urlbase/api/submitphone"),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, String>{
        'code': code,
        'phone': phone,
      }),
    );
    if (response.statusCode == 200) {

When stepping trough it never gets to the if statement. It just locks up then crashes. The server is responding. I can curl or use the browser directly and it works fine

Error
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 329:10  createErrorWithStack
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 265:28            _throw
dart-sdk/lib/core/errors.dart 120:5                                           throwWithStackTrace
dart-sdk/lib/async/zone.dart 1386:11                                          callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                              _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                               _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7            <fn>
Application finished.

How can I figure out what the problem is? Sorry I am new to flutter.

when wrapped in a try statement

ClientException: XMLHttpRequest error., uri=http://127.0.0.1/api/submitphone

One thing I noticed when the request is captured over wireshark it is request method "OPTIONS" instead of POST ??

UPDATE: this happens in the most basic version possible

http.Response response = await http.get(Uri.parse("http://127.0.0.1"),);

line crashes even when a 200 is returned. I tested against

python -m http.server 80

There must be something really stupid and obvious I am doing? This is running on the web version using chrom


Solution

  • Thanks to @Richard Heap. The issue was CORS. The docs for what your server need to do are here https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

    a low level python wsgi implementation is shows here so you can see exactly what to do

    def handler(environ, start_response):
        method = environ["REQUEST_METHOD"]
        origin = environ.get("HTTP_ORIGIN")
        cookie = environ.get("HTTP_COOKIE", "N/A")
        
        cors = origin
        preflight = cors and method == "OPTIONS"
    
        headers = [("Content-Type", "text/plain")]
        if cors:
            headers.extend([
                ("Access-Control-Allow-Origin", origin),
                ("Access-Control-Allow-Credentials", "true")
            ])
            if preflight:
                headers.extend([
                    ("Access-Control-Allow-Methods", "POST"),
                    ("Access-Control-Allow-Headers", "Content-Type")
                ])
        else:
            headers.append(("Set-Cookie", "auth=fnd"))
    
        if method == "OPTIONS":
            start_response("204 No Content", headers)
            return []
        else:
            start_response("200 OK", headers)
            return ["Cookie: ", cookie]
    

    Credit https://gist.github.com/FND/204ba41bf6ae485965ef