EXPRESS : How to prevent Fetch() to repond with cached response - node.js

I am facing a very strange issue, I have a middleware where I am making a fetch() call to my API from my Express APP. it looks like :
Middlware Function
export function handler (req, res, next) {
if (someURL) {
return fetch(someURL, {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
},
credentials: 'include',
cache: 'no-store'
})
.then((response) => response.json())
.then((response) => {
log.info(`called response${response}`);
log.info(`called response status${response.status}`);
if (response.status && response.status === 'SUCCESS') {
res.clearCookie('master', { httpOnly: true, secure: true, domain: 'someDomain' });
return next();
}
throw Error(response.statusText);
})
.catch((error) => {
next(error);
});
}
}
here When I hit that URL that is intercepted with this Middleware, I want the cookie to be cleared and for that i am using the Header with the details above. But When I make this call I get the 200 OK from the disc written in the chrome network tab and call does not work properly as the cookie expiration headers coming from the APIs are not getting rendered. Can someone Point out what is wrong and how can I stop this caching in-order to get these cookies deleted?
thanks in advance

Related

Empty request body in server, Object object into DB

I'm using NodeJS+express and React. The request body's expected output is "tipologia", but it actually returns an empty object.
I have looked for similar questions (there a lot of them) but none of these is useful.
client:
function CreateStudyPlan(tipologia){
return new Promise((resolve, reject) => {
fetch((URL+'/PianoStudio'), {
method: 'POST',
credentials: 'include',
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(tipologia),
}).then((response) => {
if (response.ok) {
resolve(null);
} else {
// analyze the cause of error
response.json()
.then((message) => { reject(message); }) // error message in the response body
.catch(() => { reject({ error: "Cannot parse server response." }) }); // something else
}
}).catch(() => { reject({ error: "Cannot communicate with the server." }) }); // connection errors
});
}
server:
// set-up the middlewares
app.use(morgan('dev'));
app.use(express.json());
const corsOptions = {
origin: 'http://localhost:3000',
credentials: true,
};
app.use(cors(corsOptions));
const isLoggedIn = (req, res, next) => {
if(req.isAuthenticated())
return next();
return res.status(401).json({ error: 'not authenticated'});
}
app.post('/PianoStudio', isLoggedIn, async (req, res) => {
try {
await dao.createPianoStudio(req.body, req.user.id);
res.status(201).json(req.body);
} catch(err) {
console.log(err);
res.status(503).json({error: `Database error during the creation of piano di studi for user ${req.user.id}.`});
}
});
The problem is that req.body is empty and should not be ( i am expecting it to output part-time):
The insert into the DB shows that req.user.id is ok, while req.body is an empty Object:
--
2 WORDS ON REQUEST ID AND BODY:
req.body should be the
body: JSON:Stringify(tipologia)
from the client, while req.user.id is retrieved by the session through the isLoggedIn.
2 WORDS ON HEADERS:
At first i had
headers: {
'Content-Type': 'application/json',
But it gave me CORS error:
Access to fetch at 'http://localhost:3001/PianoStudio' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
So i changed the Headers to
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*"
}
as
putting 'Content-Type': 'application/json', returns again CORS error.
You should try to define tipologia as an object, in the Client:
body: JSON.stringify({tip_str: tipologia})
While in your Server, you will retrieve your tipologia as follows:
dao.createPianoStudio(req.body.tip_str, req.user.id)

React NextJs: how to render a page after fetching data to the server-side?

Usually, I send the data in react to the server-side like this:
e.preventDefault();
await fetch(process.env.NEXT_PUBLIC_DR_HOST, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: body,
}).then(res =>
{
window.location = res.url;
})
And if there is an error within the sent data, a 400 error is thrown and the request is sent to the error middleware:
server.use((err, req, res, next) =>
{
const error = new ServerError(err.message, err.status)
res.status(error.status)
res.redirect("/create") //this could be anything
})
As you might guess the code above works fine. But what if I want to render something instead of redirect to another url?
server.use((err, req, res, next) =>
{
const error = new ServerError(err.message, err.status)
res.status(error.status)
app.render(req, res, "/error", { error }) //replaced readirect with app.render
})
Rendering a page leads to no response .then(res =>{ window.location = res.url }) and the page remains untouched. How can I create something similar to the redirect method but with app.render instead?

express redirect got response 304 and do nothing

