Get body POST request in Moleculer - node.js

I use Fetch in ReactJs to send a request to api Moleculer like this :
var data ={
'ordername' : 'PUG',
'receivername' : 'AnSama'
}
fetch(url,{
method: 'POST',
header: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body : data
})
.then(res => {return res.json()})
.then(
(result) => {
alert(JSON.stringify(result));
},
(error) => {
alert('error');
}
)
Then, I want to get body of request in Moleculer (Framework of NodeJS). How can i do?

In Moleculer API Gateway the JSON body is always parsed and reachable via ctx.params. If you want to send header values to the service, use the onBeforeHook in router settings.
broker.createService({
mixins: [ApiService],
settings: {
routes: [
{
path: "/",
onBeforeCall(ctx, route, req, res) {
// Set request headers to context meta
ctx.meta.userAgent = req.headers["user-agent"];
}
}
]
}
});

In addition to the #Icebob answer, If your POST API process request Asynchronously(most likely it will)& returning a promise. Here is an example(This is how we are using) :
actions : {
postAPI(ctx) {
return new this.Promise((resolve, reject) => {
svc.postdata(ctx, (err, res) => {
if (err) {
reject(err);
} else {
resolve(res);
}
});
})
.then((res) => {
return res;
}, (err) => {
return err;
});
}
}

Related

Why is react not posting res.json() to console?

I have tried so many thing but my react app is not recieving jsonData variable or res as a return from the node app. The app is working and printing to console on the node side but I can't get it to print onto the react side.
const submitForm = async (event) => {
event.preventDefault(); // Prevent default submission
const data2 = document.getElementById("miles").value;
const data =
"passenger_vehicle-vehicle_type_" +
carType +
"-fuel_source_" +
vehicleType +
"-engine_size_na-vehicle_age_na-vehicle_weight_na";
axios
.post(`http://localhost:8000/api/vehicle/`, { data, data2 })
.then((res) => {
const returnText = res.json();
console.log(returnText);
return res.json();
})
.then((jsonData) => {
console.log(jsonData);
return;
})
.catch((error) => {
console.log("got errr while posting data", error);
});
};
I edited out the api and api key.
var fetch = require('node-fetch');
exports.vehicle = (req, res) =>{
let status;
const { data, data2 } = res.body;
const values = {
"emission_factor": data,
"parameters": {
"distance": parseInt(data2),
"distance_unit": "mi",
},
};
fetch('https://AAAAAAAAAAAAAAAA', {
method: 'POST',
headers: {
'Authorization': 'Bearer MYAPIKEY',
'Content-Type': 'application/json'
},
body: JSON.stringify(values)
})
.then((res) => {
status = res.status;
return res.json()
})
.then((jsonData) => {
console.log(jsonData);
console.log(status);
return jsonData
})
.catch((err) => {
// handle error
console.error(err);
});
res.send(req.body);
}
Working code thanks for the help:
const submitForm = async (event) => {
event.preventDefault(); // Prevent default submission
const data2 = document.getElementById("miles").value;
const data =
"passenger_vehicle-vehicle_type_" +
carType +
"-fuel_source_" +
vehicleType +
"-engine_size_na-vehicle_age_na-vehicle_weight_na";
axios
.post(`http://localhost:8000/api/vehicle/`, { data, data2 })
.then((res) => {
console.log(res.data);
return;
})
.catch((error) => {
console.log("got err while posting data", error);
});
};
Node solution in comments.
The functions inside your then() statements need to return data e.g. then((res) => {return res.json()})
You have two problems here...
Client-side, you seem to be mixing up an Axios response with a fetch() Response. You want res.data, not res.json(). Since you've tagged this with reactjs, here is where you would set the data to a state value, eg
axios.post(...).then(res => {
setSomeState(res.data)
})
Server-side, you aren't waiting for your fetch request to complete. I'd recommend using an async function
exports.vehicle = async (req, res) => {
try {
const { data, data2 } = req.body
const values = {
"emission_factor": data,
"parameters": {
"distance": parseInt(data2),
"distance_unit": "mi",
},
}
// don't mix up the Express "res" with the fetch "response"
const response = await fetch('https://AAAAAAAAAAAAAAAA', {
method: 'POST',
headers: {
'Authorization': 'Bearer MYAPIKEY',
'Content-Type': 'application/json'
},
body: JSON.stringify(values)
})
if (!response.ok) {
throw new Error(`${response.status}: ${await response.text()}`)
}
res.json(await response.json()) // respond with the data
} catch (err) {
console.error(err)
res.status(500).send(err)
}
}

How to send parameters through axios get method in react?

