Home > Back-end >  API call to Flask API works from Postman and fails from Flutter
API call to Flask API works from Postman and fails from Flutter

Time:10-02

EDIT: Posted fix in comments below- was using Postman incorrectly

The call works successfully in postman, but fails from my flutter application. In postman, I include the following key, value in "Body"

key: dirty

Value:

{"Roster":[],"Athlete":[{"AthleteID":"cac8396a-d83e-4c0c-b8b4-97a0b3fdd65a","FirstName":"Dom","LastName":"Aluise","Alias":"","Height":null,"Weight":null,"BDay":null,"AccountID":"4771ac0d-2959-4abd-9ae1-52e29b6016e6","Updated":1632947536476,"Dirty":1},"Trial":[]}

However the call fails when trying to make the call with Dart, once it reaches my flask API, the quotation marks inside "value" all become single quotes, and thus doing "Json.loads" on the "dirty" argument fails. Here is how I call the API from flutter:

 Uri uri = Uri.parse('https://'   apiUrl   '/api/v1/'   endpoint);
    print(queryParameters);
    //final uri = Uri.https(apiUrl, '/api/v1/$endpoint', queryParameters);
    final response = await http.post(uri,
        headers: {
          HttpHeaders.authorizationHeader: 'bearer $accessToken',
          HttpHeaders.contentTypeHeader: 'application/json',
        },
        body: json.encode(queryParameters));

Where queryParameters is a map<String, dynamic> like: {"dirty" : {"Roster": [], .....} containing all the above value data.

What do I need to do instead to make sure that the body is being successfully transferred to the flask API? In python, my argument is defined as:

        self.parser.add_argument("dirty", type=str, help="JSON encoded dirty records from local database")

I assume it is a Flutter problem because the request works through postman. Thank you

CodePudding user response:

Ran a test, wasn't able to repro, but here is what I did, maybe it will help.

Here is my Python server, that receives the request:

import json
from http.server import BaseHTTPRequestHandler, HTTPServer

class CustomServer(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        jsondata = json.loads(post_data)
        print(f"received ({content_length} b):\n\n", json.dumps(jsondata, indent=4))

        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        jsonanswer = json.dumps({"status": "success"})

        self.wfile.write(jsonanswer.encode())

def run():
    httpd = HTTPServer(('', 8080), CustomServer)
    print('Starting server...\n')
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    print('Stopping server...\n')
    httpd.server_close()

if __name__ == '__main__':
    run()

and here is my dart code that makes the request to that python server above:

import 'dart:convert';
import 'package:http/http.dart' as http;

void main(List<String> arguments) async {
  var data = {
    "dirty": {
      "Roster": [],
      "Athlete": [
        {
          "AthleteID": "cac8396a-d83e-4c0c-b8b4-97a0b3fdd65a",
          "FirstName": "Dom",
          "LastName": "Aluise",
          "Alias": "",
          "Height": null,
          "Weight": null,
          "BDay": null,
          "AccountID": "4771ac0d-2959-4abd-9ae1-52e29b6016e6",
          "Updated": 1632947536476,
          "Dirty": 1
        },
      ],
      "Trial": []
    }
  };

  var resp = await http.post(Uri.parse('http://127.0.0.1:8080'),
      headers: {
        'Content-Type': 'application/json',
      },
      body: jsonEncode(data));

  print(resp.body);
}

Below is the output for the python server:

$ python3 main.py

Starting server...

received (273 b):

 {
    "dirty": {
        "Roster": [],
        "Athlete": [
            {
                "AthleteID": "cac8396a-d83e-4c0c-b8b4-97a0b3fdd65a",
                "FirstName": "Dom",
                "LastName": "Aluise",
                "Alias": "",
                "Height": null,
                "Weight": null,
                "BDay": null,
                "AccountID": "4771ac0d-2959-4abd-9ae1-52e29b6016e6",
                "Updated": 1632947536476,
                "Dirty": 1
            }
        ],
        "Trial": []
    }
}
127.0.0.1 - - [01/Oct/2021 11:05:49] "POST / HTTP/1.1" 200 -

^CStopping server...

And lastly, the output from the dart code:

$ dart run
{"status": "success"}

CodePudding user response:

I was making a dumb mistake, but I'll leave the post here in case anyone runs into this: I was incorrectly using Postman: I was putting my arguments into Body "form-data" instead of body "raw". This was falsely validating the API working. My solution was to change the request parser as such:

self.parser.add_argument("last_sync", type=int, location='json', help="Last sync of database in milliseconds since epoch")
        
self.parser.add_argument("dirty", type=dict, location='json', help="JSON encoded dirty records from local database")

And simply access it as

args = self.parser.parse_args()
args['dirty'] ....

This would automatically decode the JSON body so I did not need to do any JSON.loads manually. Thank you for the help guys.

  • Related