How to pass parameters to an external API via Firebase Functions - javascript

I have rerouted an external API call using Firebase Functions and everything seems to be working just fine (I have the paid plan) however, I am not sure how to pass parameters from the client side. The code on the server side looks like this:
const functions = require("firebase-functions");
const cors = require("cors")({ origin: true });
const { default: axios } = require("axios");
exports.news = functions.https.onRequest((request, response) => {
cors(request, response, () => {
var config = {
headers: {
"X-Api-Key": functions.config().news.key,
},
};
axios
.get(
"https://newsapi.org/v2/everything?q=usa&from=2021-08-27&to=2021-08-28&sortBy=popularity",
config
)
.then((res) => {
response.send(res.data);
})
.catch((error) => {
response.sendStatus(error);
});
});
});
What I will be passing from the client side is the from and to dates which currently are hard coded in the url. Just to make sure, am I doing it right to make an API call from the client side using the generated link from the Firebase Functions:
https://us-central1-<PROJECT-NAME>.cloudfunctions.net/news/?
Thanks in advance for all your replies.

You can pass those params as query parameters similar to the API call:
axios({
method: 'get',
url: 'the_cloud_function_url?from=the_date&to=another_date'
});
These query parameters can be access by request.query in the Cloud function.
Alternatively, you can make a POST request from Axios (client-side) and pass the data in body:
axios({
method: 'post',
url: 'the_cloud_function_url',
data: {
fromDate: '2021-08-27',
toDate: '2021-08-29'
}
});
This data can be read in cloud function using the request object:
exports.news = functions.https.onRequest((request, response) => {
const {fromDate, toDate} = request.body
console.log(fromDate, toDate)
// continue
})

Send data in body and handle the request.

Related

Why can't I send a form data from axios?

I am consuming an api that asks me to send a filter series within a formData, when doing the tests from Postman everything works without problem, I tried with other libraries and it also works without problem, but when trying to do it from axios the information does not return with the filters.
This is the code I am using:
const axios = require('axios');
const FormData = require('form-data');
let data = new FormData();
data.append('filtro_grafica', '2,0,0,0');
let config = {
method: 'get',
url: 'https://thisismyurl/filter',
headers: {
'Authorization': 'JWT MYTOKEN',
...data.getHeaders()
},
data : data
};
axios(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
You can send Form-data using get method, but the most servers, will reject the form data.
However it is not recommended anymore. The reason is, first because it is visible in the URL and browsers can cache them in it’s history backstacks, and second reason is because browsers have some limitations over the maximum number of characters in url.
If you are to send only few fields/input in the forms you can use it but if you have multiple inputs you should avoid it and use POST instead.
At the end it depends on your own usecase. Technically both GET and POST are fine to send data to server.
replace get with post
const axios = require('axios');
const FormData = require('form-data');
let data = new FormData();
data.append('filtro_grafica', '2,0,0,0');
let config = {
method: 'post',
url: 'https://thisismyurl/filter',
headers: {
'Authorization': 'JWT MYTOKEN',
...data.getHeaders()
},
data : data
};
axios(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});

How do I acquire the data in a json response from a POST request in Next/React?

I am using Next.js api route to handle a POST request then send a response back to the frontend. I have used Rapid API client extension to confirm there is a response being sent to the frontend. I just dont know how to handle it in the frontend.
Here is the code on the api route:
import clientPromise from "../../../config/mongodb";
export default async function userDetailsHandler(req, res) {
const body = req.body;
if (req.method == "POST") {
const client = await clientPromise;
const db = client.db("mood-board");
let emailQuery = await db
.collection("users")
.find({ email: body.email })
.limit(1)
.toArray();
let parsedData = JSON.parse(JSON.stringify(emailQuery));
res.status(200).json(parsedData)
console.log(parsedData)
} else if(req.method = "GET") {
}
}
In the following example, you use the fetch api to post the data which returns a promise. You can use then() which takes a callback function that you can use to operate on the data once that promise is returned.
Example:
useEffect(() => {
// POST request using fetch inside useEffect React hook
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'React Hooks POST Request Example' })
};
fetch('https://reqres.in/api/posts', requestOptions)
.then(response => response.json())
.then(data => setPostId(data.id));
// empty dependency array means this effect will only run once (like componentDidMount in classes)
}, []);

Receving "500 Internal Server Error" on Post Request to Firebase-Cloud-Function Endpoint

