Can't set headers after they are sent. in express js - node.js

I am using express package of nodejs and I have written this function to send response for any generic API. Although it keeps giving error and I can't figure out why. status function sets response status so I don't know why this should happen
function ResponseHandler(response, respObj, resData) {
var resp = {
"message" : respObj.message,
"data" : resData
}
response.status(respObj.code);
response.json(resp);
}

This is because you're sending the request back with the .status(number) and then try to send the status again with .json(string). Chain your functions and only one response will be sent.
response.status(respObj.code).json(resp);

You should use the below format:
res.status(500).json({ error: 'message' });
Check the following link to know more details:
https://expressjs.com/en/api.html

app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});

Related

Issue with PUT request in node js

I have below code which is working fine for GET and POST but not for PUT in node js. I am using method overloading for GET and PUT.
const AuthRoutes = Router();
const AppRoutes = Router();
AuthRoutes.get('/customer/:customername', getCustomerbyname);
AuthRoutes.post('/calculate/:id', calculate);
AuthRoutes.put('/customer/:customername', saveCustomer);```
Here my GET and POST is working fine but for PUT its giving me error. Below URL I am trying for PUT.
https://domainname/customer/abc
I dont know what I am missing here.
Error - You don't have permission to access /domainname/customer/abc
Can you please help me if I am missing something here. Basically I am trying to do a PUT request by providing customer name in URL and other details in BODY section of request. So if customer with name exist, it will update it otherwise create it newly. Am I missing any npm package here?
Try this:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
next();
});
I took it from here :
Response

Angular + Expressjs Http failure response Unknown error 0

I'm using Angular 8 and ExpressJS. Everything work perfectly, the app is live and a lot of users (6000) are using it. But there are a few users (less than 10) that get Unknown Error (code 0) from any API call.
This is the error response:
{"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":"https:/xxxxxxxxxx/api/auth/recover-pass","ok":false,"name":"HttpErrorResponse","message":"Http failure response for https://xxxxxxxx/api/auth/recover-pass: 0 Unknown Error","error":{"isTrusted":true}}
I readed it can be an CORS error, but I don't think so. I'm using this
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET");
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, x-access-token");
res.header("Access-Control-Allow-Credentials", true);
next();
});

HTTP 200 but Access-Control-Allow-Origin denied with POST with Dribbble API

I am working in Dribble's API and getting this error message:
XMLHttpRequest cannot load https://dribbble.com/oauth/token?client_id=08b8dec4ee5c7af3edd96e0a27eb97f8…a739&code=2806099a944253b647afe25ba384d68a90ca04158a1d1dceadddfe076de941f0. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:3000' is therefore not allowed access.
I have already tried many different ways to set Access-Control-Allow-Origin = '*' but none of them worked for me, but reading the console.log(res._headers) i can see that it is being defined, i am sending this through a POST request but the header is not working. This one of the ways i have defined in app.js on Express v4 to set the header.
app.all("/", function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS");
res.header("Access-Control-Expose-Headers", "ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset");
res.header("Access-Control-Max-Age", "86400");
res.header("Access-Control-Allow-Credentials", true);
return next();
});
And this is how i am sending the POST request with Axios:
export const postUserOAUTH = code => ((dispatch) => {
axios({
url: `https://dribbble.com/oauth/token?client_id=${clientId}&client_secret=${clientSecret}&code=${code}`,
method: 'post',
}).then((response) => {
dispatch({ type: 'shots', payload: { registerResponse: response.data, token: response.data.access_token } });
console.log('ok')
}).catch((error) => {
dispatch({ type: 'shots', payload: { registerResponse: error.message } });
console.log('error')
});
});
Edit:
Now the problem changed a little, the code status is 200, i received the token in response from my request by the API but still having the same error the code is still going inside the .catch not in the .then, i have attached a link of the Image Error. I don't think this a problem about authentication since i am now getting the response that i want, but with this error i can't work with promises in my code. Step 2. Dribbble redirects back to your site.
It looks like you're trying to set headers on the response object instead of the request (and the headers you are trying to set are headers that the server will set on a successful CORS request). Instead, try this:
app.all("/", function(req, res, next) {
req.header("Origin", "*"); // ideally the '*' will be your hostname
return next();
});
The server should then respond with the headers you were trying to set on the object.
Disclaimer: I don't know Express, this code may not work as written, but hopefully you get the idea.
For more info on CORS check out: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Also, you can see our example setting the Origin header here: http://developer.dribbble.com/v1/#cross-origin-resource-sharing
Cheers,
Ian
Developer # Dribbble

CORS request not working when sending authorization headers

EDIT: Kevin B answered my question in a comment below. I added some logic to send a 200 request if an OPTIONS http request hit my API to fix the problem. Here is the code:
var allowCrossDomain = function(req, res, next) {
if ('OPTIONS' == req.method) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
res.send(200);
}
else {
next();
}
};
router.use(allowCrossDomain);
Original Question:
I currently am trying to get an Ionic 2 application running on my localhost to be able to send data to an Express 4 application. It works when I send requests without an authorization header. However, once I added auth headers, my API began to throw errors. I have done my research and have tried to implement what I found here: (https://stackoverflow.com/a/15254158/5379931.
However, I am getting errors still. If I set Access-Control-Allow-Origin like this:
res.header("Access-Control-Allow-Origin", "http://localhost:8100");
I get this error:
XMLHttpRequest cannot load URL. Response to preflight request doesn't pass
access control check: The 'Access-Control-Allow-Origin' header has a value
'http://localhost:8100/' that is not equal to the supplied origin. Origin
'http://localhost:8100' is therefore not allowed access.
If I set my Access-Control-Allow-Origin header like this:
res.header("Access-Control-Allow-Origin", "http://localhost:8100/");
I get this error:
XMLHttpRequest cannot load URL. No 'Access-Control-Allow-Origin' header is
present on the requested resource. Origin 'http://localhost:8100' is
therefore not allowed access. The response had HTTP status code 400.
Here is the rest of my express 4 code that is relevant:
router.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:8100");
res.header("Access-Control-Allow-Headers", "Origin, Authorization, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
next();
});
It looks like you forgot to respond to the options request. By not responding, it will go to your error handler and be dealt with as if it were an error.
Just send a 200 status within your .use if it is an options request so that it doesn't reach your error handler.

CORS in Node.js and AngularJS

I have a CORS problem with my app.
My stack is Node.js with Express 4 and AngularJS using Restangular
I already have tried a few things (for example) but I keep getting:
XMLHttpRequest cannot load http://localhost:8080/api/users. Request header field Content-Type is not allowed by Access-Control-Allow-Headers.
In the server side I have this headers:
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, POST","PUT");
next();
});
In the AngularJS part I am using this:
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
And I am doing the post with Restangular like this:
var baseUsers = Restangular.all('users');
....
....
baseUsers.post(newUser).then(function(user){
console.log(user);
});
One more thing, in the Node.js server I am consoling the req.method and it says OPTIONS, I really don't know why.
Perhaps is something silly, hope someone can help me.
Thanks!
Change -
res.header("Access-Control-Allow-Headers", "X-Requested-With");
TO
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
Source 1
Source 2
I am posting same answer with a detailed code, Because i got some issues when i use the selected answer.
Just pull the code below after initialization of the app object
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
res.header("Access-Control-Allow-Methods", "GET, POST","PUT");
next();
});
I hope this will be little bit more helpful.

Resources