apigee-127 / swagger-node-runner Goto Github PK
View Code? Open in Web Editor NEWThe heart of Swagger-Node
License: MIT License
The heart of Swagger-Node
License: MIT License
When I have a response validation error, I'm left with a broken response message, because it seems the response message itself does not pass the validation, or it could be something else entirely, I just can't pinpoint the issue. I'm not entirely sure how things break in this way, perhaps it's got something to do with Content-Length, or something else.
I'm posting this issue to offer a work-around to others, and perhaps get some feedback on this issue.
So I worked around this problem by creating my own json_error_handler
fitting, and instead of sending the full error in the response, I simply just return the error message, and console.error
the err.results
.
The problem is here: https://github.com/theganyo/swagger-node-runner/blob/424734a6000da517f6336d9f8ce006c5cfbd7b83/fittings/json_error_handler.js#L36
My code change: [edit] Don't do this, see below
next(null, JSON.stringify({
message: err.message
}));
This was causing me some pain, I hope this helps others.
I just found that the resulting distribution package sent to npm contains the tests...
I don't know how to create a PR for adding a file, but there you go...
.npmignore
test
.gitignore
.jshintrc
.npmignore
.travis.yml
changes in #16 doesn't seem to be present even after I delete my node_module folder, am I doing something completely wrong?
Thanks
There's a codepath I'm not comfortable with, I need your take on this.
from W3 spec:
The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
So, in contrast, IMHO - the case slips our code here:
https://github.com/theganyo/swagger-node-runner/blob/master/lib/connect_middleware.js#L87
the problem is that if ctx.output
is falsful - including zero (0
), empty string (""
), null
, undefined
, and obviously false
- the respondse.end()
is not called, where the last in chain-of-responsibility is usually the framework, wich ends with it's default response, usually 404 in the form of cannot GET /the-path
.
All of the above (except undefined maybe) are legit replies the server may be required to provide, regardless to 204 status code, where there should be cases where the server should emit no body.
Am doing something wrong or missing anything?
If I'm not missing anything - LMK, and I'll start a PR to fix this...
It appears that swagger_validate fitting no longer supports response validation. What's the long term plan? Is there a recommended work around for now?
There appears be code in the swagger-tools project's swagger-validator middleware, but it's not clear how these two should be integrated (and swagger-tools is technically deprecated).
I'm trying to create some reusable pipe fittings packed as simple npm packages.
So to prove the concept I placed a simple node_modules/required-fitting/index.js
(together with a standard package.json
) in same folder, as follows:
var debug = require('debug')('fitting:required-fitting');
module.exports = function create(fittingDef) {
console.log('required-fitting', fittingDef);
return function stam(ctx, cb) {
console.log('REQUIRED-FITTING IS CALLED');
cb()
}
}
And added to the config:
So:
swagger:
fittingsDirs: [ lib/fittings, node_modules ]
...
Alas - the pipe explodes. The error is observed on the response as {"message":"undefined is not a function"}
, with NO MENTION of it on the server log
It appears to explode on cors
, which is now ambiguous between the two paths:
node_modules/cors
lib/fitting/cors.js
playing with order of paths in fittingsDir
did not help :(
I can PR to rename lib/fitting/cors.js
to lib/fitting/swagger_cors.js
or anytihng of that sort, however, it looks like a breaking change.
I think the situation points also to an additional problem:
I think the fitting builder that calls the fitting factory may be required to make sure that the factory returns a function in the correct arity. (the vanilla cors
package is a f(1)
factory that returns f(3)
)
I did not miss the part about type:node-machine
that requires some overhead plus pushes me to experimental zone, which I would totally prefer to avoid at this stage... my client wont approve of anything with experimental labelled on it...
Thoughts?
On https://github.com/theganyo/swagger-node-runner/blob/master/fittings/swagger_params_parser.js#L40, it says 'we do not check for errors here' Why is that?
There's a lot of nice validation in https://github.com/apigee-127/sway/blob/master/lib/types/parameter.js#L118 that results in exceptions. Since they are not caught in the parser, they will typically take down the process.
Say you have a swagger spec with an endpoint with a parameter "in: formData". Everything is working fine and dandy. However, if a (malicious?) client requests the endpoint and omits the Content-Type header, then that causes req.body to be undefined and an exception in to be thrown (https://github.com/apigee-127/sway/blob/master/lib/types/parameter.js#L147). Since that is not caught, gone is your service.
Edited: beautify and used more precise language
Hi.
I noted compeating efforts between:
json_error_handler.js#L42
json_error_handler.js#L60
and
connect_middleware.js#L127
If the concern of serializing a model object to a string is a concern of the connect_middleware
, then the json_error_handler
should not stringify, but leave a model object (the Error, perhaps augmented with statusCode or so)
I came to this thought when I approached a requirement to format error responses with in a custom envelope that is accustomed in the corp I do the job for.
My initial thought was :
swagger-route-error:
- name: json_error_handler
- fitting/the-corp-envelope
swagger-router:
- onError: swagger-route-error
- ...
Then I noted that the error handler leaves a string. If I want to manipulate it - I'll have to parse it, where it was an object just one step before...
.
I began to believe that the safe serialization logic belongs to connect_middleware
, and should be agnostic to wether it's an error or not
(I mean, serialization error will still raise statusCode
to 500, but it's not unique to json_error_handler
)
What do you think?
I'm using swagger-node-runner
through swagger-hapi
. The related dependencies are:
├─┬ [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ └── [email protected]
When handling a request with a parameter in the path, the request.swagger.params
object is undefined. I looked around request
and request.swagger
thinking it could've been renamed, but couldn't find the parameter anywhere.
Downgrading swagger-hapi
to 0.1.0
, which in turn downgrades swagger-node-runner
to 0.5.13
fixes the issue.
If it helps, the handler I'm running is at https://github.com/opentrials/api/blob/master/api/controllers/trials.js#L4.
Hi,
Just wondering if there's a way to specify a fitting (or middleware) to be executed for a specific path or even an operation for a specific path without writing an extension as seen in Volos[1]? Much like as you'd specify a middleware for a connect/express route.
For the time being the only option I can think of is a generic fitting that execute as part of swagger_controllers
, but the downside of that is I need to check for the path I'm interested and invoke the middleware on a match. Not very elegant sadly.
Is there a way to load multiple swagger definition files?
This is needed for handling API versioning as swagger defines one API version per definition file.
Thanks.
This block of code is preventing OPTIONS calls in the cors module from working. The cors fitting middleware is never hit because a 405 is returned in the connect middleware.
if (!operation) {
var path = runner.getPath(req);
if (!path) { return next(); }
if (!path['x-swagger-pipe']) {
var msg = util.format('Path [%s] defined in Swagger, but %s operation is not.', path.path, req.method);
var err = new Error(msg);
err.statusCode = 405;
var allowedMethods = _.map(path.operationObjects, function(operation) {
return operation.method.toUpperCase();
});
err.allowedMethods = allowedMethods;
res.setHeader('Allow', allowedMethods.sort().join(', '));
return next(err);
}
}
I have this URL format: domain.com/api/resource
The baseUrl defined in swagger.yaml is /api
The express configured so that the /api is just a sub-app:
app = express();
apiApp = express();
app.use('/api', apiApp);
The swagger middleware is then added into apiApp.
Both swagger definition and express already configured to use the /api
basePath, but connect middleware bypass it by calling next()
because the runner.getPath
return undefined.
Note the api.getPath
, the pathOrReq.url here is returning only the sub path. In this case the pathOrReq.url = '/resource'
instead of '/api/resource'
. Therefore the regexp
and isArray
return false.
I suggest we fix this by calling api.getPath(req.originalUrl)
either in runner or connect middleware since originalUrl
contain the full path.
Refer to this also apigee-127/sway#81
76f5051 seems to have broken response validation, since v. 0.6.0 of Sway can no longer validate JSON encoded strings as objects, see apigee-127/sway#48.
Paths are directly passed to the app
object in lib/restify_middleware.js
which results to not having path params parsed. Restify uses :param
syntax for specifying path parameters and Swagger uses {param}
syntax. This results 404s when trying to access an url with dynamic part in it.
api.pathObjects.forEach(function(path) {
if (path.operationObjects && path.operationObjects.length > 0) {
path.operationObjects.forEach(function(operation) {
registerHandler(path.path, operation.method);
});
} else {
ALL_METHODS.forEach(function(method) {
registerHandler(path.path, method);
});
}
});
Hi,
Firstly congrats on the Sway 1.0 based release. Much appreciated. It seems that after the release, my existing security handlers are no longer working.
Pre-upgrade npm ls
shows I had been using:
[email protected]
[email protected]
[email protected]
I should mention that I was using API level security instead of specifying security per route, i.e. in my swagger.yaml
file I had:
# API security. Applies to all routes
security:
- BasicAuth: []
# Routes
paths:
/stars/{starId}/accounts:
x-swagger-router-controller: star-controller
get:
description: Returns accounts for a star identified by it's id
...
# API security definition
securityDefinitions:
BasicAuth:
type: basic
Post upgrade, I'm using:
[email protected]
[email protected]
[email protected]
Looking at the security fitting[1] it seems that operation
comes back as undefined
and this suggests that support for API level security has somehow been broken.
I've currently worked around by specifying operation level security for each route and that's fine, but I wanted to highlight this nevertheless as API level security is part of the spec and should be supported.
[1] https://github.com/theganyo/swagger-node-runner/blob/master/fittings/swagger_security.js#L32
When request to non allowed method in swagger.yaml I get a 500 instead of 405:
error: Sending 500 ("Server Error") response:
Error: Path [aPathApi] defined in Swagger, but GET operation is not.
at middleware (/projectdir/node_modules/swagger-sails-hook/node_modules/swagger-node-runner/lib/connect_middleware.js:31:21)
...
at callbacks (/projectdir/node_modules/sails/node_modules/express/lib/router/index.js:167:11) { [Error: Path [aPathApi] defined in Swagger, but GET operation is not.] statusCode: 405, allowedMethods: [ 'DELETE', 'POST' ] }
Is there an option to overide this ?
https://github.com/theganyo/swagger-node-runner/blob/master/lib/connect_middleware.js#L40
Thanks
All modules are in a flat format now and it appears that having swagger-node-runner/fittings/cors.js and the module cors (in the new flat format) breaks what is loaded via require.
I can test this theory by installing a sample project with the latest npm (3.3.12) and seeing it break then going into the swagger-node-runner module and renaming the cors wrapper (and relevant config for bagpipes) and it works.
Not sure of an elegant workaround for this. Renaming fittings/cors.js would cause problems with existing projects.
https://github.com/expressjs/cors#configuration-options shows that you can set origin to a regexp to only allow CORS request from a given domain:
RegExp - set origin to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern /example.com$/ will reflect any request that is coming from an origin ending with "example.com".
Is there a way to pass such a regexp in the config ? If not, how may I create my own cors middleware and use it in the swagger-node-runner setup ?
If I try to upload unexpected file name param I get a 500 error, I expected a 400 Bad Request instead
Perhaps I am missing something ?
Example:
$ curl -F "badfilename=@s" --header 'Content-Type: multipart/form-data' 'http://localhost:1337/hello' -v
* Trying ::1...
* Connected to localhost (::1) port 1337 (#0)
> POST /hello HTTP/1.1
> Host: localhost:1337
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Length: 240
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------7a61cdece2908f90
>
< HTTP/1.1 100 Continue
< HTTP/1.1 500 Internal Server Error
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials:
< Access-Control-Allow-Methods:
< Access-Control-Allow-Headers:
< Access-Control-Expose-Headers:
< X-Content-Type-Options: nosniff
< Content-Type: text/html; charset=utf-8
< Content-Length: 1476
< Date: Thu, 09 Jun 2016 05:44:22 GMT
< Connection: keep-alive
* HTTP error before end of send, stop sending
<
Error: Unexpected field<br> at makeError (/Users/cgaliber/dev/bugs/upload-swagger-sails/node_modules/multer/lib/make-error.js:12:13)<br> at wrappedFileFilter (/Users/cgaliber/dev/bugs/upload-swagger-sails/node_modules/multer/index.js:39:19)<br> at Busboy.<anonymous> (/Users/cgaliber/dev/bugs/upload-swagger-sails/node_modules/multer/lib/make-middleware.js:112:7)<br> at emitMany (events.js:127:13)<br> at Busboy.emit (events.js:201:7)<br> at Busboy.emit (/Users/cgaliber/dev/bugs/upload-swagger-sails/node_modules/busboy/lib/main.js:31:35)<br> at PartStream.<anonymous> (/Users/cgaliber/dev/bugs/upload-swagger-sails/node_modules/busboy/lib/types/multipart.js:213:13)<br> at emitOne (events.js:96:13)<br> at PartStream.emit (events.js:188:7)<br> at HeaderParser.<anonymous> (/Users/cgaliber/dev/bugs/upload-swagger-sails/node_modules/dicer/lib/Dicer.js:51:16)<br> at emitOne (events.js:96:13)<br> at HeaderParser.emit (events.js:188:7)<br> at HeaderParser._finish (/Users/cgaliber/dev/bugs/upload-swagger-sails/node_modules/dicer/lib/HeaderParser.js:68:8)<br> at SBMH.<anonymous> (/Users/cgaliber/dev/bugs/upload-swagger-sails/node_modules/dicer/lib/HeaderParser.js:40:12)<br> at emitMany (events.js:127:13)<br> at SBMH.emit (events.js:201:7)
* Closing connection 0
Here is the error from node console
Error: Unexpected field
at makeError (node_modules/multer/lib/make-error.js:12:13)
at wrappedFileFilter (node_modules/multer/index.js:39:19)
at Busboy.<anonymous> (node_modules/multer/lib/make-middleware.js:112:7)
at emitMany (events.js:127:13)
at Busboy.emit (events.js:201:7)
at Busboy.emit (node_modules/busboy/lib/main.js:31:35)
at PartStream.<anonymous> (node_modules/busboy/lib/types/multipart.js:213:13)
at emitOne (events.js:96:13)
at PartStream.emit (events.js:188:7)
at HeaderParser.<anonymous> (node_modules/dicer/lib/Dicer.js:51:16)
at emitOne (events.js:96:13)
at HeaderParser.emit (events.js:188:7)
at HeaderParser._finish (node_modules/dicer/lib/HeaderParser.js:68:8)
at SBMH.<anonymous> (node_modules/dicer/lib/HeaderParser.js:40:12)
at emitMany (events.js:127:13)
at SBMH.emit (events.js:201:7)
Here is an extract of swagger.yaml parameters section
parameters:
- name: stdout
in: formData
description: the file to upload
required: false
type: "file"
As per swagger-api/swagger-node#253
Sway just released 1.0.0 https://github.com/apigee-127/sway/releases/tag/v1.0.0 which introduces a bunch of improvements, would it be possible to get a new release of swagger-node-runner which includes it?
Swagger YAML Def:
/Permission:
x-swagger-router-controller: permission
get:
tags: ['Permissions']
description: Get either all permissions or a permission with a specific id
operationId: getPermissions
parameters:
- $ref: "#/parameters/NodeIDs"
responses:
"200":
description: Success
schema:
type: array
items:
$ref: "#/definitions/Permission"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
NodeIDs:
name: ids
in: query
description: A list of node ids (integers).
type: array
items:
type: integer
Example command: curl -k https://0.0.0.0:3000/Permission?ids=123
Error:
{"message":"Validation errors","errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"INVALID_TYPE","params":["array","integer"],"message":"Expected type array but found type integer","path":[],"description":"A list of node ids (integers)."}],"in":"query","message":"Invalid parameter (ids): Value failed JSON Schema validation","name":"ids","path":["paths","/Permission","get","parameters","1"]}]}
However the following works: curl -k https://0.0.0.0:3000/Permission?ids=1231,1231
The following behavior does not hold true when the yaml def changes to the following:
parameters:
NodeIDs:
name: ids
in: query
description: A list of node ids (integers).
type: array
items:
type: string
However, I receive an error when I try to put an integer 1231
into a string.
I'd really love for a resolution to this.
Best,
Dan
I tried to use swagger-node (with express) with the config module. I was loading all the config first and then used SwaggerExpress.create. This module was throwing "Cannot assign to read only property 'swagger' of [object Object]", stack trace:
TypeError: Cannot assign to read only property 'swagger' of [object Object]
at new Runner ([cut]\node_modules\swagger-node-runner\index.js:154:18)
at Object.module.exports.create ([cut]\node_modules\swagger-node-runner\index.js:54:3)
at Object.module.exports.create ([cut]\node_modules\swagger-express-mw\lib\index.js:30:10)
at Object. ([cut]\app.js:12:16)
at Module._compile (module.js:413:34)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:447:10)
at startup (node.js:141:18)
at node.js:933:3
I debugged the problem and used a (kinda) dirty hack - I load SwaggerExpress (and hence swagger-node-runner) before anything else, and suddenly it works. Anyway, it was not an expected behavior
I researched it deeper, and understood that this is related to the config object becoming immutable
So you should either update the docs with a note that this module should be loaded prior to config module reads (it writes to swagger variable), or alter the inner structure somehow.
Just started out in Koa and would be awesome to have this aswell.
There seems to be an issue with default parameters when used in combination with arrays. I've added the following to the test-case swagger:
/hello_w_default_array:
x-swagger-router-controller: hello_world
get:
description: Returns 'Hello' to the caller
operationId: hello_array
parameters:
- name: names
in: query
description: The names of the people to whom to say hello
default: ["Tom", "Maria"]
type: array
items:
type: string
collectionFormat: csv
The test code in /tests/lib/common.js:
it('should execute with default names', function(done) {
request(this.app)
.get('/hello_w_default_array')
.set('Accept', 'application/json')
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
should.not.exist(err);
res.body.should.eql('Hello, Tom and Maria');
done();
});
});
and the added function to the hello_world.js is:
...
hello_array: hello_array,
...
function hello_array(req, res) {
var hello = 'Hello';
console.log(req.swagger)
var names = req.swagger.params.names.value
for (let n =0; n < names.length; n ++) {
if (names.hasOwnProperty(n)) {
if ((n + 1) === names.length){
hello += " and "
}else {
hello += ", "
}
hello += names[n]
}
}
res.json(hello);
}
And mocha test/lib/connect_middleware.js -g "with default names"
fails with:
1) connect_middleware standard controllers should execute with default names:
Uncaught AssertionError: expected Error { message: 'expected 200 "OK", got 400 "Bad Request"' } to not exist
at Test.<anonymous> (test/lib/common.js:72:22)
at Test.assert (node_modules/supertest/lib/test.js:156:6)
at Server.assert (node_modules/supertest/lib/test.js:127:12)
at emitCloseNT (net.js:1521:8)
If I add a required: false
the hello_array is properly identified but the names property is empty as if the default parameters are ignored. This could possibly be a upstream bug in sway as there seems to be an issue with how default arrays are passed. I think the package should have tests for default values so I've added them (see pull request) and therefore started reporting the issue here.
I've a error handler set up
swaggerExpress.runner.on('responseValidationError', function(validationResponse, request, response) { ... }
and I'm also serving up the swagger-ui using static serve.
However the hookResponseForValidation fails with
TypeError: Cannot read property 'validateResponse' of undefined api_1 | at ServerResponse.hookEnd (/app/node_modules/swagger-node-runner/lib/connect_middleware.js:163:63)
as operation
is undefined on context.request.swagger.operation.validateResponse
I'll submit a pull request shortly but the gist of the change is to filter out based on
if(context.request.swagger.operation == undefined){ debug('not a swagger operation, will not validate response'); }
Not possible using swagger-tools, add when swagger-api is available.
In lib/restify_middleware.js
paths are attached directly to the app
object without having the basePath
in mind. This results to 404's.
api.pathObjects.forEach(function(path) {
if (path.operationObjects && path.operationObjects.length > 0) {
path.operationObjects.forEach(function(operation) {
registerHandler(path.path, operation.method);
});
} else {
ALL_METHODS.forEach(function(method) {
registerHandler(path.path, method);
});
}
});
A few days ago, finally it issue had released that in order to catch uncoughtExpcetion.
I'd like to upgrade 1.3.1. but swagger-node-runner has not released.
when could I apply it ?
Hi there, I'm having a hard time with error handling. When a validation error is raised it comes back as an ugly JSON response with my request buffer attached. How do developers opt out, or modify this error object?
I am using a project generated with swagger project create
, with express
.
The other thing, is that the swagger error responses are coming back clipped. Example:
{"message":"Response validation failed: failed schema validation","code":"SCHE
This may be related to #30
Am I please able to have some help in resolving these issues?
Many thanks,
Wilfred
can't wait...
any timeline for that?
Scott,
As I am going through migrating from the a127 to the swagger-node new framework, I ran into the issue of trying to use the global replacement capability using the x-a127-config section in the yaml file.
We rely on this capability to be able to set different options per environment specifically for the volos libraries.
It seems that this was left out by design, assuming the app could provide the swagger instance via the config object. This is fine, but it would require the app to do something like the doConfigReplacements
function in the a127-magic module.
Is there any way that a global yaml config section can be added to provide this kind of functionality or do you know of any other way that this can be achieved?
Thanks in advance for the help.
JC
Hey @theganyo, it seems like SwaggerConnect.create
never passes the error back to the caller whenever the Swagger document is not valid. Here are more details: swagger-api/swagger-node#354. Any way to check this out?
project
└─┬ [email protected]
└── [email protected]
Issue: Passing an unconfigured parameter (not in swagger request schema) in a POST body doesn't throw a validation error.
Detail: Talking to the Swagger spec guys on IRC, it turns out that this "missing" behaviour isn't explicitly stated in the spec but was intended to exist, at least optionally. Does swagger-node-runner
have this ability?
Hi,
Just as the question says. Is there a way that in express this could be like it normally works req.params
in some type of config?
Cross-ref apigee-127/swagger-express#9
Hi,
I have some middleware which check permission for specific API.
The validation is against path in a rules manifest like user/create.
until now i use it from express like this:
app.post("/user", permissionMW("users/create"), myControllerFunc);
Now i want to move this manifest path to be in the swagger yaml with x-permission-path.
but to use it i need to add this middleware to run after the metadate middleware (before/after the security middleware). so i will have access to the swagger object.
I want to somehow pass an hook MW which i can define from outside when to run it, and provide the func.
something like add to the config in the constructor:
MWhooks : {
"before[MWname]" : [myMW1, myMW2],
"after[MWname]" : [myMW3, myMW4]
}
an actual value for this example will be :
myMW1 = function(req, res, next){
if something next();
throw err;
}
MWhooks = {
"aftersecurity" : [myMW1]
}
var config = {
MWhooks : MWhooks
}
Runner.create(config, function(err, runner) {
if (err) { return cb(err); }
cb(undefined, runner.expressMiddleware());
});
What do you think about this? is this sound like a good solution?
When deliberately making invalid requests (POST to PUT only endpoint) I receive a full error stack dump on the client side, looking at the debug log, the flow never makes it to pipeworks (and the tidy json_error_handler).
My project is based off the express swagger-node skeleton but I'm trying to upgrade to swagger-express-mw 0.7.0.
Valid requests the express router seems to be passed through and pipes handles everything correctly.
DEBUG=* log on invalid request:
express:router dispatching POST /postOnly +2s
express:router query : /postOnly +0ms
express:router expressInit : /postOnly +1ms
express:router middleware : /postOnly +0ms
finalhandler default 405 +1ms
Error: Path [/postOnly] defined in Swagger, but POST operation is not.
at middleware
at Layer.handle [as handle_request]
at trim_prefix
at /lib/router/index.js:280:7
at Function.process_params
at next
at expressInit
at Layer.handle [as handle_request]
at trim_prefix
at
at Function.process_params
at next
at query
at Layer.handle [as handle_request]
at trim_prefix
at
at Function.process_params
at next
at Function.handle
at EventEmitter.handle
at Server.app
at emitTwo (events.js:106:13)
at Server.emit (events.js:191:7)
at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:546:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
My software versions:
"dependencies": {
"express": "^4.12.3",
"swagger-express-mw": "^0.7.0"
}
config file:
# swagger configuration file
# values in the swagger hash are system configuration for swagger-node
swagger:
fittingsDirs: [ api/fittings ]
defaultPipe: null
swaggerControllerPipe: swagger_controllers # defines the standard processing pipe for controllers
# values defined in the bagpipes key are the bagpipes pipes and fittings definitions
# (see https://github.com/apigee-127/bagpipes)
bagpipes:
_router:
name: swagger_router
mockMode: true
mockControllersDirs: [ api/mocks ]
controllersDirs: [ api/controllers ]
_swagger_validate:
name: swagger_validator
validateResponse: false
_json_error_handler: # <= Add this definition
name: json_error_handler
handle500Errors: true
# pipe for all swagger-node controllers
swagger_controllers:
- onError: _json_error_handler
- cors
- swagger_params_parser
- swagger_security
- _swagger_validate
- express_compatibility
- _router
# pipe to serve swagger (endpoint is in swagger.yaml)
swagger_raw:
name: swagger_raw
# any other values in this file are just loaded into the config for application access...
Thanks for any help!
Commits were made to fix issue #56, but a version bump wasn't made. I realized I have the latest "version", but didn't have the fix because I use a caching registry. Could we get it bumped?
When DELETE
operation is specified in swagger.yaml
the Restify middleware tries to invoke app.delete
which is not an actual function in Restify (it uses app.del
instead). This might be the same for OPTIONS
which in Restify is app.opts
.
In previous version it was working for iteration was done over Restify's methods and now you are iterating over the methods described in swagger.yaml
As a hack I use app.delete = app.del
in my app.js.
Exception stack:
Error in callback! Tossing to global error handler. TypeError: app[method] is not a function
at registerHandler (/home/api/node_modules/swagger-restify-mw/node_modules/swagger-node-runner/lib/restify_middleware.js:24:18)
at /home/banzsh/projects/api/node_modules/swagger-restify-mw/node_modules/swagger-node-runner/lib/restify_middleware.js:33:11
at Array.forEach (native)
at /home/banzsh/projects/api/node_modules/swagger-restify-mw/node_modules/swagger-node-runner/lib/restify_middleware.js:32:31
at Array.forEach (native)
at Middleware.register (/home/banzsh/projects/api/node_modules/swagger-restify-mw/node_modules/swagger-node-runner/lib/restify_middleware.js:30:21)
at /home/banzsh/projects/api/app.js:76:20
at /home/banzsh/projects/api/node_modules/swagger-restify-mw/lib/index.js:32:5
at /home/banzsh/projects/api/node_modules/swagger-restify-mw/node_modules/swagger-node-runner/index.js:234:7
hi i am using swagger-express-mw w
IT looks like swagger validator is not is validating respone body .
_swagger_validate: { name: 'swagger_validator', validateReponse: true },
it looks like there is no use of validateReponse in fittings/swagger-validator.js
can you look at this issue ?
Hi.
The snippet bellow describes a fitting that allows using in parameters a custom attribute x-alias
that helps support API changes concerning parameter names.
The use cases which I get to met a lot, are described as:
Having an API that changed a parameter name
I would like to name in the spec only the official new name
so new users will adhere to the new wayHaving an API that changed a parameter name
I would like to be able to decide to support the old name
to help backward compatibility
And the question to you:
Now that we can officially support loading user fittings from node_modules
, I may wrap it as a package such as openapi-parameter-alias
with it's own tests and all, and let users cherry-pick it into their projects by adding this fitting one step before swagger_validation
Yes, we're ready, lets rock.
OR - alternatively -
No, its too early from your point of view to start diverging modularity, you'd rather it as a PR into bagpipes if at all. In this case, it may not even need to be a separate step. It's a light non-breaking useful feature and same work can be done in fittings/swagger_params_parser.jsaround lines
31~41saving an extra loop iteration over
swagger.params` per served request.
What are your thoughts about it?
P.S:
the snippet is expressed only as a thought, I did not ran it yet, but I hope the spirit is clear.
it's written in ES6, but it can very easily be put in ES5 if need be, (just replace const
for var
and handle the destruction and arrows the old way...
const assert = require('assert');
const debug = require('debug')('fitting:openapi_params_alias');
module.exports = function create(fittingDef) {
debug('created');
return openapi_params_alias;
function openapi_params_alias(ctx, cb) {
debug('exec');
const req = ctx.request;
const { params, operation } = req.swagger;
operation.parameterObjects.forEach( parameter => {
const name = parameter.name;
if (parameter.value) {
debug('value found on official name [%s]', name);
return;
}
const alias = parameter.definition['x-alias'];
if (!alias) {
debug('no value and no alias for [%s]', name); //if its required - validator will reject it
return;
}
const aliasParam = Object.create(parameter, { name: alias });
const aliasValue = aliasParam.getValue(req).value;
params[name].value = aliasValue;
debug('value of parameter [%s] was tried and %sfound under alias [%s]', name, aliasValue ? "" : "NOT ", alias, aliasValue);
});
cb()
}
}
My application depends upon npm module swagger-express-mw which in turn depends on this project.
This project (swagger-node-runner
) depends on npm module config
Since my application also depends on npm module config, I think it's causing a conflict because this config
module expects a single configuration directory relative to the current working directory of the process.
The outcome is that when I run the application, I think swagger-node-runner
must be reading my application config
files instead of the intended config. (swagger-node-runner
doesn't report an error)
I might be wrong about swagger-node-runner
getting hold of the application config file instead of the intended config
file but that's my reasoning based on how the config
module works.
Does anyone have any inputs as to what might be happening and the correct way of handling this problem?
btw, Is config
needed only to run the swagger editor? Or is it needed by middleware to serve a live API.
Hey, I have some express middleware I typically use with my express apps, for things like request and error logging. From tidbits I picked up in other issues, I've got it working by deactivating the error handler fitting and adding app.use()
statements inside the callback passed in to SwaggerExpress.create()
.
However, I noticed that you had some experimental code in the bagpipes library that creates a connect-middleware
fitting type. I'm interested in the idea of using existing middleware as a fitting, and messed around a bit, modifying index.js
in this repo to add a connectMiddlewareDirs
property to the pipesConfig
object, and otherwise paralleling the logic that produces the value fed into the userFittingsDirs
property of that same object.
Though I made some headway, I never got my middleware fully working as a fitting, but before continuing, I figured I should ask about your intentions with that experiment, and whether you think it a good idea to support such a thing over here.
EDITED: clarifications added here and there...
I was trying to implement security handlers.
I found the example in the test:
swagger:
bagpipes:
_swagger_security:
name: swagger_security
securityHandlersModule: api/helpers/securityHandlers
Ok. that's a start.
Imature for my flavor - but still a start.
2 problems are:
So I thought to create a PR that will accept multiple modules and consolidate them together to the securityHandlers
collection.
Something Like that:
swagger:
bagpipes:
_swagger_security:
name: swagger_security
securityHandlers:
basic: openapi-seciruty-myorg-basic
oauth: openapi-seciruty-myorg-oauth
req-ip: openapi-seciruty-myorg-req-ip
Keys are types matching api.securityDefinitions
like the openapi spec demonstrates.
About values - I thought to let them be
factory(config, cb)
that yields a handler(req,res,cb)
or handler(req,def,keyOrScope,cb)
, pre-loaded once on server-startup.config
, as siblings to swagger
, or as siblings to bagpipes
, I have not decided yet.(fittingDef,bagpipes)
like any pipe, and return a fitting. The pipe will reject a context by nexting an Error
with all rejection-info loaded on it, and accept a context by nexting a null
. I assume the error will end up with the error_json_handler
. The pipe may enrich the context with more data like middlewares often enrich request objects with user data or roles collection.These are were the early thoughts.
So I thought to have a look inside and see where it takes me.
I opened fitting/swagger_security, which calls yet again for double-checking with you...
It seems like it wants to support:
swagger:
bagpipes:
...
securityHandlers:
<but what's here? I have no idea>
After reading the code it looks to me that if config.swagger.securityHandlers
is present - no security handlers are loaded...
If you use a swagger_raw pipe to send out the swagger spec when mediated by connect_middleware, the request processing continues after the response has been sent. This eventually leads to express's default 404 handler kicking in, which in turn produces an error when it attempts to set the status code header for a response that has already been sent.
Specifically, the commit ac6dad9 needs to be reverted. It's not clear what problem it's attempting to solve, so I can't say what the impact is, but whatever it's trying to do, this manner of doing it breaks express's contact.
Stack trace:
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:690:11)
at ServerResponse.res.setHeader (/development-source/web/node_modules/express/node_modules/connect/lib/patch.js:63:22)
at next (/development-source/web/node_modules/express/node_modules/connect/lib/proto.js:156:13)
at /development-source/web/node_modules/express/lib/application.js:121:9
at next (/development-source/web/node_modules/express/node_modules/connect/lib/proto.js:129:23)
at /development-source/web/node_modules/express/lib/application.js:121:9
at next (/development-source/web/node_modules/express/node_modules/connect/lib/proto.js:129:23)
at [object Object].finishConnect (/development-source/web/node_modules/swagger-node-runner/lib/connect_middleware.js:94:13)
<snip...>
Perhaps as a config option
The HTTP status code in res.json is set always set to 200. It should be possible to set a different code within the controller, though. Removing line 220 in connect_middleware.js (res.statusCode = 200) solves the issue without having any negative effect (as far as I see).
So... am I missing a sideeffect/wanted behavior or should the line be removed?
Cheers.
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.