I am trying to implement a location autocomplete feature in my Flutter App with the help of the Google Places API and its autocomplete feature. To keep the API-calling logic and the API Key away from the Client, the Flutter App should call a Firebase Cloud Function, which then calls the Google Places API. I have been trying to get this to work for several days now, worked through all kinds of articles and I just cannot make any progress. This is the source code of my Firebase Cloud Function:
import * as functions from "firebase-functions";
import * as axios from "axios";
export const autofillSuggestions = functions.region("europe-west3")
.https.onCall(async (data) => {
const input = data.input;
const sessionToken = data.sessiontoken;
// will be stored as an environment variable, as soon as i get cloud function to work
const googleAPIKey = "my_api_key";
const requestURL = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=" + input +
"&key=" + googleAPIKey + "&sessiontoken=" + sessionToken;
return await axios.default.get(requestURL).then((apiResponse) => {
return {predictions: apiResponse.data.predictions,
};
})
.catch((error) => {
console.log(error);
});
});
This source code gets imported into a index.ts
which then exports the file again, so the issue should not lie there.
The Cloud Function Calling Logic inside the Flutter App looks like this:
HttpsCallable _getCallable(String functionName) =>
FirebaseFunctions.instance.httpsCallable(functionName);
Future<dynamic> _getSuggestionsFromGoogleMapsAPI(String input) async {
//FirebaseFunctions.instance
// .useFunctionsEmulator(origin: 'http://localhost:5001');
final callable = _getCallable('autofillSuggestions');
try {
final data = HashMap.of({
'sugg': input,
'sessionToken': _sessionToken,
});
final response = await callable.call(data);
return response.data;
} catch (e) {
print(e);
throw AutocompletionFailure();
}
}
When I trigger the Cloud Function Call within the Flutter app and I uncomment the lines mentioning useFunctionsEmulator
, everything works just fine. But as soon as I comment those out again and want to communicate with the real Firebase Server, I always get this error message in the VS Code debug console:
[firebase_functions/internal] Response is not valid JSON object.
The error log on the Firebase Server looks like this:
autofillSuggestions
{
"@type":"type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo":{"principalEmail":"my@mail.com"},
"requestMetadata":
{
"callerIp":"10.10.101.101",
"callerSuppliedUserAgent":"FirebaseCLI/9.8.0,gzip(gfe),gzip(gfe)",
"requestAttributes":{"time":"2021-04-04T09:34:15.120516Z","auth":{}},
"destinationAttributes":{}
},
"serviceName":"cloudfunctions.googleapis.com",
"methodName":"google.cloud.functions.v1.CloudFunctionsService.SetIamPolicy",
"authorizationInfo":
[
{
"resource":"projects/my-project/locations/europe-west3/functions/autofillSuggestions",
"permission":"cloudfunctions.functions.setIamPolicy",
"granted":true,
"resourceAttributes":{}
},
{
"permission":"cloudfunctions.functions.setIamPolicy",
"granted":true,
"resourceAttributes":{}
}
],
"resourceName":"projects/my-project/locations/europe-west3/functions/autofillSuggestions",
"request":
{
"updateMask":"version,bindings",
"resource":"projects/my-project/locations/europe-west3/functions/autofillSuggestions",
"policy":
{
"bindings":
[
{
"members":["allUsers"],
"role":"roles/cloudfunctions.invoker"
}
]
},
"@type":"type.googleapis.com/google.iam.v1.SetIamPolicyRequest"
},
"response":
{
"bindings":
[
{
"members":["allUsers"],
"role":"roles/cloudfunctions.invoker"
}
],
"@type":"type.googleapis.com/google.iam.v1.Policy","etag":"BwW/IkjRmog="
},
"resourceLocation":{"currentLocations":["europe-west3"]}
}
Since it does not mention anything like Function execution started
or Function execution terminated with ...
I suspect that the Cloud Function does not get called at all... Am I right with this thought? If yes, does anyone know how to get this working???
I oriented myself heavily on this and this article. I also found this pretty interesting, haven't tried it out yet, though, because I thought my main issue is the Cloud Function not even being called...