I have a axios GET method and I need to pass parameters with the get request. I am calling the GET method in Client side (React.js) like this,
const [Cart] = useState([]);
const user = {
userId : session.userId
};
console.log(user);
useEffect((user) => {
if(session.userId !== null){
//Axios.get('http://localhost:5000/api/cart/getCart', user) <- I tried both these ways
Axios({
method: 'GET',
url: 'http://localhost:5000/api/cart/getCart',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
data: {},
params: {
"userId" : session.userId
}
})
.then(res => {
const cart = res.data;
let tempProducts = [];
cart.data.forEach(item => {
const singleItem = {...item};
tempProducts = [...tempProducts, singleItem];
});
this.setState(() => {
return {Cart: tempProducts};
});
})
}
console.log(Cart)
});
But in server side (node.js), it doesn't get the parameter value.
router.get('/getCart', (req, res) => {
console.log(req.body.userId) //This gives the output as undefined
User.findOne({_id: req.body.userId}
,(err, userInfo) => {
res.json(userInfo.Cart);
})
});
I implemented the uncommented axios.get request by referring to this. Can you please help me to find the error? Or can you suggest me any other method to do this? Thanks
UseEffect :
axios.get('/api', {
params: {
foo: 'bar'
}
});
Server :
function get(req, res, next) {
let param = req.query.foo
.....
}

Always get 502 error when calling AWS lambda endpoint from Node Js using `requestjs`

trying to post data in our AWS serverless api using Nodejs Request package but always get 502 error and can post data from the front end app (React or Jquery).
var dataToPost = {
name: 'ABC',
address: 'XYZ'
}
request(
{ method: 'POST'
, uri: 'url here...'
, headers: {
'User-Agent': 'request'
} , multipart:
[ { 'content-type': 'application/json'
, body: JSON.stringify(dataToPost)
}
]
}
, function (error, response, body) {
if(response.statusCode == 201){
console.log('document saved')
} else {
console.log('error: '+ response.statusCode)
console.log(body)
}
}
)```
If you are able to post data using react and Jquery then probably you are not making a post request correctly.Try this code for post request :
const request = require('request');
var dataToPost = {
name: 'ABC',
address: 'XYZ'
}
const options = {
url: 'url goes here',
json: true,
body: dataToPost
};
request.post(options, (err, res, body) => {
if (err) {
return console.log(err);
}
console.log(`Status: ${res.statusCode}`);
console.log(body);
});
Alternatively you can also use axios which makes code more readable and have inbuilt promise support:
const axios = require('axios');
var dataToPost = {
name: 'ABC',
address: 'XYZ'
}
const url = 'put url here'
axios.post(url, data)
.then((res) => {
console.log(`Status: ${res.status}`);
console.log('Body: ', res.data);
}).catch((err) => {
console.error(err);
});
Also check what does AWS Lmbada logs says.

How to convert fetch to axios

I have the following piece of code which is working perfect. However, my task is to replace fetch with axios. can you please guide, what would be the correct replacement of code in axios?
const create = async (credentials, software) => {
return await fetch('/api/software/create', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
credentials: 'include',
body: JSON.stringify(software)
})
.then((response) => {
return response.json()
}).catch((err) => console.log(err))
}
create({ t: jwt.token }, data)
.then((data) => {
if (data.error) {
this.setState({ error: data.error })
} else {
this.props.dispatch(initSoftware()); //if successful get the list of softwares in redux store
}
})
The data variable is an object which hold the req.body equivalent...
The above code is written in react and the create() is called within onSubmit eventhandler.
I am sure if I use axios the create() would be eliminated.. but how? Please guide..
It shouldn't be too different than what you currently have but something like this...
const create = async (credentials, software) => {
return await axios({
url: '/api/software/create'
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
withCredentials: true,
data: JSON.stringify(software)
})
.then((response) => {
return response.data;
}).catch((err) => console.log(err))
}
create({ t: jwt.token }, data)
.then((data) => {
if (data.error) {
this.setState({ error: data.error })
} else {
this.props.dispatch(initSoftware()); //if successful get the list of softwares in redux store
}
})
Note that the data you would be looking for should be in a property called data.
For more, check out the API references here.
2021 answer: just in case you land here looking for how to make GET and POST Fetch api requests using async/await or promises as compared to axios.
I'm using jsonplaceholder fake API to demonstrate:
Fetch api GET request using async/await:
const asyncGetCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncGetCall()
Fetch api POST request using async/await:
const asyncPostCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
});
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncPostCall()
GET request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
POST request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
})
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
GET request using Axios:
const axiosGetCall = async () => {
try {
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosGetCall()
POST request using Axios:
const axiosPostCall = async () => {
try {
const { data } = await axios.post('https://jsonplaceholder.typicode.com/posts', {
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosPostCall()

How to connect to a third party API from node.js using Express.js

I am trying to connect to a third party api with authorization key but no luck. Any suggestion/direction/comment would be appreciated.
server.js
...
app.get('/products', (req, res) => {
request.get(BASE_URL, {
'auth': {
'bearer': 'abcdsfegete'
}
}).on('error', function (error) {
console.log(error);
}).on('response', function (response) {
console.log(response);
})
res.send();
})
...
Result: I keep getting "This response has to data available".
The issue seems to be the properties were wrong (auth, bearer). So basic authentication is used instead.
app.get('/products', (req, res) => {
const options = {
url: BASE_URL + '/products',
headers: {
'Authorization': 'abcdefghghgh',
'Accept': 'application/json'
}
};
request.get(options).pipe(res);
})

Resources