I'm trying to write things as nice and semantic as possible, but I am running into an issue where I'm not sure how to express myself succinctly. I was doing the following in a callback in node:
res.send(500, { error: err }) if err?
res.send(resource) if resource?
res.send 404
return
However, I throw header already sent errors all over the place... Ideally I want to do something like:
res.send(500, { error: err }) if err? else
res.send(resource) if resource? else
res.send 404
return
or
res.send(500, { error: err }) if err?
else res.send(resource) if resource?
else res.send 404
Where I can keep things succinct and easy to follow. Sadly, this causes the compiler to explode. So as a result, unfortunately I'm stuck with stuff like:
if err?
res.send 500, error: err
else
if resource
res.send resource
else
res.send 404
Which doesn't feel that coffee to me, I almost might as well be writing normal javascript.
So I'd appreciate anyone who can help me figure out a nice way to do logic trees like this in a prettier way.
Consider what you're doing. Ultimately, your goal is to send something according to a cascade of rules: Error, Success, or Not Found. Coffeescriptly, I'd end up writing:
res.send.apply null, if err then [500, {error: err}] else if resource then [resource] else [404]
Which, admittedly, is a little long, but that's what we have IDEs for.
[Edit]
r = if err then [500, {error: err}] else if resource then [resource] else [404]
res.send.apply null, r
There, now both lines are less than 80 characters.
Related
Axios gives us the interception ability. I have created a response interceptor to get errors.
This is my code:
const errorInterceptor = error => {
if (error.code === 'ERR_NETWORK') {
throw new Error('Network is not connected')
}
// The rest of the code
}
However, if I get the CORS error, I can't find any information to know that it was a CORS error.
Why do I need this?
I want to provide meaningful messages to my users.
If network is disconnected, I want to show You are not connected to the internet. If it's CORS, I want to show API is not configured properly for CORS, please inform the administrator.
How can I know whether the error is CORS or not?
I have created an interceptor and I have tried to extract data from it.
axios.interceptors.response.use((response) => response, (error) => {
if (typeof error.response === 'undefined') {
alert('A network error occurred. '
+ 'This could be a CORS issue or a dropped internet connection. '
+ 'It is not possible for us to know.')
}
return Promise.reject(error)
})
When this part of my code gets executed:
req.login(user, function (err){
if (err) return res.negotiate(err);
return res.redirect('/welcome');
});
I get the following error:
/home/oriol/Desktop/containers/node_modules/sails-mongo/node_modules/mongodb/lib/utils.js:98
process.nextTick(function() { throw err; });
^
Error: passport.initialize() middleware not in use
at IncomingMessage.req.login.req.logIn (/home/oriol/Desktop/containers/node_modules/passport-local/node_modules/passport/lib/passport/http/request.js:30:30)
at /home/oriol/Desktop/containers/api/controllers/AuthController.js:37:15
at wrapper (/home/oriol/Desktop/containers/node_modules/lodash/index.js:3592:19)
at applyInOriginalCtx (/home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/utils/normalize.js:421:80)
at wrappedCallback (/home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/utils/normalize.js:324:18)
at success (/home/oriol/Desktop/containers/node_modules/waterline/node_modules/switchback/lib/normalize.js:33:31)
at _switch (/home/oriol/Desktop/containers/node_modules/waterline/node_modules/switchback/lib/factory.js:58:28)
at /home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/query/dql/create.js:248:9
at /home/oriol/Desktop/containers/node_modules/async/lib/async.js:52:16
at /home/oriol/Desktop/containers/node_modules/async/lib/async.js:269:32
at /home/oriol/Desktop/containers/node_modules/async/lib/async.js:44:16
at child.<anonymous> (/home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/utils/schema.js:152:44)
at fn (/home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/utils/callbacksRunner.js:60:10)
at /home/oriol/Desktop/containers/node_modules/async/lib/async.js:181:20
at iterate (/home/oriol/Desktop/containers/node_modules/async/lib/async.js:262:13)
at Object.async.forEachOfSeries.async.eachOfSeries (/home/oriol/Desktop/containers/node_modules/async/lib/async.js:281:9)
at Object.async.forEachSeries.async.eachSeries (/home/oriol/Desktop/containers/node_modules/async/lib/async.js:214:22)
at Object.runner.afterCreate (/home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/utils/callbacksRunner.js:63:9)
at after (/home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/query/dql/create.js:243:17)
at /home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/query/dql/create.js:230:68
at wrapper (/home/oriol/Desktop/containers/node_modules/lodash/index.js:3592:19)
at applyInOriginalCtx (/home/oriol/Desktop/containers/node_modules/waterline/lib/waterline/utils/normalize.js:421:80)
I have read other posts about the same issue but none of them seems to fix it. I don't know much about why is this happening, feel free to ask for further explanation or any piece of code that might be relevant. Thanks!
I just found out now how to solve that. This question can be closed.
I did this for the second time and somehow it worked: Sails.js + Passport.js: passport.initialize() middleware not in use.
My problem with Angular 2 that was not exist in AngularJS, that I was sending the error message as a string with backend API call in case I have error, with error status 401 as example, the problem now that I can't read this message from Angular2 http response message, while I can do that from AngularJS:
I tried the following codes and nothing was helpful:
Promise:
this._http.post('/login',{email: 'email#example.com', password: '123'})
.toPromise()
.then((resp) => console.log(resp), (error) => console.log(error));
Observable:
this._http.post('/login',{email: 'email#example.com', password: '123'})
.subscribe(response =>console.log(response), (error) => console.log(error));
And from back-end I send response as a text, for OK or Unauthorized, for OK i send back String token == UUID.randomUUID().toString();, for error I send back message like String error = " Invalid credentials ";, the problem is that the console.log works and print the text for success (token in this case), but in case error, its just prints: Response with status: 200 for URL: null.
If I change code to JSON.stringify(error) I get something like this:
{"_body":{},"status":401,"ok":false,"statusText":"Unauthorized","headers":{"null":["HTTP/1.1 401 Unauthorized"],"Access-Control-Allow-Headers":["Origin"," X-Requested-With"," Content-Type"," Accept"," Referer"," User-Agent"],"Access-Control-Allow-Met
hods":["POST"," GET"," PUT"," DELETE"," OPTIONS"],"Access-Control-Allow-Origin":["*"],"Allow":["*"],"Content-Length":["36"],"Content-Type":["text/plain; charset=utf-8"],"Date":["Tue"," 23 Aug 2016 14:53:25 GMT"]},"type":2,"url":null}
As you can see the error test not even mentioned inside the Object !!
I tried to change the response for error from backend to return json like this:
{
"message": "invalid email or password"
}
I can get the result inside _body, and I can only read it like this: console.log(error._body.message) ! but i feel its something wrong this way, and I don't want to response as a json in this case.
For angularjs (angular 1), its so simple just to print the response and everything is cool, while in angular 2 its a really problem.
What the problem, and how I can solve this issue without any refactor to backend?
Edit:
I'm using Angular 2.0.0-rc.4 and same for http : `"#angular/http": "2.0.0-rc.4"
Mothanfar
In my case I'm working with the Asp Web Api as back end,this thing is making me crazy as well, the only solution I found is transform in a json and read the message, I know is really ugly but works for me.
Regards.
CheckError(error: any) {
let servermsg: any = JSON.parse(error._body)["ModelState"]["Login"][0];
if (servermsg) {
this.showMsg = true;
this.msg = servermsg;
}
}
If you are returning JSON object from the server, you may use the below code at client side:
let errMsg: ErrorMessage = err.json();
console.log(errMsg.message)
export class ErrorMessage {
message:string;
}
I am just starting using Sails.js and it's an amazing framework. But I've met some situation and I cannot find solution by Google so I came here for help.
I have a controller to connect to another remote service with very old-designed API full of XML response and inconsistency, wrapping that service in simple and clean APIs. So I have some routers like:
list: function(req, res) {
params = {
...
}
FooService.request(data, function(error, response) {
res.send(response)
})
process.once('uncaughtException', function(err) {
res.send(500, '[Foo] ' + err);
});
},
The 'process.once' is for async exceptions which may raised in the FooService.request process. I know this is bad code and my question is: how to handle such situation more Sails.js way?
In Node.js we have Domain and connect-domain, which are designed for such problems. Because Sails.js is basically Express, which can facilitate connect-domain very well, I think there may be some idiomatic way to do that.
I've tried adding this in config/local.js:
module.exports = {
...
express: {
customMiddleware: function(app) {
console.log('Custom middleware config called')
var domain = require('connect-domain')
app.use(domain())
.use(function(err, req, res, next) {
console.log('Error catched!')
res.send(500, '[Foo] ' + err)
})
}
}
};
When un-catched exception occurred, it will not crash server and error 500 being returned to client side ('app.use(domain())' works). But the custom error handler does not called. Have no idea why.
If you're in control of the FooService code, then the best option is to handle all errors that happen there by calling the callback for FooService.request early with the error, and then using res.serverError or some other response in your controller:
FooService.request(data, function(error, response) {
if (error) {return res.serverError(errror);}
res.send(response)
});
If the FooService is using packages that you don't control, which may themselves throw errors inside of async code that they aren't catching (bad code!) then another good option is to use Node's error domains. See this answer for an example of someone doing a quick wrapper to use domains to catch errors in asynchronous code.
I am an absolute NodeJS beginner and want to create a simple REST-Webservice with Express and Mongoose.
Whats the best practice to handle errors of Mongoose in one central place?
When anywhere an database error occurs I want to return a Http-500-Error-Page with an error message:
if(error) {
res.writeHead(500, {'Content-Type': 'application/json'});
res.write('{error: "' + error + '"}');
res.end();
}
In the old tutorial http://blog-next-stage.learnboost.com/mongoose/ I read about an global error listener:
Mongoose.addListener('error',function(errObj,scope_of_error));
But this doesn't seem to work and I cannot find something in the official Mongoose documentation about this listener. Have I check for errors after every Mongo request?
If you're using Express, errors are typically handled either directly in your route or within an api built on top of mongoose, forwarding the error along to next.
app.get('/tickets', function (req, res, next) {
PlaneTickets.find({}, function (err, tickets) {
if (err) return next(err);
// or if no tickets are found maybe
if (0 === tickets.length) return next(new NotFoundError));
...
})
})
The NotFoundError could be sniffed in your error handler middleware to provide customized messaging.
Some abstraction is possible but you'll still require access to the next method in order to pass the error down the route chain.
PlaneTickets.search(term, next, function (tickets) {
// i don't like this b/c it hides whats going on and changes the (err, result) callback convention of node
})
As for centrally handling mongoose errors, theres not really one place to handle em all. Errors can be handled at several different levels:
connection errors are emitted on the connection your models are using, so
mongoose.connect(..);
mongoose.connection.on('error', handler);
// or if using separate connections
var conn = mongoose.createConnection(..);
conn.on('error', handler);
For typical queries/updates/removes the error is passed to your callback.
PlaneTickets.find({..}, function (err, tickets) {
if (err) ...
If you don't pass a callback the error is emitted on the Model if you are listening for it:
PlaneTickets.on('error', handler); // note the loss of access to the `next` method from the request!
ticket.save(); // no callback passed
If you do not pass a callback and are not listening to errors at the model level they will be emitted on the models connection.
The key take-away here is that you want access to next somehow to pass the error along.
hey this is the simplest way i found..
try { } catch (error) {
console.log(error);
// checking validation
if (error.name === "ValidationError") {
const message = Object.values(error.errors).map(value => value.message);
return res.status(400).json({
error: message
})
}
res.status(400).json(error.message)
}
}
just copy paste