How to show the success response from node server on react-redux framework - node.js

I am making a demo react-redux app for the basic understanding of redux and its server is made on nodeJS. I have made a simple form which gets submitted and the server response is res.send('FORM SAVED'). In front-end, I make the post request but is not able to see the response that returns, be it the success response.
My server controller that responds when form details are saved.
export const postData = (req, res) => {
let p = new PostData();
p.name = req.body.name;
p.emp_id = req.body.emp_id;
p.age = req.body.age;
p.dept = req.body.dept;
p.phone = req.body.phone;
p.gender = req.body.gender;
p.save(((err) => {
if (err){res.send(`Error in uploading: ${err}`);}
else {res.send('Form saved');}
}));
}
This is my action:-
export const createPost = postData => dispatch => {
fetch(`${Config.address}/post`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
})
.then((post) => {
console.log('post:', post);
dispatch({
type: NEW_POST,
payload: post
})
})
}
This is how I call this in component after clicking submit:-
onSubmit = (e) => {
e.preventDefault();
let postData = {
name: this.state.name,
emp_id: this.state.emp_id,
dept: this.state.dept,
gender: this.state.gender,
age: this.state.age,
phone: this.state.phone
}
this.props.createPost(postData);
}
I want to get the response string ('Form saved') but I don't know how to read that. Can anyone help? Thanks in advance

fetch returns a raw response object. To get an expected data you should call a .json() method on raw response object which is returned by fetch, like below:
export const createPost = postData => dispatch => {
fetch(`${Config.address}/post`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
})
.then(response => response.json()) // add this line
.then((post) => {
console.log('post:', post); // you should get an object with `Form saved` or something similar to it
dispatch({
type: NEW_POST,
payload: postData // replace it to the input parameter
})
})
}
Using async/await it becomes more readable:
export const createPost = (postData) => async (dispatch) => {
// send postData to server
const rawResponse = await fetch(`${Config.address}/post`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
});
// we are done with server but we need one more step
// turn a raw response to readable JS object
const message = await rawResponse.json()
// message from server response
console.log('Message ', message);
// store same object as we sent to server in redux store
dispatch({ type: NEW_POST, payload: postData });
}
Hope it helps

Related

How to hide my API Key in a POST request?

