Reputation: 143
I have a simple function on my front-end which calls a firebase function on the back-end. Although the request and the API logic are very simple, the call always fails, because the firebase function is unable to detect either the body or the appropriate headers of the request.
Here is the front-end code:
async function updateArtwork(
artworkId: string,
title: string,
medium: string,
description?: string,
price?: number,
printPrice?: number
): Promise<string> {
try {
const res = await fetch(`${config.apiUrl}updateArtwork`, {
method: 'POST',
body: JSON.stringify({
artworkId,
title,
description,
price,
printPrice,
medium,
}),
headers: new Headers({ 'Content-Type': 'application/json' }),
});
if (res) {
return res.json();
} else {
throw new Error('Could not save changes to this artwork');
}
} catch (err) {
throw new Error('Could not save changes to this artwork');
}
}
Here's the firebase function:
export const updateArtwork = functions.https.onRequest(
async (request, response) => {
doChecks(request);
const {
artworkId,
title,
description,
price,
printPrice,
medium,
} = request.body;
try {
await db.collection('artworks').doc(artworkId).update({
title,
description,
price,
printPrice,
medium,
});
return cors(request, response, () => {
return response
.status(200)
.json('Successfully saved changes to artist');
});
} catch (error) {
return response.status(500);
}
}
);
The function doChecks()
just logs various things about the request to the console, including the headers and the body. Bafflingly, according to these logs request.body
is {}
, even though when I check the dev tools network tab, the body is populated. Similarly, the logs tell me that there is no content-type
header on the request, while dev tools tells me the content-type
is application/json
, which is as expected.
In addition, the above call in the front-end makes two API calls, as opposed to the expected one. I know it does this because I did the following:
const res = await fetch...
lineif (res)...
) What makes this even more strange is that none of the above code has changed recently. It's possible that recent environment changes (upgrading npm packages, etc.) have somehow messed things up, but it's unclear what effect they would have.
Any help on this would be greatly appreciated!
Here is more detail on the doChecks()
function mentioned above. Here is the function:
const doChecks = (request: any) => {
console.log('request.body:');
console.log(request.body);
console.log('request.headers:');
console.log(request.headers);
console.log(`content type is ${request.headers['content-type']}`);
};
For the above call, here is what is logged:
> request.body:
> {}
> request.headers:
> {
> host: 'localhost:5001',
> connection: 'keep-alive',
> accept: '*/*',
> 'access-control-request-method': 'POST',
> 'access-control-request-headers': 'content-type,pragma',
> origin: 'http://localhost:3001',
> 'sec-fetch-mode': 'cors',
> 'sec-fetch-site': 'same-site',
> 'sec-fetch-dest': 'empty',
> referer: 'http://localhost:3001/cart',
> 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
> 'accept-encoding': 'gzip, deflate, br',
> 'accept-language': 'en-US,en;q=0.9'
> }
> content type is undefined
Upvotes: 1
Views: 1181
Reputation: 143
After much tearing out of hair, I've found what looks to be the solution. I simply wrapped all the business logic of the firebase function inside the cors()
call as below. None of the docs or examples I've seen have done this, so I'm not sure why this works. If anyone knows, please let me know!
export const updateArtwork = functions.https.onRequest(
async (request, response) => {
return cors(request, response, async () => {
try {
const {
artworkId,
title,
description,
price,
printPrice,
medium,
} = request.body;
await db.collection('artworks').doc(artworkId).update({
title,
description,
price,
printPrice,
medium,
});
} catch (err) {
return cors(request, response, () => {
response.status(500).end(err);
});
}
response.status(200).send('Successfully saved changes to artist');
});
}
);
Upvotes: 1