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

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);
});

Related

Cookies do not stored when set it with axios POST method

I'm trying to write and read cookies and falling into a problem below.
This is my basic server side:
server.js
const app = express();
app.use(cors());
app.use(cookieParser());
import routes from '...';
app.use("/foo", routes);
app.listen(8888);
routes.js
const routes = express.Router();
routes.post('/', (req, res) => {
res.cookie("myFoo", "abcd");
res.send("Cookie added");
}
});
routes.get('/', (req, res) => {
res.send(req.cookies.myFoo);
}
});
export default routes;
And my client side at "http://localhost:3000".
I do two HTTP request
POST http://localhost:8888/foo
GET http://localhost:8888/foo
And get the response exactly what I expected abcd. Also, the cookie exists in the browser tab Application > Cookies too.
The problem cases when axios is used in the client.
const api = axios.create({
baseURL: "http://localhost:8888/foo"
});
async function setCookie(object) {
return api.post("/", object)
.then((res) => {
return res;
});
}
function getCookie() {
return api.get("/")
.then((res) => {
return res;
});
}
setCookie({})
.then((res) => {
getCookie();
})
The api.post() run usually and the header response Set-Cookie is correct. But cookies in the browser tab Application > Cookies are empty. Also, api.get() get the undefined.
I did try to move res.cookie() or the set cookie job in server side to GET route it WORKS on both HTTP and axios
routes.get('/', (req, res) => {
res.cookie("myFoo", "abcd");
});
tldr: Set cookie in HTTP POST method work fine but when client use axios to call so it causes problems.
Can you show me why this happened? And which code part went wrong that caused me into this?
Cookies are only used in cross-origin Ajax requests when:
The client asks to use them
The server grants permission to use them cross origin
So you need to change the client side code to ask for them:
const api = axios.create({
baseURL: 'http://localhost:8888/',
withCredentials: true,
});
And the server code to grant permission (note that you can't use credentials at the same time as the wildcard for origins).
app.use(cors({
origin: 'http://localhost:3000',
credentials: true
}));

React Native Expo - Why is my proxy not working - making requests leads to TypeError: Network request failed?

Im trying to add a proxy in my react native expo app so I can make api requests to my backend without always specifying http://localhost:3001 during development.
Im not sure if its different with react native that in react apps and cannot find any info about it (everything is always about using react and roxy).
I added a proxy and when I make a request from my frontend I always get this type err:
[Unhandled promise rejection: TypeError: Network request failed]
there is nothing wrong with my code, if I type out http://localhost:3001 in my request, everything works fine. What is wrong with my proxy?
app/client/src/setupProxy.js:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
["/api/*",],
/* '/api',*/
createProxyMiddleware({
target: 'http://localhost:3001',
changeOrigin: true,
})
);
};
app/client/components/search.js
...
const callApi = async () => {
console.log("calling the test")
const response = await fetch('http://localhost:3001/api/hello');
//that without proxy would work
const response = await fetch('/api/hello');
const body = await response.json();
if (response.status !== 200) throw Error(body.message);
console.log("body", body)
return body;
};
...
<Button title="test" onPress={callApi}>press test</Button>
...
my serverside code:
app/server/index.js
const express = require('express');
const router = express.Router();
module.exports = app => {
app.use(router.get('/api/hello', (req, res) => {
console.log("incoming req success")
res.send({ express: 'Hello From Express' });
}))
};

Axios frontend doesn't seem to pass request parameters to backend

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}

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);
});

GraphQL - POST body missing. Did you forget use body-parser middleware?

I keep getting the following error on my graphql queries and not sure why:
POST body missing. Did you forget use body-parser middleware?
Am I doing something weird here? I have tried different recommendations with body-parser online, but still can't seem to fix it.
Server:
require('babel-polyfill')
const express = require('express')
const router = require('./middleware')
const expressStaticGzip = require('express-static-gzip')
const app = express()
const port = process.env.EXPRESS_PORT || 4000
const bodyParser = require('body-parser')
app.use(/\/((?!graphql).)*/, bodyParser.urlencoded({ extended: true }))
app.use(/\/((?!graphql).)*/, bodyParser.json())
app.use('/search/data', expressStaticGzip('public'))
app.use('/', router)
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
Router
const router = express.Router()
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const { authorization = '' } = req.headers
const universalFetch = (url, opts = {}) => {
return fetch(url, {
...opts,
headers: {
...opts.headers,
authorization,
},
})
}
const request = createRpcClient(universalFetch)
const methods = {}
const catalog = Object.keys(methods).reduce((catalog, method) => {
catalog[method] = params => request(methods[method], params)
return catalog
}, {})
return { catalog, fetch: universalFetch }
},
})
router.use(bodyParser.json())
router.use(bodyParser.text({ type: 'application/graphql' }))
router.use('*', renderer)
server.applyMiddleware({ app: router })
In my particular case the client just missed "Content-type" header with 'application/json' value. After adding that the error message has dissapeared.
applyMiddleware already adds body-parser for the GraphQL endpoint -- there's no need to apply it again and doing so may be causing your issue.
Additionally, I would expect applyMiddleware to be called before router.use('*', renderer) -- otherwise, I would think the wildcard route would be used for /graphql as well?
I forgot the header content-type: application/json
This error also caused by incorrect json in the body or some other problems in the body, such as unnecessary wrong invisible chars. So check generated json for errors and what is actually presents in the request body.
This error can also be raised because the body is too large.
I got it with apollo-server-micro inside a custom api route of NextJs.
It can be fixed by calling the json function coming from micro before apollo gets the request :
import { json } from 'micro'
import { ApolloServer } from 'apollo-server-micro'
const server = new ApolloServer({/*config*/})
const raiseBodyLimit: (handler: NextApiHandler) => NextApiHandler = (
handler
) => async (req, res) => {
if (req.headers['content-type'] !== 'application/json') {
return handler(req, res)
}
await json(req, { limit: '1gb' }) // This is the trick to raise body limit
return handler(req, res)
}
export default raiseBodyLimit(
server.createHandler({
path: '/api/graphql',
})
)
I saw this in this apollo-server's github issue.
Here are some information to build an apollo server endpoint with next.js
if your api upload anything you need to add the
{
uploads:true
}
in middleware while using graphql

Resources