问题
overview
My custom errorHandler middleware is not catching the swagger-tools request validator error. Instead, the swagger tools HTML error is sent back to the client. How can I get my errorHandler middleware to catch the swagger tools validation error and respond to the client accordingly?
my prognosis
I'm rather clueless unfortunately. No matter where I put the app.use(errorHandler) directive, the swagger tools html error is returned to the client and my errorHandler function never catches the error.
Maybe I'm overlooking something overtly incorrect about my setup. Below is my app.js file and below my app.js is the [undesired] swagger-tools HTML error response that is returned to the client. Again, I have tried putting the app.use(errorHandler) literally (figuratively) everywhere, despite the fact that the below code only shows it in two places.
app.js
"use strict";
var swaggerTools = require("swagger-tools");
var compression = require("compression");
var app = require("express")();
var logger = require("./config/logger");
var projectConfig = require("./config/projectConfig");
var debug = require("debug")("app-js"); // run this to enable debug logging DEBUG=app-js node app.js
// swaggerRouter configuration
var options = {
controllers: './api/controllers',
useStubs: false
};
// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
var swaggerDoc = require('./api/swagger/swagger.json');
// compress all requests except those which have Cache-Control header with the no-transform directive
app.use(compression());
// for testing
module.exports = app;
// global error handler
function errorHandler(err, req, res, next, statusCode) {
logger.error(err);
debug(err);
if (res.headersSent) {
return next(err);
} else {
res.status(statusCode || 500).json(projectConfig.genericErrorResponse(statusCode || 500, err.message || err || "something blew up and the err object was undefined"));
}
}
// handles timed out requests
function haltOnTimedout(req, res, next) {
if (!req.timedout) {
next();
} else {
debug("\nrequest timed out!\n");
next("the request timed out", null, null, null, 504);
}
}
// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
"use strict"
// Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
app.use(middleware.swaggerMetadata());
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*"); // CORS should be parametrized by configuration
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// Validate Swagger requests
// app.use(middleware.swaggerValidator());
app.use(middleware.swaggerValidator({
validateResponse: false
}));
app.use(haltOnTimedout);
app.use(errorHandler);
// Route validated requests to appropriate controller
app.use(middleware.swaggerRouter(options));
});
app.use(haltOnTimedout);
app.use(errorHandler);
app.listen(projectConfig.port || process.env.PORT || 9000)
.on("connection", function (socket) {
debug("\na new cxn was made by a client.\n");
socket.setTimeout(projectConfig.expressTimeout || 120000);
})
swagger tools html error returned to client
Error: Parameter (copy) failed schema validation
<br> at throwErrorWithCode (/Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/swagger-tools/lib/validators.js:121:13)
<br> at Object.module.exports.validateAgainstSchema (/Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/swagger-tools/lib/validators.js:176:7)
<br> at /Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/swagger-tools/middleware/swagger-validator.js:143:22
<br> at /Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/async/lib/async.js:356:13
<br> at async.forEachOf.async.eachOf (/Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/async/lib/async.js:233:13)
<br> at _asyncMap (/Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/async/lib/async.js:355:9)
<br> at Object.map (/Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/async/lib/async.js:337:20)
<br> at validateValue (/Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/swagger-tools/middleware/swagger-validator.js:136:11)
<br> at /Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/swagger-tools/middleware/swagger-validator.js:343:21
<br> at /Users/cuv/Documents/dev/dev-project/dev-simple/node_modules/async/lib/async.js:356:13
what versions am i running?
node:
node --version
v6.2.2
latest versions of swagger-tools and express:
"swagger-tools": "^0.10.1",
"express": "^4.12.3"
close
Any help and/or insight into how to get my errorHandler middleware to catch and thereby override the swagger-tools html error would be very much obliged. I've posted my question in the apigee community forums as well, as it is part of an apigee-127 project. https://community.apigee.com/questions/29267/swagger-tools-error-handler-middleware-not-catchin.html
Thanks!
回答1:
I see two problems.
At first: error handler must have 4 args, so statusCode will be ignored.
errorHandler(err, req, res, next) // correct definition
Second place is
next("the request timed out", null, null, null, 504);
First argument of error handle must be Error object not String, so correct code will be
next(new Error("the request timed out")); // other args passed by closure
There are many variants how pass statusCode.
// 1. Bad way: Pass string with delimiter
next(new Error("the request timed out;404"));
...
// In error handler
var args = err.message.split() // => args[0] = the request timed out, args[1] = 404
// 2. Check message error text
If (err.message == 'the request timed out')
statusCode = 404;
// 3. Best way is use custom error
More about custom error here
来源:https://stackoverflow.com/questions/38647242/swagger-tools-error-handler-middleware-not-catching-errors