I am working on a Flutter tablet app. Once one input field is inputted, I am trying to send a post request to the server. Following is the method I am invoking for this:
Future < http.Response > _postRequest() async {
print(globals.novaCoord.toString() + ' XYZXYZXYZXYZXYZ');
var url = globals.URL + 'api/nova_position';
Map data = {
'id_nova': '1',
'position.x': '1',
'position.y': '1',
'position.z': '1',
'position.pitch': '1',
'position.yaw': '1',
'position.roll': '1',
};
//encode Map to JSON
var body = json.encode(data);
http.Response response = await http.post(url,
headers: {
"Content-Type": "application/json"
},
body: body
);
print("${response.statusCode}");
print("${response.body}");
return response;
}
And on the NodeJs server side I have this:
app.post('/api/nova_position/', async (req,res) => {
console.log("NOVA POSITION");
console.log(req.body.id_nova);
const id_nova = req.body.id_nova;
const x = req.body.position.x;
const y = req.body.position.y;
const z = req.body.position.z;
const pitch = req.body.position.pitch;
const yaw = req.body.position.yaw;
const roll = req.body.position.roll;
const position = await db.db.create_position(id_nova,x,y,z,pitch,yaw,roll);
});
However, on the server-side, I am receiving an empty "body" for the request I sent and I receive the following error:
(node:23939) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'x' of undefined
I need help at this point. I appreciate any help and guidance.
Sending Map<String,dynamic> with http.post won't send your data properly.
To solve this, change the content-type of the header to:
Map<String, String> customHeaders = {
...
"content-type": "application/json"
...
};
Then, you can use http.post as follows:
http.post(url, headers: customHeaders, body);
You have to jsonEncode before pushing into Post request
Like
String bodyF = jsonEncode(body);
And i hope you will get your solution.
The solution I have found was simply to add Content-Length : x to your header, with x being the size of your json body.
Related
I have to make a post call to upload a image. Getting an error due to the boundary values in the header. (Regex not matched)
var requestUrl = API_URL;
// INITIALIZE MULTIPART REQUEST
http.MultipartRequest request;
// PREPARE HEADER VALUES
request = new http.MultipartRequest("POST", Uri.parse(requestUrl));
Map<String, String> headers = {
'Content-Type': 'multipart/form-data',
'Accept': 'multipart/form-data',
'Authorization': 'Bearer '+accessToken,};
request.headers.addAll(headers);
// DECLARE FILE NAME WEB
String imageType = "image." + this.xfile!.mimeType.toString().split('/').last;
// ADD TO REQUEST
request.files.add(http.MultipartFile.fromBytes('image', await this.xfile!.readAsBytes(), filename:imageType ));
// SEND REQUEST
http.StreamedResponse responseAttachmentSTR = await request.send();
I deployed the codes to the server. Apparently this causes a 403 Forbidden error, when I try to upload an image.
Through debugging, it was because of the regex in the Header (Boundary):
boundary=dart-http-boundary-poYEiL0Ungmxkla.2lkZeC6Mub.-Fupw5T_MmJpxColFVjXf-qr
What can I do about this?
edit: I found the solution and answered the question.
I'm trying POST to Instagram's API in my app. The POST works fine in Postman, but in my flutter code I always get a error response: {error_type: OAuthException, code: 400, error_message: Invalid platform app} . I must be doing something wrong in my flutter POST but I can't figure out what.
Here is my Postman POST (that works every time) along with the correct body response:
And here is my Dart/Flutter code that gives me the error:
var clientID = '708XXXXXXXX';
var clientSecret = '37520XXXXXXXXXXXXX';
var grantType = 'authorization_code';
var rediUrl = 'https://httpstat.us/200';
var urlTwo = 'https://api.instagram.com/oauth/access_token';
var body = json.encode({
'client_id': clientID,
'client_secret': clientSecret,
'grant_type': grantType,
'redirect_uri': rediUrl,
'code': _accessCode
});
print('Body: $body');
var response = await http.post(urlTwo,
headers: {
'Accept': '*/*',
'Content-Type': 'application/json',
},
body: body,
);
print(json.decode(response.body));
I read about the error on a different thread and they say to post as x-www-formurlencoded.. When I switch the Content-Type to this, I get the same error.
The error I get in Flutter:
{error_type: OAuthException, code: 400, error_message: Invalid platform app}
I triple checked and I am using all the same value in Postman and Flutter. I've tried the values as Strings and numbers.
When I print body:
Body: {"client_id":"70000edited","client_secret":"37520634edited","grant_type":"authorization_code","redirect_uri":"https://httpstat.us/200","code":"AQCs-H3cIU0aF1o2KkltLuTmVMmJ-WJnZIhb9ryMqYedited"}
try this once
final response = await http.post(urlTwo,
body: body,
headers: {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
encoding: Encoding.getByName("utf-8"));
I've finally got it working using a Map. Which is weird because other attempts I also used a map (I've been trying numerous stack overflow answers). Anyways, here is the working code I used:
var urlTwo = 'https://api.instagram.com/oauth/access_token';
var clientID = '7080000';
var clientSecret = '375XXXXXX';
var grantType = 'authorization_code';
var rediUrl = 'https://httpstat.us/200';
var map = new Map<String, dynamic>();
map['client_id'] = clientID;
map['client_secret'] = clientSecret;
map['grant_type'] = grantType;
map['redirect_uri'] = rediUrl;
map['code'] = _accessCode;
http.Response response = await http.post(
urlTwo,
body: map,
);
var respData = json.decode(response.body);
print(respData);
I am using http client for flutter network call.
My request working on postman getting response properly,
But while trying with http.post it returns error code 307-Temporary Redirect,
Method Body:
static Future<http.Response> httpPost(
Map postParam, String serviceURL) async {
Map tempParam = {"id": "username", "pwd": "password"};
var param = json.encode(tempParam);
serviceURL = "http:xxxx/Login/Login";
// temp check
Map<String, String> headers = {
'Content-Type': 'application/json',
'cache-control': 'no-cache',
};
await http.post(serviceURL, headers: headers, body: param).then((response) {
return response;
});
}
Also, the same code returns a proper response to other requests and URLs.
First I trying with chopper client but had same issue.
I am unable to detect that issue from my end of from server-side.
Any help/hint will be helpful
Try to put a slash / at the end of the serviceUrl. So, serviceUrl is serviceURL = "http:xxxx/Login/Login/" instead of serviceURL = "http:xxxx/Login/Login".
This works for me.
You need to find a way to follow redirect.
Maybe postman is doing that.
Read this >>
https://api.flutter.dev/flutter/dart-io/HttpClientRequest/followRedirects.html
Can you try with using get instead of post? At least to try and see what happend
In the documentation said:
Automatic redirect will only happen for "GET" and "HEAD" requests
only for the status codes
HttpStatus.movedPermanently (301),
HttpStatus.found (302),
HttpStatus.movedTemporarily (302, alias for HttpStatus.found),
HttpStatus.seeOther (303),
HttpStatus.temporaryRedirect (307)
keeping https instead of http in the URL it is helping me.
#Abel's answer above is correct but I had to switch from using:
Uri url = Uri.https(defaultUri, path);
to
Uri url = Uri.parse('https://todo-fastapi-flutter.herokuapp.com/plan/');
to get that last / after plan.
The first way kept dropping it so I was getting 307 errors.
flutter.dev shows a full example:
Future<http.Response> createAlbum(String title) {
return http.post(
Uri.parse('https://jsonplaceholder.typicode.com/albums'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'title': title,
}),
);
}
here: https://flutter.dev/docs/cookbook/networking/send-data#2-sending-data-to-server
For Dio Http Client, use Dio Option follow redirect as True
getDioOption(){
return BaseOptions(connectTimeout: 30, receiveTimeout: 30,
followRedirects: true);
}
i am trying to send json data to my rest api.
it works when my "ContactData" as just 6 items but if it more than 6 item like the way it is, my api will see it as null.
var ContactData = {
'myContactData1': myContactDataItem1,
'myContactData2': myContactDataItem2,
'myContactData3': myContactDataItem3,
'myContactData4': myContactDataItem4,
'myContactData5': myContactDataItem5,
'myContactData6': myContactDataItem6,
'myContactData7': myContactDataItem7,
'myContactData8': myContactDataItem8,
'myContactData9': myContactDataItem9,
'myContactData10': myContactDataItem10,
'myContactData11': myContactDataItem11,
'myContactData12': myContactDataItem12,
'myContactData13': myContactDataItem13,
'myContactData14': myContactDataItem14,
'myContactData15': myContactDataItem15,
'myContactData16': myContactDataItem16,
'myContactData17': myContactDataItem17,
'myContactData18': myContactDataItem18,
'myContactData19': myContactDataItem19,
};
if i should reduce "ContactData" to just 6 items, i will work fine
Map data = {
'contact' : ContactData,
'item1': itemdata1,
'item2': itemdata2,
'item3': itemdata3,
'item4': itemdata4,
'item5': itemdata5,
'item6': itemdata6,
'item7': itemdata7,
'item8': itemdata8,
'item9': itemdata9,
'item10': itemdata10,
'item11': itemdata11,
'item12': itemdata12,
'item13': itemdata13,
'item14': itemdata14,
'item15': itemdata15,
'item16': itemdata16,
'item17': itemdata17,
'item18': itemdata18,
'item19': itemdata19,
};
//encode Map to JSON
var dataToSend = json.encode(data);
var response = await http.post("v1/add"),
headers: {
"Content-Type": "application/json; charset=UTF-8",
"securedData": ServiceConnector.securedData,
},
body: dataToSend);
Here I am trying to send the Object Map in the multipart request but my request is going as a string, not in JSON format please suggest me to do correct request. Thanks in advance.
I have tried the multipart request but my request should be in correct form..
var getApiUrl = 'http://malik-env-test.ap-south-1.elasticbeanstalk.com/webapi/post/create';
Map userData = {
"creator": {
"creatorId": "298",
"createDate": "2018-12-21 20:44:45.8"
},
"info": "$campusInfo",
"title": "$eventName",
"postCampusId": "5642"
};
Uri uri = Uri.parse(getApiUrl);
http.MultipartRequest request = new http.MultipartRequest('POST', uri);
request.fields['creator'] = userData['creator'];
request.fields['info'] = '$campusInfo';
request.fields['title'] = '$eventName';
request.fields['postCampusId'] = '5642';
request.files.add(await http.MultipartFile.fromPath('image_file1', imagePath, contentType: new MediaType('application', 'x-tar')));
// var body = json.encode(request);
print(request);
http.StreamedResponse response = await request.send();
String jsonData = response.toString();
print(jsonData);ddd
Try:
request.fields['userData'] = json.encode(userData);
You need to find out from the API spec or server owner what field name to use for the json. I've assumed userData.
If you want control over the media type, encoding, etc, add it as a file like this:
request.files.add(
http.MultipartFile.fromBytes(
'the_form_field name',
utf8.encode(json.encode(userData)),
contentType: MediaType(
'application',
'json',
{'charset': 'utf-8'},
),
),
);
I think, the easiest way to add object fields is using brackets like this ;
request.fields['creator[creatorId]'] = '$creatorId';
request.fields['creator[createDate]'] = '$createDate';
request.fields['title'] = '$eventName';
request.fields['postCampusId'] = '5642';
So, for the fields inside another you need to put the object name first then add to fields name inside brackets.
this should work just fine.
var userData = json.encode({
"creator": {
"creatorId": "298",
"createDate": "2018-12-21 20:44:45.8"
},
"info": "$campusInfo",
"title": "$eventName",
"postCampusId": "5642"
});
var client = http.Client();
client
.post('https://'+ url ,
headers: {
'content-type': 'application/json',
},
body: userData )