forward the response of http request to the client - node.js

I am invoking a web service through an azure function in node.js with Axios, I have a couple of questions here.
1- in the body of this request I'm hardcoding the value for appUser. however, if I want to run this request on postman and pass the JSON value in the body for appUserwhat changes do I need to do in the code so the param value can pick up what is being passed.
2- the response for this request is only returned in the console of the editor but not getting sent to the client response body (i.e. postman) any idea how to forward the response?
module.exports = async function () {
const axios = require("axios");
const data = {
appUser: "yamen",
};
const headers = {
Authorization:
"Basic WUFNkVQRDg9",
};
{
axios
.post(
"https://tegossl/GetAppUser?company=Enva",
data,
{ headers: headers }
)
.then((response) => {
console.log(`Status: ${response.status}`);
console.log("data: ", response.data);
})
.catch((err) => {
console.error(err);
});
}
};

Related

Nodejs + Axios Post returns undefined value

I am using React + NodeJS & Axios but have been trying to send a post request but experiencing difficulties.
The request seems to be posting successfully, but all actions at the nodejs server is returning in the "undefined" data value, even if the data is passed successfully shown in the console.
REACT
const fireAction = (data1, data2) => {
const data = JSON.stringify({data1, data2})
const url = `http://localhost:5000/data/corr/fire`;
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'AUTHCODE',
}
}
axios.post(url, data, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
fireAction("Oklahoma", "Small apartment")
NODE
app.post('/data/corr/fire', async (req, res) => {
try {
const data = req.body.data1;
console.log(data)
} catch(e) {
res.send({success: "none", error: e.message})
}
});
Result of node: "undefined"
I have added the following body parser:
app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
I am not sure why this error is happening. I see there is similar questions to mine: however none of them are applicable as I'm using both express and body parser which is already suggested.
You're POSTing JSON with a content-type meant for forms. There's no need to manually set content-type if you're sending JSON, but if you want to manually override it, you can use 'Content-Type': 'application/json', and access the response in your route with req.body. If it does need to be formencoded, you'll need to build the form:
const params = new URLSearchParams();
params.append('data1', data1);
params.append('data2', data2);
axios.post(url, params, config);

Node, how to send result back to client from nested HTTP request?

I'm using ReactJS to run my front-end and using Express for my back-end. I want to make a get request to my back-end using the "/paas" path to get a listing of all of my pods that are running inside my namespace in Rancher(Kubernetes).
The back-end then needs to be able to make an https request to my Rancher API endpoint and return the result to the front-end. I can make the successful call to Rancher API and see the data print to the screen on my back-end but I get lost when trying to send this data to the front-end and console log it out inside the browser.
Due to "pre-flight" errors, I can't just make a direct call to the Rancher endpoint inside of my App.js file. More info on this here. So I need to go the custom back-end route. I any case, it seems like this should be pretty straightforward. Any guidance would be appreciated.
App.js:
import React, { useEffect } from "react"
import axios from "axios"
function App() {
useEffect(() => {
const fecthPods = async () => {
try {
const response = await axios.get(`http://localhost:3001/paas`)
console.log(response.data)
} catch (err) {
if (err.response) {
// Not in the 200 response range
console.log(err.response.data)
console.log(err.response.status)
console.log(err.response.headers)
} else {
console.log(`Error: ${err.message}`)
}
}
}
fecthPods()
},[])
return (
<div>
Hello World!
</div>
);
}
export default App;
Back-end server.js:
import express from "express"
import cors from "cors"
import https from "https"
import bodyParser from "body-parser";
const app = express()
app.use(cors())
app.use("/data", (req, res) => {
res.json({ name: "Minion", favFood: "pizza"})
})
app.get("/paas", bodyParser.json(), (req, res) => {
const options = {
hostname: "k8.fqdn.com",
port: 443,
path: "/k8s/clusters/c-wwfc/v1/pods/mynamespace",
method: "GET",
headers: {
Authorization: "Bearer token:12345"
}
}
const request = https.get(options, (res) => {
let responseBody = ""
res.setEncoding("UTF-8")
res.on("data", (chunk) => {
console.log("---chunk", chunk.length);
responseBody += chunk;
});
res.on("end", () => {
let json = JSON.parse(responseBody)
// console.log(responseBody)
console.log("Response finished");
res.json({data: responseBody})
});
});
request.end()
res.json({ status: "complete", data: request.data})
})
app.listen(3001)
console.log("backend up on 3001")
I see a couple of errors on your backend code.
First, you are naming the res variable for the express middleware and also for the response received by the https module. In this way, you lose the possibility to access to the express response object in the on.('end') callback.
Secondly, you are triyng to respond to the client multiple times (inside the on.('end') callback and also directly inside the express middleware with the instruction res.json({ status: "complete", data: request.data}). Also, consider that the code you wrote is repliyng to the client before the call to the k8s cluster is made. And the response will always be a JSON with this data: { "status": "complete", "data": undefined}.
To fix all, try with this code (I will try to comment all edits):
app.get("/paas", bodyParser.json(), (req, res) => {
const options = {
hostname: "k8.fqdn.com",
port: 443,
path: "/k8s/clusters/c-wwfc/v1/pods/mynamespace",
method: "GET",
headers: {
Authorization: "Bearer token:12345"
}
}
const k8sRequest = https.get(options, (k8sResponse ) => { // as you can see I renamed request and res to k8sRequest and k8sResponse, to avoid loosing the scope on req and res express middleware variables
let responseBody = ""
res.setEncoding("UTF-8")
k8sResponse.on("data", (chunk) => { // here use k8sResponse to collect chunks
console.log("---chunk", chunk.length);
responseBody += chunk;
});
k8sResponse.on("end", () => { // here use k8sResponse again
let json = JSON.parse(responseBody)
// console.log(responseBody)
console.log("Response finished");
res.json({ status: "complete", data: responseBody}) // here use the express res variable, to reply to the client.
});
});
k8sRequest.end() // here use the k8sRequest variable to make the https call to the k8s cluster
// here I deleted the res.json instruction
})
The above code should just works. Anyway, I suggest you using axios also with your backend service. You are already using it with React, so you know how to use it. The syntax is minimal and easier and you can use the async/await approach.
Axios solution:
import axios from "axios"
app.get("/paas", bodyParser.json(), async (req, res) => {
try {
const url = 'https://k8.fqdn.com/k8s/clusters/c-wwfc/v1/pods/mynamespace'
const k8sResponse = await axios.get(url, headers: {
Authorization: "Bearer token:12345"
})
res.json({ status: "complete", data: k8sResponse.data })
} catch (e) {
res.json({status: "error", data: e.response.data})
}
})
You should wrap your axios call inside a try/catch block to properly handle errors like you are doing with your React implementation. Error handling should be also implemented if you still want you the native node.js https module

Can't Find Response Headers in an NodeJS - ExpressJS App

I have set up a simple api request using node/express.js to access the Feedly Dev Api: https://developer.feedly.com/. The Feedly Api comes with two response headers -- X-Ratelimit-Count and X-Ratelimit-Reset. The problem is that I can't figure out how to access.
Here is the relevant parts of my express.js file:
app.get('/feedly', async (request, response) => {
const apiUrl =
'https://cloud.feedly.com/v3/streams/contents?streamId=user/[USER_ID]/category/global.all'
const fetchResponse = await fetch(apiUrl, {
headers: {
Authorization: `Bearer ${process.env.FEEDLY_ACCESS_TOKEN}`
}
})
const json = await fetchResponse.json()
response.json(json)
response.end()
})
what do I have to do in order to see both X-Ratelimit-Count and X-Ratelimit-Reset response headers?
Thanks.
Fetch API: Headers
(async() => {
const fetchResponse = await fetch("https://httpbin.org/anything");
console.log(fetchResponse.headers.get('X-Ratelimit-Count'))
console.log(fetchResponse.headers.get('X-Ratelimit-Reset'))
fetchResponse.headers.forEach((v, k) => console.log(`${k}: ${v}`));
})();

How to pass Authorization token from ReactJS to NodeJS request

I'm try to pass the 'token_mailchimp' from axios get request to nodejs request get
For the moment i pass the auth token from a variable directly in app.js in my node/express project.
app.js in node/express project
app.get('/mailchimp/campaigns', checkAuth, function (req, res) {
request
.get('https://' + mailchimpInstance + '.api.mailchimp.com/3.0/campaigns')
.set('Content-Type', 'application/json;charset=utf-8')
.set('Authorization', 'Basic '+token_mailchimp)
.end((err, result) => {
if (err) {
res.status(500).json(err);
} else {
res.json(result.body);
}
});
});
axios get request in ReactJS project
.get('http://localhost:8081/mailchimp/campaigns',
{ headers: {"Authorization" : `Bearer `+jwt_token} })
.then(({ data })=> {
this.setState({
campaigns: data.campaigns
});
})
.catch((err)=> {})
How can i pass from axios request the auth token for the request /mailchimp/campaigns?
You can send a new custom header like x-api-token
{ headers: {"Authorization" : Bearer+jwt_token, "x-api-token" : "your_token"} }
Then in the app.js, access the headers from the request,
const {headers} = req;
Then use that in your API request
.set('Authorization',`Basic ${headers["x-api-token"]}`)
Note: If you are using cors plugin then make sure it's allowing that header to pass.
You can add header x-api-token manually in cors configuration if needed.

Axios does not return the error in the frontend

I'm using Axios to consume an API on my backend with the NODEJS + EXPRESS ...
After this, I use Axios in my frontend with ES6 + JAVASCRIPT ORIENTED TO OBJECTS ...
What happens is the following, if I get through my backend in the API route, it returns me the error when it is to return, and returns me the date when it is to return ...
But in my frontend, the axios catch does not work because it returns me inside my date error and does not change status and statusText.
I would like to know why this happens, and fix on my backend into the "date" attribute it returns me the result when there is no error, and when there is error it change the "status" and "statusText" attribute of the Axios response to the catch on the frontend will work ..
BACKEND CONTROLLER CODE (NODEJS CONSUME API):
module.exports.consume = (app, req, res) => {
// PARAMS && QUERYS
const xsjs = req.params.urn;
const shoppingId = req.query.Shop,
periodOf = req.query.PeriodOf,
periodUntil = req.query.PeriodUntil,
kpi = req.query.Kpi,
select = req.query.Select;
// API_DAO.JS (CLASS)
const apiDAO = new app.models.apiDAO(xsjs, shoppingId, periodOf, periodUntil, kpi, select);
apiDAO.getResponseAxios().then ( response => res.json(response.data) )
.catch ( error => res.json({ ErrorStatus: error.response.status, ErrorText: error.response.statusText }) );
}
AXIOS IN MY FRONTEND
class Api {
constructor(xsjs, shoppingId, periodOf, periodUntil, kpi, select){
this.xsjs = xsjs;
this.shoppingId = shoppingId;
this.periodOf = periodOf;
this.periodUntil = periodUntil;
this.kpi = kpi;
this.select = select;
}
configAxios(){
return axios.create({
baseURL: 'http://localhost:3000/api/',
method: 'GET',
responseType: 'json',
responseEncoding: 'utf8',
headers: {
'Content-Type': "application/json",
'Cache-Control': "no-cache",
},
params: {
Shop: this.shoppingId,
PeriodoDe: this.periodOf,
PeriodoAte: this.periodUntil,
Kpi: this.kpi,
Select: this.select
}
});
}
async consume(){ return await this.configAxios().get(`/${this.xsjs}?`); }
}
Axios Error Response on the Frontend
Note that it inserts within the date attribute the errors and does not change the status or statusText out of the date attribute. (This should be wrong, as there was an error in the API query on my backend)
Axios Response, when executed with Parameters and Query correctly
The issue is inside .catch callback. There was an error on your backend side but after catching it you send a normal JSON response with default 200 status code:
.catch(error => res.json({ ErrorStatus: error.response.status, ErrorText: error.response.statusText }) );
If you want your backend to respond with HTTP error you need to set HTTP status code in a different way:
.catch(error => res.status(error.response.status).send(error.response.statusText);

Resources