how to pass parameter from client side to node-get request - javascript

i have a problem.
i have an object in my client side witch have to be my params.
anyone know how to pass an object from client side to server side?
this is my node route, i need to use endPoint from user to do query params
const fetch = require("node-fetch");
async function getDataByEndPoint(req, res, endPoint) {
const url = "https://pixabay.com/api/?key=<KEY-GOES-HERE>";
const options = {
method: "GET",
// headers: {
// "X-RapidAPI-Host": "famous-quotes4.p.rapidapi.com",
// "X-RapidAPI-Key": "your-rapidapi-key",
// },
};
try {
let response = await fetch(url, options);
response = await response.json();
res.status(200).json(response);
console.log(res);
} catch (err) {
console.log(err);
res.status(500).json({ msg: `Internal Server Error.` });
}
}
module.exports = getDataByEndPoint;
this is my client side code
function App() {
const data = useSelector((state) => state.counter.data);
const endPoint = useSelector((state) => state.counter.endPoint);
const dispatch = useDispatch();
// const [data, setData] = useState([]);
const getData = async (endPoint) => {
const requestOptions = {
method: "GET",
};
try {
const res = await fetch(
`http://localhost:8000/dataByParams`,
requestOptions
);
const resJson = await res.json();
console.log(resJson);
dispatch(setData(resJson.hits));
} catch (err) {
console.log(err);
}
};
unfortunately i cant do
?params=
be because i used node fetch so its doesn't work on my localhost....
i tried to use params on https://pixabay.com/api/?key=<KEY-GOES-HERE>
and its worked but when i use it on local host it doesn't because its not the full url, its just the local host

Related

Hi I'm getting error "SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON"

Hi I have created a simple app that uses three apis to fetch data and render that data appropriately in the webpage. It uses node, express server, body-parser and cors, as middleware. Also I compiled all the code in webpack and ran the webpack dev-server in which the error is appearing. Here is my server.js:
// Setup empty JS object to act as endpoint for all routes
cityData = {};
weatherData = {};
picturesData = {};
// Require Express to run server and routes
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
// Start up an instance of app
const app = express();
/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
app.use(cors())
// Initialize the main project folder
app.use(express.static('../website/client'));
app.get("/all", function sendData(req, res) {
res.send(cityData);
})
app.get("/allWeather", function sendWeather(req, res) {
res.send(weatherData);
})
app.get("/allPictures", function sendPictures(req, res) {
res.send(picturesData);
})
app.post("/addWeather", (req, res) => {
weatherData['temp'] = req.body.temp;
res.send(weatherData);
})
app.post("/addPicture", (req, res) => {
picturesData['pic'] = req.body.pic;
res.send(picturesData);
})
// Setup Server
app.listen(3000, () => {
console.log("App listening on port 3000")
console.log("Go to http://localhost:3000")
})
Here is my app.js:
const geoURL = "http://api.geonames.org/searchJSON?";
const geoUsername = `rohanasif1990`;
const weatherURL = "https://api.weatherbit.io/v2.0/forecast/daily?"
const weatherKey = "20028a8267a24bba9a807362767bc4a7"
const pixabayKey = "30776478-ff0b8818f9bba72161ebb1731"
const pixabayURL = "https://pixabay.com/api?"
const present = new Date();
const submitBtn = document.getElementById("submitBtn");
submitBtn.addEventListener("click", (e) => {
e.preventDefault();
const city = document.getElementById("city").value;
const departure = document.getElementById("date").value;
const [depart_date, depart_time] = departure.split("T")
const [depart_year, depart_month, depart_day] = depart_date.split("-")
const [depart_hour, depart_minute] = depart_time.split(":")
const future = new Date(depart_year, depart_month - 1, depart_day, depart_hour, depart_minute);
console.log(future);
console.log(present);
if (city !== "" || departTime !== "") {
document.getElementById("time").innerHTML = `Departure in ${(future - present) / 3600000 / 24} days`
getCity(geoURL, city, geoUsername)
.then(function (data) {
return getWeather(weatherURL, weatherKey, data["geonames"][0]['lat'], data["geonames"][0]['lng'])
}).then(weatherData => {
return postWeatherData("/addWeather", { temp: weatherData['data'][0]['temp'] })
}).then(function () {
return receiveWeatherData()
}).catch(function (error) {
console.log(error);
alert("Please enter a valid city and a valid time");
})
getPictures(city, pixabayURL, pixabayKey)
.then(function (picsData) {
return postPictureData("/addPicture", { pic: picsData['hits'][0]["webformatURL"] })
})
.then(function () {
return receivePictureData()
}).catch(function (error) {
console.log(error);
alert("No pictures found")
})
}
})
const getCity = async (geoURL, city, geoUsername) => {
const res = await fetch(`${geoURL}q=${city}&username=${geoUsername}`);
try {
const cityData = await res.json();
return cityData;
}
catch (error) {
console.log("error", error);
}
}
const postWeatherData = async (url = "", data = {}) => {
const response = await fetch(url, {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
temp: data.temp
})
});
try {
const newData = await response.json();
return newData;
}
catch (error) {
console.log(error);
}
}
const receiveWeatherData = async () => {
const request = await fetch("/allWeather");
try {
const allData = await request.json()
document.getElementById("temp").innerHTML = "TEMPERATURE: " + allData['temp'];
}
catch (error) {
console.log("error", error)
}
}
const getWeather = async (weatherURL, weatherKey, lat, lon) => {
const res = await fetch(`${weatherURL}&lat=${lat}&lon=${lon}&key=${weatherKey}`);
try {
const weatherData = await res.json();
return weatherData;
}
catch (error) {
console.log("error", error);
}
}
const getPictures = async (city, pixabayURL, pixabayKey) => {
const query = city.split(" ").join("+");
const res = await fetch(`${pixabayURL}key=${pixabayKey}&q=${query}`);
try {
const picsData = await res.json();
return picsData;
}
catch (error) {
console.log("error", error)
}
}
const receivePictureData = async () => {
const request = await fetch("/allPictures");
try {
const allData = await request.json()
document.getElementById("city-pic").src = allData['pic'];
}
catch (error) {
console.log("error", error)
}
}
const postPictureData = async (url = "", data = {}) => {
const response = await fetch(url, {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
pic: data.pic
})
});
try {
const newData = await response.json();
return newData;
}
catch (error) {
console.log(error);
}
}
To see the error I ran "npm i" to install dependencies and webpack packages. Then "npm run build-prod" to build the project dist folder. Then running "npm run build-dev". Then in incognito go to localhost:3000. And when I enter some city name like "london". I get the following errors:
screenshot of the error
I can't figure out why there are errors at lines 130 and 64. I'm new to javascript and have been doing many web development projects but never seen this kind of error. It seems like the data being sent or received is not JSON which it should be but rather an HTML file. I think the server is serving only the static HTML file and executing none of the code in app.js. Please have a look and please help me solve this issue as this is an important project of mine.
That is an error page came in response instead of the JSON.

