Axios frontend doesn't seem to pass request parameters to backend - node.js

I have this hook on react for my frontend to perform http requests to get data to show on page
useEffect(() => {
const options = {
method: "GET",
url: `http://localhost:8080/api/v1/postersgrid`,
params: { query: props.query },
};
axios
.request(options)
.then((res) => {
console.log(res);
setResults(res.data.results);
setTotalPages(res.data.total_pages);
setSuccessfulRequest(true);
})
.catch((err) => {
console.log(err);
setSuccessfulRequest(false);
});
}, [props.query]);
as you can see that endpoint is mine because i made a little backend for my app
const express = require("express");
const cors = require("cors");
const axios = require("axios");
const PORT = 8080;
const app = express();
app.use(cors());
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
app.get("/api/v1/postersgrid", (req, res) => {
const options = {
method: "GET",
url: `https://api.themoviedb.org/3/search/movie?api_key=${APIKEY}&query=${req.query}`,
};
axios
.request(options)
.then((response) => {
res.json(response.data);
})
.catch((error) => {
console.log(error);
});
});
this backend communicates with an api of which i have the api key.
What i want is:
frontend queries backend where api key is hidden
backend queries api and returns data to frontend
Now the problem is when i try to pass parameters from frontend to backend
const options = {
method: "GET",
url: `http://localhost:8080/api/v1/postersgrid`,
params: { query: props.query },
};
here i try to pass it to backend but as soon as i use it in the url to perform http requests to the api it's like it's undefined or null
url: `https://api.themoviedb.org/3/search/movie?api_key=${APIKEY}&query=${req.query}`,
to prove this works, if i change the query to be static
url: `https://api.themoviedb.org/3/search/movie?api_key=${APIKEY}&query=war`
everything works as intended, where am I wrong? btw I'm doing all of this instead of performing requests directly from frontend to hide my api key correctly

Had to change this
url: `https://api.themoviedb.org/3/search/movie?api_key=${APIKEY}&query=${req.query}
to this
url: `https://api.themoviedb.org/3/search/movie?api_key=${APIKEY}&query=${req.query.query}

Related

Send params from frontend to be used in a NodeJS Get request

I am trying to pass data to my Node.js backend in order to use it in a get request to an API.
For example:
Server.js
const PORT = 8000
const axios = require('axios').default
const express = require('express')
const app = express()
const cors = require('cors')
app.use(cors())
require('dotenv').config()
app.use(express.json())
app.get('/convertedAmount', (req, res) => {
const contentBody = req.body
const options = {
method: 'GET',
url: 'https://currency-converter5.p.rapidapi.com/currency/convert',
params: {format: 'json', from: contentBody.primaryCurrency, to:
contentBody.secondaryCurrency, amount: contentBody.primaryCurrencyAmount},
headers: {
'x-rapidapi-host': process.env.RAPIDAPI_HOST,
'x-rapidapi-key': process.env.RAPIDAPI_KEY,
},
}
axios
.request(options)
.then((response) => {
res.json(response.data)
})
.catch((error) => {
console.error(error)
})
})
app.listen(PORT, () => console.log(`server running on PORT ${PORT}`))
The issue is, I don't know how to pass data to the backend from the frontend, without making it a POST request. But that doesn't work if I make a POST request to the rapidAPI url. So the backend needs to stay the same.
My question is, how would I write the frontend part for this?
Using a POST request in the frontend sends the data with the req.body, but I cant get the data to display in my browser on localhost:8000/convertedAmount.
Thank you
My attempt is:
Frontend.js
...
axios.post('/convertedAmount', {
primaryCurrency: 'USD',
secondaryCurrency: 'GBP',
primaryCurrencyAmount: 1
})
.then((response) => {
console.log(response);
}, (error) => {
console.log(error);
})
...
You shouldn't be trying to send data in the body (such as in req.body) through a GET request. That is what a POST request is for.
With a GET request, you should pass data (such as a user id) as a parameter. Basically, in the url string.
FRONTEND
axios.get("/convertedAmount/USD/GBP/1")
BACKEND
app.get("/convertedAmount/:primaryCurrency/:secondaryCurrency/:primaryCurrencyAmount", (req, res)=>{
console.log(req.params.primaryCurrency);
console.log(req.params.secondaryCurrency);
console.log(req.params.primaryCurrencyAmount);
});
Alternatively, you could use query strings, which would look like this:
FRONTEND
axios.get("/convertedAmount?primaryCurrency=USD&secondaryCurrency=GBP&primaryCurrencyAmount=1")
BACKEND
app.get("/convertedAmount*", (req, res)=>{
console.log(req.query.primaryCurrency);
console.log(req.query.secondaryCurrency);
console.log(req.query.primaryCurrencyAmount);
});