I'm trying to make a POST request using axios to my firebase cloud-function on form submit in react app. But I get '500' error everytime I make a request with an html-page response This app works best with javascriot enabled.
Latest Update:
It looks like there is no issue with cloud function
code. Rather more of a react-component issue. I used Postman to send
the POST request with header prop Content-Type set to application/json
and sending body in raw format {"email": "example_email"} and got
expected response from the cloud function. But when sent the request from
react component above, I get an html file response saying the app
works best with javascript enabled
I've tried setting Content-Type to both Application/json and multipart/form-data as I suspected it to be an issue but still got no luck.
Following is my code for cloud function and react submit form:
Cloud Function
const functions = require('firebase-functions');
const cors = require('cors')({ origin: true })
const runThisFunc1 = require(./libs/runThisFunc1);
const runThisFunc2 = require(./libs/runThisFunc2);
exports.wizardFunc = functions.https.onRequest((request, response) => {
cors(request, response, () => {
let email = request.body.email;
try {
return runThisFunc1(email)
.then(data => {
console.log("Word Done by 1!");
return runThisFunc2(data);
})
.then(res => {
console.log("Word Done by 2!");
return response.status(200).send("Success");
})
.catch(err => {
console.error("Error: ", err.code);
return response.status(500).end();
});
}catch(err) {
return response.status(400).end();
}
});
});
React-Form-Component Snippet
import axios from 'axios'
...
handleSubmit = e => {
e.preventDefault()
const { email } = this.state
axios({
method: 'post',
url: `${process.env.REACT_APP_CLOUD_FUNCTION_ENDPOINT}`,
data: { email: email },
config: {
headers: {
'Content-Type': 'multipart/form-data'
}
}
})
.then(res => {
//do something with reponse here
})
.catch(error => {
console.error(error)
})
}
...
Is there something wrong I am doing in the code or the request config is wrong?

can't get success response data/status from node/express to my client app(react): "referenceerror response is not defined"

i've made a basic node/express server, and have a route that handles submission of form data(i've made using react), the post request is handled using async/await with fetch api.. i'm not sure if the issue is with my server-side route or my implementation of the post request with async/await fetch. however the server does receive the form data it just doesn't return a response.
my code:
node/express route
router.post('/add', function (req, res) {
console.log(req.body);
res.json({success : "Updated Successfully", status : 200});
});
note: the console.log(prints the expected data, but the response isn't being picked up by client correcly)
post request implementation:
const postRequestHelper = async (routePath, objectPayload) => {
console.log("posting payload object: ");
console.log(objectPayload);
const rawResponse = await fetch(routePath, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(objectPayload)
});
const response = await rawResponse.json();
return response;
};
export default postRequestHelper;
form submission code where post request is called:
async handleSubmit(event) {
if(typeof this.state.validationMessages === "undefined"){
// create payload data object
let objectPayload = Object.assign({}, this.state);
for(let key in objectPayload){
if(!isInObject(key, formKeyConstants)) // delete any prop keys that aren't in formPropertyKeys js file
delete objectPayload[key]
}
// send post request
console.log(objectPayload);
const response = await postRequestHelper("http://localhost:8080/user/add", objectPayload);
// log response data
console.log("response");
console.log(response);
}
event.preventDefault();
}
What about trying in your server
return res.send(JSON.stringify({success : "Updated Successfully", status : 200}));
issue was with async await fetch api it seems, issue with await was breaking the response from the server.
If routing takes place in app , then use :
app.use(express.json)
If routing takes place in router folder , then use :
router.use(express.json)
It'll by default uncover the req.body into json format.(For which installing and initializing express is a must)

Check Axios request url before sending

API requests are failing because the URL generated by Axios is incorrect due to my config. I know what the request url is suppose to look like, so I want to see the request url Axios generates.
I can point Axios to my local server and see the requests there, but I want to debug this on the client. I want to play with the config, and see how the requests change. Is there a way to output the request url from Axios before or after sending?
// param format
{ address: 'Vancouver', key: GOOGLE_API_KEY }
// Geocode sample
https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY
_request = async (...args) => {
const { outputFormat, params } = args
const instance = axios.create({
baseURL: `https://maps.googleapis.com`,
})
const response = await instance.get('/maps/api/geocode/${outputFormat}?', {
params,
})
// I want to see the url generated by Axios so I can debug the issue
console.log(response)
}
I am within the Expo, React Native environment.
Working example using fetch:
const url = `https://maps.googleapis.com/maps/api/geocode/json?address=vancouver&key=${GOOGLE_API_KEY}`
fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(data)
})
.catch(function(error) {
console.log(error)
})
Solution used:
_request = async (obj) => {
const { outputFormat, params } = obj
const instance = axios.create({
baseURL: `https://maps.googleapis.com`,
})
instance.interceptors.request.use(function (config) {
console.log(config)
return config
}, function (error) {
return Promise.reject(error)
})
const response = await instance.get(`/maps/api/geocode/${outputFormat}`, {
params,
})
}
You can turn on debug mode and look at the network tab as mentioned in the other answer, or you can intercept axios and console.log or do whatever you want with the request before it's sent:
axios.interceptors.request.use(function (config) {
// Do something before request is sent
console.log(config)
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
You can just use axios#getUri([config]) (source) to perform the same logic as the request. It merges the configurations (e.g. the given config and the instance configuration), merges the url with the baseURL, and appends any params using the paramSerializer.

Categories

Resources