I want to hide my API key when I am making a post request from my browser. I need to input a number plate and send the request to the API and the API responds me with details about it. I have managed to get this working with a GET request to another API by using nodeJS but I can't manage to make it work with a post request. Keep in mind the request needs information from my input field in the browser which is the registration number of the vehicle to send me information back about it.
Here is my function in my browser JS file.
const searchBtn = document.getElementById("search-btn")
function startFetch() {
let plate = document.getElementById("plate").value
let reg = {registrationNumber: `${plate}`}
fetch(`https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': `my key is here`,
},
body: JSON.stringify(reg),
})
.then(response => response.json())
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
};
searchBtn.addEventListener("click", startFetch);
Any help and method would be appreciated. Thanks in advance.
For anyone in the same boat. I have managed to achieve what I want.
Client side JS file:
function startFetch() {
let plate = document.getElementById("plate").value
let reg = {registrationNumber: plate}
fetch(`http://localhost:3000/v`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(reg),
})
.then(response => response.json())
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
};
And the backend using Express, NodeJS, body-parser and axios
require("dotenv").config()
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const axios = require('axios');
app.use(bodyParser.json());
app.use(express.static("src"))
//Env vars
const API_URL = process.env.API_URL
const API_KEY = process.env.API_KEY
app.post('/v', (req, res) => {
const body = req.body;
// Make a request to the backend API
axios.post(API_URL, body,
{
headers: {
"Content-Type": "application/json",
'x-api-key': API_KEY
}
}
)
.then((response) => {
// Return the response from the backend API to the client
res.send(response.data);
})
.catch((error) => {
// Handle any errors
res.status(500).send(error);
});
});
app.listen(3000, () => {
console.log('API proxy server is listening on port 3000');
});
You are already sending the body.
A very minor modification to you code:
function startFetch() {
let plate = "abc123";
let reg = { registrationNumber: `${plate}` };
fetch(`https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": `my key is here`,
},
body: JSON.stringify(reg),
}
);
}
startFetch();
You can see your api-key in the header (though you should never send secret via http):
Then in the body (in chrome they call it payload):

Axios POST request to Twillio returns with an Authentication Error?

in Node.js, I am trying to send a POST request with Axios to Twilio and send an SMS message to my phone. But I am getting an 'error: Authentication Error - No credentials provided ? Here is the code:
const body = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Body: 'hi from vsc',
To: toNumber,
From: fromNumber,
};
const headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: `Basic ${accountSID}:${authToken}`,
};
exports.axios = () => axios.post(`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`, body, headers).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
I also tried to use the same parameters with POSTMAN and the POST request is successful. I also tried to encode my authorization username and password to Base 64, but with no success.
I wrote to Twilio customer help but haven`t received any replies yet.
Axios makes an auth option available that takes an object with username and password options. You can use this with the username set to your account SID and password set to your auth token.
The headers object should be sent as the headers parameter of a config object in the third parameter to axios.post. Like so:
const params = new URLSearchParams();
params.append('Body','Hello from vcs');
params.append('To',toNumber);
params.append('From',fromNumber);
const headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
};
exports.axios = () => axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`,
params,
{
headers,
auth: {
username: accountSID,
password: authToken
}
}
}).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
Headers is actually a field of config, try something like this:
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: `Basic ${accountSID}:${authToken}`,
}
}
axios.post(URL, data, config).then(...)
Or this (general example calling a Twilio endpoint)
const axios = require('axios');
const roomSID = 'RM1...';
const participantSID = 'PA8...';
const ACCOUNT_SID = process.env.ACCOUNT_SID;
const AUTH_TOKEN = process.env.AUTH_TOKEN;
const URL = "https://insights.twilio.com/v1/Video/Rooms/"+roomSID+"/Participants/"+participantSID;
axios({
method: 'get',
url: URL,
auth: {
username: ACCOUNT_SID,
password: AUTH_TOKEN
}
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
Working code:
const params = new URLSearchParams();
params.append('Body','Hello from vcs');
params.append('To',toNumber);
params.append('From',fromNumber);
exports.axios = () => axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`,
params,
{
auth: {
username: accountSID,
password: authToken,
},
},
).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
The previous solutions did not work for me. I encountered either the Can't find variable: btoa error or A 'To' phone number is required..
Using qs worked for me:
import qs from 'qs';
import axios from 'axios';
const TWILIO_ACCOUNT_SID = ""
const TWILIO_AUTH_TOKEN = ""
const FROM = ""
const TO = ""
const sendText = async (message: string) => {
try {
const result = await axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${TWILIO_ACCOUNT_SID}/Messages.json`,
qs.stringify({
Body: message,
To: TO,
From: FROM,
}),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
auth: {
username: TWILIO_ACCOUNT_SID,
password: TWILIO_AUTH_TOKEN,
},
},
);
console.log({result});
} catch (e) {
console.log({e});
console.log({e: e.response?.data});
}
};

An problem occur when submit a GET Request by node-fetch

I am using node-fetch to fetch data from REST API.
Here is my code:
this.getUserList = async (req, res) => {
const fetch = require('node-fetch');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
let params = {
"list_info": {
"row_count": 100
}
}
fetch('https://server/api/v3/users?input_data=' + JSON.stringify(params), {
headers:{
"TECHNICIAN_KEY": "sdfdsfsdfsd4343323242324",
'Content-Type': 'application/json',
},
"method":"GET"
})
.then(res => res.json())
.then(json => res.send(json))
.catch(err => console.log(err));
}
It works fine.
However, if I change the following statement:
let params = {"list_info":{"row_count": 100}}
To
let params = {"list_info":{"row_count": 100}, "fields_required": ["id"]}
It prompts the following error message:
FetchError: invalid json response body at https://server/api/v3/users?input_data=%7B%22list_info%22:%7B%22row_count%22:100%7D,%22fields_required%22:[%22id%22]%7D reason: Unexpected end of JSON input`
The problem is that you are not URL-encoding your query string. This can be easily accomplished using URLSearchParams.
Also, GET requests do not have any request body so do not need a content-type header. GET is also the default method for fetch()
const params = new URLSearchParams({
input_data: JSON.stringify({
list_info: {
row_count: 100
},
fields_required: ["id"]
})
})
try {
// 👇 note the ` quotes
const response = await fetch(`https://server/api/v3/users?${params}`, {
headers: {
TECHNICIAN_KEY: "sdfdsfsdfsd4343323242324",
}
})
if (!response.ok) {
throw new Error(`${response.status}: ${await response.text()}`)
}
res.json(await response.json())
} catch (err) {
console.error(err)
res.status(500).send(err)
}

Not able to POST image files to server

I'm trying to send an image to server using POST request but on server side I'm receiving and empty object.
// Client Side
function uploadFile(thumbnailRef) {
const thumbnail = thumbnailRef.current.files[0];
const formData = new FormData();
formData.append('file', thumbnail)
fetch('http://localhost:8080/upload', {
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data'
},
}).then(res => { console.log(res) })
.catch(err => console.log(err))
}
// server side
app.post('/upload', (req, res) => {
console.log(req.body) // getting empty - {}
res.end()
})
I think it should work if you remove headers. Like this:
function uploadFile(thumbnailRef) {
const thumbnail = thumbnailRef.current.files[0];
const formData = new FormData();
formData.append('file', thumbnail)
fetch('http://localhost:8080/upload', {
method: 'POST',
body: formData,
}).then(res => { console.log(res) })
.catch(err => console.log(err))
}

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()

Resources