How do I make server-side fetch calls?

I have a React web application which currently does fetch calls client-side to update a dashboard with live information (let's say current weather, as an example), meaning that with an increase in users it will cause unnecessary traffic calls and could potentially crash this weather website.
What I am trying to understand is how can I make those fetch calls be server-side? I have looked into creating a Node.js Express server, but I am unsure if it has the functionality to make fetch calls to a remote host.
Here is my code with request-weather which does not really work, unfortunately.
const { response } = require('express');
const express = require('express');
const app = express();
var fetch = require('node-fetch');
const port = process.env.PORT || 5000;
app.use(express.json());
// This displays message that the server running and listening to specified port
app.listen(port, () => console.log(`Listening on port ${port}`));
// create a GET route
app.get('/request-info', (req, res) => {
res.send({ information: 'information call successful' });
});
app.get('/request-weather', (req, res) => {
fetch('http://thisotherwebsite.com/weather-query-that-returns-json',
{method: 'GET',
headers: {' Accept': 'application/json'}})
.then(res => {
return res;
})
});
Couple things:
Your /request-weather handler makes the request to thisotherwebsite but doesn't do anything with the response.
Your .then(res => { return res; }) doesn't actually do anything. You're just taking what fetch already returns and returning it.
If you want to send the response back to the browser you might do something like this:
fetch(...) // make the request
.then(result => result.json()) // extract the data
.then(data => {
res.json(data); // send it to the browser
})
If you want to do additional processing you could await the fetch call and then do whatever else you need to do with it:
app.get('/request-weather', async (req, res) => { // make handler async
// get data from the other site
const data = await fetch(...)
.then(response => response.json());
// package it up with some other stuff
responseData = {
fromOtherSite: data,
myExpressStuff: {
foo: 1,
bar: 2,
}
}
// return it to the browser
res.json(responseData);
Reference:
fetch: response.json() - Extracting data from a fetch response
express response.json() - Sending json to the response (usually to the browser)

Sending data to Nodejs backend in Reactjs for API call

I'm trying to send data to my Nodejs server (hosted on Firebase), from Reactjs to retrieve data from an API call.
It worked when the API url was hard coded, so the issue should be in sending the data from React to Node. I'm currently trying to have it only return one request, but once I'm able to do that, I will be trying to fetch multiple requests.
The result is to populate the stocks state with the response.
My React code looks like this:
class Table extends Component {
constructor (props)
{
super(props);
this.state = {
favorites: ['APPL'],
stocks: []
};
}
componentDidMount() {
// http is adjusted for stackoverflow
fetch('http://localhost:5001/', {
// new part:
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
favorites: this.state.favorites})
// old part - worked before i tried to send data to the backend:
})
.then((response) => response.json())
.then(stockList => {
this.setState({ stocks: stockList });
console.log(stockList);
});
}
Node code:
const functions = require("firebase-functions");
const express = require("express");
const fetch = require("node-fetch");
const cors = require("cors");
const app = express();
app.use(cors({origin: true}));
app.get('/', async (request, response) => {
// new line that was ment to catch the data from frontend.
const favorites = request.body.favorites
// web and key is the rest of the API call.
const url = web+favorites+key;
const fetchResponse = await fetch(url);
const symbol = await fetchResponse.json();
response.json(symbol);
});
In order to get the data from the frontend you will need to make a post endpoint instead in your Node server and send a GET request inside that method.
const functions = require("firebase-functions");
const express = require("express");
const fetch = require("node-fetch");
const cors = require("cors");
const app = express();
app.use(cors({origin: true}));
app.post('/', (req, res) => {
// here is how you get the POST data from the body
console.log(req.body.favorites)
// send the data from the POST request to the API through a GET request here
})
Now you need to make a GET request where I put the comment, you can use the simpler https node.js library for that.
In my question, I'm trying to use Firebase functions to handle the link to an external API and use the data from that API in my frontend.
After some though and help from Stackoverflow, I have found that it might not be an ideal way to do it. I was basically trying to add a layer between the frontend and the API, but that is not necessary, as it is possible to reach the API directly in React. This will remove the function from Firebase, meaning less steps, less code and less fees.
So for every instance in the state.favorites, the correlated data is pulled from the API and stored in the state.stocks.
This piece of code did the trick:
class Table extends Component {
constructor (props)
{
super(props);
this.state = {
favorites: ['aapl', 'arvl'],
stocks: []
};
}
componentDidMount() {
this.state.favorites.map((favorites, index) => {
fetch(`API_website${favorites}/(API_token`)
.then((response) => response.json())
.then(stockList => {
this.setState({ stocks: stockList });
console.log(stockList);
});
})
}

"message":"Request failed with status code 500","name":"Error","stack":"Error: Request failed with status code 500\n

I wanted to fetch data from open API from this link. According to the documentation, The HTTP method must be POST and Content-Type must be either "application/graphql" or "application/json". I used node express server to fetch the data. But when run the server I got error. From this API I wanted to display on browser public transportation timetables between one location to another location.
Ps. I never fetched Graphql open api.
const express = require("express");
const app = express();
const port = 3000;
const bodyParser = require("body-parser");
const axios = require("axios");
const morgan = require("morgan");
const cors = require("cors");
app.use(morgan("common"));
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
const url = "https://api.digitransit.fi/routing/v1/routers/hsl/index/graphql";
app.get("/hsl/timetables", async (req, res, next) => {
axios
.get(url, {
method: "POST",
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/graphql"
}
})
.then(response => res.send(response.data))
.catch(err => {
console.log("catch error", err), res.status(500).send(err);
});
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
If you notice in the Axios docs here you do not need to have the method in your options . (Remove this method: "POST",).
Also, you will want to change the request to a .post( instead of a .get( like you have
You will need to include a body in your request as well. This will be where you need to figure out what you want. I'm not sure what routes you are looking to display but as an example,
let data = {
routes(name: "10") {
gtfsId
shortName
longName
mode
}
}
You can find lots of examples on what you data should be for whatever query you want
To add it all up, you would have something like this:
axios.post(url, data, {
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/graphql"
}
})

Can't pass req.params when using http-proxy-middleware ... NodeJS/Express

I am new to Node, and I can't pass request parameters when using http-proxy-middleware..
It throws me 404 error
This is the express listener:
app.put("/api/markets/:id",()=>{..code..});
This is the axios PUT request:
axios
.put("/api/markets/" + idToPass, {..Object..})
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
And this is the proxyMiddleware:
const proxy = require("http-proxy-middleware");
module.exports = function(app) {
app.use(proxy("/api/*", { target: "http://localhost:3050" }));
};
My client runs on localhost:3000 (react app)
And my server is on localhost:3050
When I open my browser network tab to inspect requests I see that call is being made to
localhost:3000/api/markets/idContent
not
localhost:3050/api/markets/idContent
as it is supposed to.
It works when I send it manually to
localhost:3050/api/markets/idContent
How can I fix this, any ideas?
Thx in advance
It seems the problem is with the proxy configuration. As of now it matches urls only one level deep.
Try /api or /api/** instead
const proxy = require("http-proxy-middleware");
module.exports = function(app) {
app.use(proxy("/api", { target: "http://localhost:3050" }));
};
You are not specifying the base URL. Create an axios instance and specify the correct base URL:
const instance = axios.create({
baseURL: 'http://localhost:3050'
});
And then make every axios requests using that instance:
instance
.put("/api/markets/" + idToPass, {..Object..})
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});

Resources