I've been working on this issue for some time now, and I can't seem to figure out what exactly the issue is. In Dart(2) the json.encode()
does not seem to be giving me the result I am aiming for.
I am passing in a Map<String, dynamic>
that looks like this:
_data = <String, dynamic>{
'uid': newProfileCreationModel.accountID,
'displayName': newProfileCreationModel.profileName,
'greeting': newProfileCreationModel.profileBody ?? '',
'avatarSrc': newProfileCreationModel.avatarSrc,
'heroSrc': newProfileCreationModel.heroSrc,
'accountType': newProfileCreationModel.accountType,
'cityID': newProfileCreationModel.cityID,
'cityName': newProfileCreationModel.cityName,
'country': newProfileCreationModel.countryCode,
'state': newProfileCreationModel.stateAbv,
};
and using this to convert it to JSON
final String _jsonData = json.encode(_data);
Then I am sending it to a google cloud function in the following way.
final Uri _uri = Uri.parse(functionUrl);
final String _jsonData = json.encode(_data);
final String _userToken = await AuthenticationService.getUserToken();
HttpClient client = new HttpClient();
HttpClientRequest request = await client.postUrl(_uri);
request.headers.set('Authorization', 'Bearer ' + _userToken);
request.headers.set('Content-Type', 'application/json; charset=utf-8');
print('Encoded: ' + _jsonData);
request.write(_jsonData);
HttpClientResponse response = await request.close();
if(response.statusCode != HttpStatus.OK){ ...
The line where I print the encoded string outputs this to the console:
05-04 18:52:57.902 26146-26200/com.app.name I/flutter: Encoded: {"uid":'123456789',"displayName":"James","greeting":"My Greetings!","avatarSrc":"http://cdn.free.com/someImage.jpg","heroSrc":"http://cdn.free.com/someImage.jpg","accountType":"per","cityID":1,"cityName":"Eugene","country":"US","state":"OR"}
However the request.write(_jsonData)
fails with the following firebase console log error Request Body Missing Data the response that looks like this in the
Firebase Console Log.
Request body is missing data. {
uid: '123456789',
displayName: 'James',
greeting: 'My Greetings!',
avatarSrc: 'http://cdn.free.com/someImage.jpg',
heroSrc: 'http://cdn.free.com/someImage.jpg', accountType: 'per',
cityID: 1,
cityName: 'Eugene',
country: 'US',
state: 'OR'
}
Invalid request IncomingMessage {
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
ended: true,
endEmitted: true,
reading: false,
sync: false,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: false,
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
socket:
Socket {
connecting: false,
_hadError: false,
_handle:
TCP {
bytesRead: 13285,
_externalStream: {},
fd: 14,
reading: true,
owner: [Circular],
onread: [Function: onread],
onconnection: null,
writeQueueSize: 0,
_consumed: true },
_parent: null,
_host: null,
The interesting part is that the data is getting through as is clearly displayed in the firebase console log, however it won't recognize it as the body.
Raw Data Approach
When I try sending a raw JSON object through the request.write()
as
request.write({'hello':'universe'});
I get a totally different kind of error in the firebase console.
SyntaxError: Unexpected token h in JSON at position 1
at Object.parse (native)
at parse (/var/tmp/worker/node_modules/body-parser/lib/types/json.js:84:17)
at /var/tmp/worker/node_modules/body-parser/lib/read.js:102:18
at IncomingMessage.onEnd (/var/tmp/worker/node_modules/raw-body/index.js:149:7)
at IncomingMessage.g (events.js:292:16)
at emitNone (events.js:86:13)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
on the firebase side I am using a function using a callable, this is where the firebase console logs are being recorded from
export const finalizeProfile = functions.https.onCall((data, context) => {
//CODE
});
Is anyone able to spot what I may be doing incorrectly?
The solution was hidden in plain sight. The issue had to do with a missing field. for Firebase Cloud Functions, the contents 'body', as referred to in the error message body is missing data
, literally means it requires a key named data
which contains the object of data you are passing.
The google docs are not(ish) crystal clear on this, as they are missing an example https://firebase.google.com/docs/functions/callable-reference#request_body
This is how the data must be sent to functions.https.onCall()
, note the Data Field as compared to the original question which did not include this:
{
"data":{
"uid":"123456789",
"displayName":"James",
"greeting":"My Greeting!",
"avatarSrc":"http://cdn.free.com/someImage.jpg",
"heroSrc":"http://cdn.free.com/someImage.jpg",
"accountType":"per",
"cityID":1,
"cityName":"Eugene",
"country":"OR",
"state":"AL"
}
}
The resulting code that now works looks as follows:
// Helper function to format any map to be used for Firebase
Map prepMapForFirebaseJSON(Map<String, dynamic> mapData){
Map<String, Map<String, dynamic>> _fireJson = {
'data' : mapData
};
return _fireJson;
}
// Process HTTP request
final Uri _uri = Uri.parse(functionUrl);
final String _jsonData = json.encode(prepMapForFirebaseJSON(mapData));
final String _userToken = await AuthenticationService.getUserToken();
HttpClient client = new HttpClient();
HttpClientRequest request = await client.postUrl(_uri);
request.headers.set('Authorization', 'Bearer ' + _userToken);
request.headers.set('Content-Type', 'application/json; charset=utf-8');
request.write(_jsonData);
request.close();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With