restify / errors Goto Github PK
View Code? Open in Web Editor NEWHttpErrors and RestErrors extracted from restify
License: MIT License
HttpErrors and RestErrors extracted from restify
License: MIT License
Custom constructors created via makeConstructor()
are currently stored on the module. This can create some problems if this module is shared between libraries that want to create constructors with the same name (or happens to get deduped by npm/yarn). There is an argument to be made that returning the constructor to userland, where users can keep track of it themselves, is the simplest path forward. While that increases friction in terms of usability, it also increases flexibility.
We could explore options for a hybrid approaches, as well.
When sending error with next(error) callback, response sent to client does not contain optionnal properties of my new Error Object created with makeConstructor restify-errors module.
Env : Node v12.18.3 with ESM loader (type: "module") in package.json
Example :
import errs from 'restify-errors';
const TestError = errs.makeConstructor("TestError", {
statusCode: 500,
info: {errcode: "ERR_GENERIC"},
message:"App Error"
});
const tmp = new TestError();
console.log("tmp.info exists : ", JSON.stringify(tmp.info));
console.log("But this is sent to client when next(tmp) called : ", JSON.stringify(tmp));
Print :
tmp.info exists : {"errcode":"ERR_GENERIC"}
But this is sent to client when next(tmp) called : {"code":"Test","message":"App Error"}
It seems to be caused by JSON.stringify that only check for ownProperties (it don't look for prototype chain).
Is there any technical reason why this package depends on @netflix/nerror and not on the original verror?
restify-errors is literally the only public package that depends on nerror, so it forces us to install nerror, besides verror that many of us (indirectly) use already anyway.
tried:
errors.makeConstructor("CustomError", {
statusCode: 410,
message: "custom default error message"
});
but this didn't work - would be nice though.
I see, by design strictly only code
and message
are being passed to http response body.
https://github.com/restify/errors/blob/master/lib/baseClasses/HttpError.js#L92
https://github.com/restify/errors/blob/master/lib/baseClasses/HttpError.js#L147
Imagine a scenario when you want to pass down some extra metadata in the error response. For example validation details:
{
"code": "BadRequest",
"message": "",
"validation": { ... }
}
How do you guys pass extra error metadata in http response?
Are there any typescript typing anywhere for restify-errors?
I can see in the DefinitelyTyped repo only typings for restify (not for beta though) and for restify-plugins.
If there isn't one, would it be possible for you to create one?
I want to set extra options in error response. Didn't find the exact solution anywhere.
tried passing in the body
const errors = require('restify-errors');
new errors.MethodNotAllowedError({ body: { extra: option } }, some-error-message));
what's the exact method to allow some extra options in error response?
Is there a way to set the default for all the errors and just pass the extra field parameters?
Also, I just want options in already existing error methods.
Custom errors created via makeConstructor()
return the generic constructor name (ErrCtor
) when applying toString()
:
> const errors = require('restify-errors');
> errors.makeConstructor('CustomError', { statusCode: 400 });
> const cerr = new errors.CustomError('oops');
> cerr.toString();
'ErrCtor: oops'
// Expected: 'CustomError: oops'
toJSON()
serialization is also affected for MultiErrors if the "cause" is a custom error:
> const merr = new errors.BadGatewayError(cerr, {message: 'Unable...'});
> merr.toString();
'BadGatewayError: Unable...; caused by ErrCtor: oops'
> merr.toJSON();
{ code: 'BadGateway',
message: 'Unable...; caused by ErrCtor: oops' }
This can be traced to VError.toString()
, which checks the instance for its own name
property, and navigates up the prototype chain to land on the constructor name. For custom error instances, cerr.hasOwnProperty('name') === false
, yielding ErrCtor
.
Options:
toString()
implementation if this is important to themthis.name = name
in the constructor: https://github.com/restify/errors/blob/master/lib/index.js#L75Documentation isn't clear when to use return next(err);
vs using just next(err);
For instance, everywhere it uses return
except in the section Checking Error types
Makes it easier for users to keep track of custom constructors.
Throw if constructor already exists.
Should be able to just pass an Error
object and automatically fetch the error message from the Error
object.
For example:
return next(new errors.BadRequestError(error));
Instead of (currently):
return next(new errors.BadRequestError(error.message));
Using this new module:
return next(new errors.BadRequestError('400 bad request message here'));
Returns the following JSON:
{"code":"BadRequest","message":"400 bad request message here"}
Previously, using Restify:
return next(new restify.BadRequestError('400 bad request message here'));
Returned the following JSON:
{
"message": "/foo does not exist",
"statusCode": 404,
"body": {
"code": "ResourceNotFound",
"message": "/foo does not exist"
},
"restCode": "ResourceNotFound"
}
I actually don't care about the body
property, but statusCode
and restCode
are useful, and should be named the same key.
The context
option was implemented before verror's info
option was available. Now that it's available upstream we should try and use that under the hood instead. Some implications in terms of how to access the context property and inspect it (verror uses a static method verror.info()
). Should be able to continue to use the same serializer, however, since it already supports verror's info
field.
Replaces #55
I wanted to create an additional property on the return, but I can't quite figure out the correct syntax for makeContructor(name, defaults) to get the toString and toJson to update - I'd like to ideally pass in an object, and then strip off a property off that object (errors) and perform some work on it (getting message for each object in errors) and just combine them.
ideally, could I submit a PR that did something like https://github.com/Raynos/send-data
https://github.com/Raynos/send-data/blob/master/error.js#L78-L82
if (opts.additionalParams) {
opts.additionalParams.forEach(function appendKey(k) {
body[k] = err[k];
});
}
the reason I ask is right now options.context sends back the information in logging, but I don't have a way to get that options.context out to the user.
Thanks in advance,
Paul
Both HttpError
and RestError
objects use util.inherit
to establish (pseudo)inheritance. As stated by the docs:
usage of
util.inherits()
is discouraged. Please use the ES6 class and extends keywords to get language level inheritance support.
In the process of migrating from Restify 4 to Restify 5, it seems that we are no longer able to override the body of the error.
You used to be able to do:
new restify.errors.BadRequestError({body: {whatever: 'you want'}})
After looking through the documentation and the source code, I can't see a way to accomplish this. Is this something that would fit in this project? I would be willing to open a PR if I knew it would be well received.
Thanks, Garret
Hi,
Can you please update to the latest assert-plus npm (currently 0.2.0)? It fixes an issue I see in my code when I try to run in strict mode (I'm trying to update my code and its dependencies to work with node 5.0.0 in strict mode to get access to ECMAScript 6 features). This issue occurs when assert-plus's assert.string()
method is called.
/tmp/errors(master) $ node --use_strict foo.js
/private/tmp/errors/node_modules/assert-plus/assert.js:41
stackFunc = stackFunc || _assert.caller;
^
TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.
at _assert (/private/tmp/errors/node_modules/assert-plus/assert.js:41:49)
at Object.string (/private/tmp/errors/node_modules/assert-plus/assert.js:160:9)
at Object.<anonymous> (/private/tmp/errors/foo.js:2:8)
When we merge them, httpErrors
implicitly overwritten by restErrors
.
tried to do something like this:
throw new errors.UnprocessableEntityError({
message: 'email invalid',
somethingElse: 'maybe some more info'
});
but restify's output stays the same:
{
"code": "UnprocessableEntity",
"message": "email invalid"
}
I was trying to create an error handler and noticed that toString wasn't working properly (or at least not as documented).
const internalError = new errors.NotFoundError('NotFoundError message');
const outerError = new errors.UnauthorizedError(internalError, 'UnauthorizedError message');
console.log(outerError.toString());
// UnauthorizedError: UnauthorizedError message
console.log(outerError.message);
// UnauthorizedError message
console.log(outerError);
/*
{ [UnauthorizedError: UnauthorizedError message]
message: 'UnauthorizedError message',
we_cause:
{ [NotFoundError: NotFoundError message]
message: 'NotFoundError message',
body: { code: 'NotFound', message: 'NotFoundError message' },
context: null },
body: { code: 'Unauthorized', message: 'UnauthorizedError message' },
context: null }
*/
The documentation describes
I can create a pull request, but I don't want to do it without knowing what to change the toString or the documentation.
If you prefer to update the docs, I'd like to create a messageWithCause()
function that keeps the caused by
.
when creating new restify error with a "%25" as a prefix and than one of the following chars (e,E,f,g,G,d etc...) the application will break with an uncaught exception.
it looks like verror uses sprintf, and it encodes "%25" a real "%" delivered as an argument.
this end with "Error: next shouldn't be called more than once"
Based on README, the error should be compared using instanceof
operator.
for example
const errors = require('restify-errors');
const err = new errors.ResourceNotFoundError();
err instanceof errors.ResourceNotFoundError; // true
However I couldn't compare them in a specific case under restify
:
// trigger this error when some in-existing route being called
server.on('NotFound', (req, res, err, cb) => {
req.log.info(JSON.stringify(err, null, 2)); // { "code": "ResourceNotFound", "message": "/xxxx does not exist" }
req.log.info(err.toString()); // ResourceNotFoundError: /xxxx does not exist
req.log.info(err.code); // Error
if (err instanceof errors.ResourceNotFoundError) {
// never get here
}
cb();
});
kind of weird, any ideas?
I'm not sure where is better to report this issue, restify
or this repo?
versions
restify
: 5.2.0
restify-errors
: 5.0.0
Is there a way to render multiple errors or accomplish the following in the response.
{
"message": "Validation Error",
"errors": [
{ "message": "`email` is required." },
{ "message": "`first_name` is required." },
]
}
title says it all ;)
(not to be confused with restify's 5.x)
Remove a lot of the logic around the context
property and simply use VError's info
property. This will necessitate a reworking of the variadic args parsing, since an options object as a first parameter is what we used to differentiate custom restify-errors logic vs straight pass through to VError. This will be a breaking change to the API. It might be worth re-evaluating what this module brings to the table on top of VError now that VError is able to do most of what this module does. In my mind, those things are:
Would appreciate any feedback from folks who are using this module.
I changed the default error output in restify 4.x using the below code
`var restify = require('restify');
var util = require('util');
function ValidationError(message, errors) {
restify.RestError.call(this, {
restCode: 'ValidationError',
statusCode: 400,
message: message,
constructorOpt: ValidationError
});
this.name = 'ValidationError';
this.body.errors = errors; //<---
}
util.inherits(ValidationError, restify.RestError);`
And I got the desired result. Now am in a process of migrating my project to restify 7.x. So I couldn't use the restify.RestError, I have tried 'restify-errors-options' package's subclassing property but it doesn't work for me. I have tried the below code
restifyErrors.makeConstructor('ValidationError', { restCode: 'ValidationError', statusCode: 400, message: message }); var myErr = new errors.ValidationError( );
And I ended up with the below error
var myErr = new errors.ValidationError(); ^
TypeError: errors.ValidationError is not a constructor
So can anyone suggest a solution for this problem?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.