frontend is react and request to server use Fetch .
code like this .
fetch(`/ONETOWN/LARK/PACKAGE/STOCKOUT/LOAD_LIST_BY_TELL`,{
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
credentials: 'include',
body: JSON.stringify(info)
})
the backend(server) code like this,cookie expired,so i hope redirect to unauthorized page .
static authentication(req,res) {
if(this.verifyCookie(req,res)) {
return true;
}
//res.status(401).end();
res.redirect('/#/page/unauthorized');
return false;
}
my Web don't redirect to the path i want,still stay the original page
if Redirect change to Location method
res.location('/#/page/unauthorized').end()
got response 200
got response 200
The thing is that you are using a fetch call to make an HTTP call, so your browser is not making a request, so it knows nothing that it needs to open a different page.
The solution is to check the response of your fetch call and make a redirect to the different page if needed.
thanks #Ayzrian, i have change my code logic to fix this problem . you are right , i shoud do redirecting in frontend , check server response's status(401) , code like this .
enter code here
fetch(`url`,{
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
credentials: 'include',
body: JSON.stringify(info)
})
.then(res => Authentication(res))
.then(res => res.json())
.then(json => {
}).catch((e) => {
if (e.status === 401) {
console.log(e);
window.location="#/page/unauthorized";
}
});
};
.......................
export const Authentication = (res) => {
if (res.ok) {
return res;
} else {
return Promise.reject({
status: res.status,
statusText: res.statusText
});
}
}
................
static authentication(req,res) {
if(this.verifyCookie(req,res)) {
return true;
}
res.status(401).end();
//res.redirect('/#/page/unauthorized'); not works
return false;
}

Axios Proxy Configuration causing Bad Request

I am trying to send a request to the particle cloud from a NodeJS application.
I am using Axios to make the PUT request. The application sends the request through a proxy server which is configured as well.
// axios proxy - not working
axios.default.put("https://api.particle.io/v1/devices/<deviceId>/ping", {}, {
proxy: {host: <proxy_ip>, protocol:'http', port:<port_no>},
headers: {
authorization: "Bearer <access_token>"
}
}).then((response) => {
console.log("Success", response.data);
}).catch((error) => {
console.log("Failed", error);
});
Error Message: Request failed with status code 400
When I send this request I get a 400 Bad Request response from the particle cloud.
But when I send the same request using the request module of NodeJS, the request is successful.
var options = {
method: 'PUT',
url: 'https://api.particle.io/v1/devices/<device_id>/ping',
proxy: {hostname: <proxy_ip>, protocol:'http', port:<port_no>},
headers:
{
authorization: 'Bearer <access_token>'
},
form: false
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(response);
});
Response: body: '{"online":false,"ok":true}'
The request also works when the application was deployed on the open network and axios was used without the proxy configuration.
// axios without proxy - working
axios.default.put("https://api.particle.io/v1/devices/<deviceId>/ping", {}, {
headers: {
authorization: "Bearer <access_token>"
}
}).then((response) => {
console.log("Success", response.data);
}).catch((error) => {
console.log("Failed", error);
});
Questions:
Why is the request from Axios failing with proxy configuration?
Is this an inherent issue with Axios?
Regards.
Axios itself has a bug which isnt fixed yet.
To overcome this issue, https-proxy-agent can be used instead of axios proxy.
const HttpsProxyAgent = require('https-proxy-agent')
axios.default.put("https://api.particle.io/v1/devices/<deviceId>/ping", {}, {
headers: {
authorization: "Bearer <access_token>"
},
proxy: false,
httpsAgent: new HttpsProxyAgent('http://proxy_domain:port')
}).then((response) => {
console.log("Success", response.data);
}).catch((error) => {
console.log("Failed", error);
});

Proxy API request through Express return pending Promise instead of response

I am currently trying to work with the Atlassian Jira rest API. In order to not get a CORS error I go through the recommended route of not sending the request from the browser but proxy it through my express server.
Now as I am doing this, all I receive back in the app is a pending promise. I assume that I have not correctly resolved it at one point but I cant figure out where.
API Handler sending the request to the proxy:
const baseURL = `${apiConfig}/jiraproxy`;
export const testConnection = integration => {
return fetch(`${baseURL}/get`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(integration)
})
.then(handleResponse)
.catch(handleError);
};
Jira Proxy Endpoint on the Express Server
const baseURL = `rest/api/3/dashboard`;
router.post("/get", (req, res) => {
fetch(req.body.link + baseURL, {
method: "GET",
headers: { Accept: "application/json" },
auth: {
username: req.body.credentials.username,
password: req.body.credentials.token
}
})
.then(handleResponse)
.catch(handleError);
});
handleResponse & handle Error Methods:
async function handleResponse(response) {
if (response.ok) {
return response.json();
}
if (response.status === 400) {
const error = await response.text();
throw new Error(error);
}
throw new Error("Network response was not ok.");
}
function handleError(error) {
// eslint-disable-next-line no-console
console.error(`API call failed. ${error}`);
throw error;
}
Goal:
Send the request of sending a request to the proxy and return the resonse of the proxy as the return of the initial "testConction" method.
Error:
No errors thrown, but the response received in the Browser is a pending promise.
Change to the Jira Proxy router fixed it. Thanks to #jfriend00.
router.post("/get", (req, res) => {
return fetch(req.body.link + baseURL, {
method: "GET",
headers: { Accept: "application/json" },
auth: {
username: req.body.credentials.username,
password: req.body.credentials.token
}
})
// This is the part that changed
.then(response => handleResponse(response))
.then(jiraResponse => res.status(200).json(jiraResponse))
.catch(handleError);
});

Resources