How can I persist auth state in a nodejs app

So, I am learning NodeJs by creating this backend that fetches some data from a third-party API, the API requires auth. I couldn't figure out how to avoid sending an auth request to the third-party API whenever I wanted to fetch data from it. is there any way I could store the auth state in the app?
const axios = require("axios");
const AUTH_URL = process.env.AUTH_URL;
const REPORT_BASE_URL = process.env.REPORT_BASE_URL;
const X_API_KEY = process.env.X_API_KEY;
const getCompanies = async (req, res) => {
let idToken;
// auth
const authPayload = JSON.stringify({
// ...
});
const config = {
method: "post",
// ...
};
try {
const { data } = await axios(config);
idToken = data.idToken; // set idToken necessary for fetching companies
} catch (error) {
console.log(error);
}
// get company by full text query
const { full_text_query } = req.query;
if (!full_text_query)
return res.send("No full_text_query parameter provided");
try {
const { data } = await axios.get(
`${REPORT_BASE_URL}/companies?full_text_query=${full_text_query}`,
{
headers: {
"x-api-key": X_API_KEY,
Accept: "application/json",
authorization: idToken,
},
}
);
res.status(200).json(data);
} catch (error) {
console.log(error);
}
};
module.exports = {
getCompanies,
};
You can break out a function like fetchIdToken and store a Promise that resolves with the idToken in memory.
let idTokenPromise;
async function fetchIdToken () {
if (idTokenPromise) return idTokenPromise;
return idTokenPromise = new Promise(async (resolve) => {
...
resolve(data.idToken);
})
}
You can then use await fetchIdToken() at the start of getCompanies.
You can also just store the idToken in memory. This is slightly simpler, but does mean that you can have a race-condition when multiple getCompanies requests happen at the same time:
let idToken;
async function fetchIdToken () {
if (idToken) return idToken;
...
idToken = data.idToken;
return idToken;
}

