I've been working through the workshops for Netlify functions and have stumbled getting a simple Fetch response to work. When running the sample at: https://github.com/DavidWells/netlify-functions-workshop/blob/master/lessons-code-complete/use-cases/5-fetching-data/functions/node-fetch/node-fetch.js
const fetch = require('node-fetch')
const API_ENDPOINT = 'https://cat-fact.herokuapp.com/facts'
exports.handler = async (event, context) => { let response
try {
response = await fetch(API_ENDPOINT)
// handle response
} catch (err) {
return {
statusCode: err.statusCode || 500,
body: JSON.stringify({
error: err.message
})
} }
return {
statusCode: 200,
body: JSON.stringify({
data: response
}) } }
but I just get the following response:
{"data":{"size":0,"timeout":0}}
The build process is working fine, and I've tried other end points but all give the same results.
Here is a working version of your original code using node-fetch
and the callback.
// import fetch from 'node-fetch';
const fetch = require('node-fetch')
const checkStatus = (res) => {
if (res.ok) { // res.status >= 200 && res.status < 300
return res.json()
} else {
throw new Error(res.statusText);
}
}
exports.handler = async function(event, context, callback) {
try {
const response = await fetch('https://cat-fact.herokuapp.com/facts')
const data = await checkStatus(response)
callback(null, {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
} catch (error) {
callback(error)
}
}
Note: Netlify functions are just AWS functions and you can read about the AWS Lambda Function Handler in the AWS docs
For async functions, you return a response, error, or promise to the runtime instead of using callback.
I like to use the method recommended in the docs, since it is supported and save the callback for non-async functions.
Here is a working version returning a promise to the async function instead.
// import fetch from 'node-fetch';
const fetch = require('node-fetch')
exports.handler = async (event, context) => {
return new Promise((resolve, reject) => {
fetch('https://cat-fact.herokuapp.com/facts')
.then(res => {
if (res.ok) { // res.status >= 200 && res.status < 300
return res.json();
} else {
resolve({ statusCode: res.status || 500, body: res.statusText })
};
})
.then(data =>{
const response = {
statusCode: 200,
headers: { 'content-type': 'application/json' },
body: JSON.stringify(data)
}
resolve(response);
})
.catch(err => {
console.log(err)
resolve({ statusCode: err.statusCode || 500, body: err.message })
})
})
}
This is just an example and there are other ways to handle the errors, but this example resolved the response rather than rejecting. It is not tested as a production example, but gives you an idea of the difference.