Handling query in React and Express

Somewhere in my React application I used REST API to send request to the server. In my URL I want to use query (in the postIconsTransition method), but when I send a request to the server, server tells me could not found this URL (I build this error in my server). If I use this URL without any query the request in the postIconsTransition method works fine. postId and authContext.userId work fine, can anyone tell me what's wrong with my code?
In my component where I send request:
const likeHandler = async () => {
setLike(prevState => !prevState);
if (!like) {
try {
await postIconsTransition(props.postId, "inc");
} catch (error) {}
} else {
try {
await postIconsTransition(props.postId, "dec");
} catch (error) {}
}
};
In useHttp.js component:
const postIconsTransition = async (postId, addtionAddress) => {
return await transitionData(
`http://localhost:5000/post/${postId}/${authContext.userId}?t=${addtionAddress}`,
"POST",
null,
{ Authorization: `Bearer ${authContext.token}` }
);
};
transitionData method:
const transitionData = useCallback(
async (url, method = "GET", body = null, headers = {}) => {
setIsLoading(true);
const abortController = new AbortController();
activeHttpRequest.current.push(abortController);
try {
const response = await fetch(url, {
method,
body,
headers,
signal: abortController.signal
});
const responseData = await response.json();
activeHttpRequest.current = activeHttpRequest.current.filter(
reqCtrl => reqCtrl !== abortController
);
if (!response.ok) {
throw new Error(responseData.message);
}
setIsLoading(false);
return responseData;
} catch (error) {
modalContext.err(error);
setIsLoading(false);
throw error;
}
},
[modalContext.err]
);
In Express:
router.post(
"/:postId/:userId?t=inc",
tokenChecker,
postController.updateLikesComments
);
router.post(
"/:postId/:userId?t=dec",
tokenChecker,
postController.updateLikesComments
);
All of them work fine but when I use query in my URL, it's not working any more.
You don't specify query parameters in express routes like that. Just send them. Express can read it.
router.post(
"/:postId/:userId",
tokenChecker,
postController.updateLikesComments
);
// Notice that you don't need the other one.
and in your controller check the parameter
// controller's code
const t = req.query.t;
if (t === 'inc') {
// do what you want here
}
if (t === 'dec') {
// do what you want here
}

Javascript/node.js sending data between server and client

I am writing a recipe search engine and i am stuck at sending data between client and server as i didn't work with backend before (i am a beginner in coding).
On the client side i ask user to choose category which he wants the recipe for (e.g chicken). Then the choice is saved in variable and that is being send to the server. That's all working right.
Then on the server i want to pass the category to API Call, make the Call and send the data back to the client, how do i do that ?
Here's some code:
CLIENT-SIDE:
function getRecipes(category){
const categorySearch = category.alt;
let data = {
categoryChoice: categorySearch
}
let options = {
method: 'POST',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body: JSON.stringify(data)
}
const promise = fetch('/data', options);
promise.then(response => {
if(!response.ok){
console.error(response)
} else {
return response.json();
}
}).then(result => {
console.log(result);
})
}
SERVER-SIDE
app.post('/data', async (request, response) => {
const data = await request.body;
const gotData = data.categoryChoice;
const category = gotData;
console.log(category);
response.json(category);
return category
})
app.get('/data', async (request, response) => {
const cat = await category;
const url = `https://edamam-recipe-search.p.rapidapi.com/search?q=${cat}&from=0&to=100`
const fetch_response = await fetch(url);
const json = await fetch_response.json();
response.json(json);
})
app.get doesn't logs or gives me anything so i don't think it even works
try this:
app.get('/data', async (request, response) => {
const cat = await category;
const url = `https://edamam-recipe-search.p.rapidapi.com/search?q=${cat}&from=0&to=100`
fetch(url).then(res => res.json()).then(res => {
response.json(json);
});
})
I think that you should use only one 'post' method for that(on both frontend and backend). Assuming that your code is correct, it should be something like that:
app.post('/data', async (request, response) => {
const data = request.body;
const category = data.categoryChoice;
console.log(category);
const url = `https://edamam-recipe-search.p.rapidapi.com/search?q=${category}&from=0&to=100`
const fetch_response = await fetch(url);
const json = await fetch_response.json();
response.json(json);
})

How to Avoid nesting promises?

How could I modify the following code to avoid nesting Promises?
The response of request-promise is needed to be inserted in Firestore.
I would also like to know how to have the jsonresponse available when the Firestore Promise is resolved to send the response.status to the caller aplication.
const functions = require('firebase-functions');
const rp = require('request-promise')
var admin = require("firebase-admin");
var serviceAccount = require("./service_key.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://melitest-5bc38.firebaseio.com"
});
let db = admin.firestore()
exports.customHttpRequest = functions.https.onRequest((request, response) => {
const url = 'https://jsonplaceholder.typicode.com/users'
var options = {
uri: url,
method: "GET",
json: true
};
rp(options).then((jsonresponse) => {
for(var i = 0 ; i < jsonresponse.length; i++){
var obj = jsonresponse[i]
var docid = obj.id
// Warning: Avoid nesting promises.eslint(promise/no-nesting)
db.collection("scrapeusertest").doc(String(docid)).set(obj).then(() =>{
console.log(`Data was upload to firestore and the response was: ${jsonresponse}`)
response.status(200).send(jsonresponse);
}).catch(error =>{
console.log(`Error uploading data Firebase: ${error}`)
});
}
return console.log("Data was send")
})
.catch((err) => {
console.log('Error:', err)
});
return null;
});
Easiest option is to use an async function:
const db = admin.firestore()
exports.customHttpRequest = functions.https.onRequest(async (request, response) => {
const url = 'https://jsonplaceholder.typicode.com/users'
const options = {
uri: url,
method: "GET",
json: true
};
const jsonresponse = await rp(options);
await Promise.all(jsonresponse.map(async obj => {
const docid = obj.id
try {
await db.collection("scrapeusertest").doc(String(docid)).set(obj);
} catch (error) {
console.log(`Error uploading data Firebase: ${error}`);
}
}));
console.log(`Data was upload to firestore and the response was: ${jsonresponse}`);
response.status(200).send(jsonresponse);
});
use promise and used the promise all as this shape
const res= await rp(options);
//should be soure the res is array
await Promise.all(res.map( async item =>{
const id=item.id;
try {
await db.collection("scrapeusertest").doc(String(id)).set(item);
} catch (error) {
//what action when handle wrror
}))})
you can use the res as what you need

Categories

Resources