Skip to content
This repository has been archived by the owner on Sep 14, 2022. It is now read-only.

add action pipeline support #132

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 21 additions & 9 deletions lib/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var shallowClone = require('./shallowClone');


function Swagger() {

if (!(this instanceof Swagger)){
return new Swagger();
}
Expand Down Expand Up @@ -348,8 +348,13 @@ Swagger.prototype.resourceListing = function(req, res) {
res.end();
};

// Adds a method to the api along with a spec. If the spec fails to validate, it won't be added

/**
* Adds a method to the api along with a spec. If the spec fails to validate, it won't be added
*
* @param {Express} app Express instance.
* @param {Function|[Function]} callback Individual action or pipeline of handlers.
* @param {Object} spec Operation swagger spec.
*/
Swagger.prototype.addMethod = function(app, callback, spec) {
var self = this;
var apiRootPath = spec.path.split(/[\/\(]/)[1];
Expand Down Expand Up @@ -388,11 +393,15 @@ Swagger.prototype.addMethod = function(app, callback, spec) {
root.apis.push(api);
appendToApi(root, api, spec);

// convert .{format} to .json, make path params happy
var fullPath = spec.path.replace(self.formatString, self.jsonSuffix).replace(/\/{/g, "/:").replace(/\}/g, "");
// convert .{format} to .json, make path params happy, remove trailing slash
var fullPath = spec.path.replace(self.formatString, self.jsonSuffix)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mgutz even though this is just formatting, I would prefer to see it in a separate commit.

.replace(/\/{/g, "/:")
.replace(/\}/g, "")
.replace(/\/$/, ""); // allows ending slash to be optional '/resource' and '/resource/'
var currentMethod = spec.method.toLowerCase();
if (allowedMethods.indexOf(currentMethod) > -1) {
app[currentMethod](fullPath, function (req, res, next) {

var checkAccess = function (req, res, next) {
self.setHeaders(res);

// todo: needs to do smarter matching against the defined paths
Expand All @@ -403,9 +412,12 @@ Swagger.prototype.addMethod = function(app, callback, spec) {
"code": 403
}), 403);
} else {
callback(req, res, next);
next();
}
});
};

var pipeline = _.flatten([checkAccess, callback]);
app[currentMethod](fullPath, pipeline);
} else {
console.error('unable to add ' + currentMethod.toUpperCase() + ' handler');
return;
Expand Down Expand Up @@ -599,7 +611,7 @@ function error(code, description) {

// Stop express ressource with error code

stopWithError = function(res, error) {
var stopWithError = function(res, error) {
this.setHeaders(res);
if (error && error.message && error.code)
res.send(JSON.stringify(error), error.code);
Expand Down
11 changes: 6 additions & 5 deletions sample-application/app.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// ### Swagger Sample Application
//
//
// This is a sample application which uses the [swagger-node-express](https://github.com/wordnik/swagger-node-express)
// module. The application is organized in the following manner:
//
// #### petResources.js
//
//
// All API methods for this petstore implementation live in this file and are added to the swagger middleware.
//
// #### models.js
//
// This contains all model definitions which are sent & received from the API methods.
// This contains all model definitions which are sent & received from the API methods.
//
// #### petData.js
//
Expand Down Expand Up @@ -57,7 +57,7 @@ swagger.addValidator(
if (!apiKey) {
apiKey = url.parse(req.url,true).query["api_key"]; }
if ("special-key" == apiKey) {
return true;
return true;
}
return false;
}
Expand All @@ -74,7 +74,8 @@ swagger.addModels(models)
.addGet(petResources.findByStatus)
.addPost(petResources.addPet)
.addPut(petResources.updatePet)
.addDelete(petResources.deletePet);
.addDelete(petResources.deletePet)
.addGet(petResources.helloPet);

swagger.configureDeclaration("pet", {
description : "Operations about Pets",
Expand Down
46 changes: 36 additions & 10 deletions sample-application/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var petData = require("./service.js");
// the description will be picked up in the resource listing
exports.findById = {
'spec': {
description : "Operations about pets",
description : "Operations about pets",
path : "/pet/{petId}",
method: "GET",
summary : "Find pet by ID",
Expand All @@ -35,7 +35,7 @@ exports.findByStatus = {
path : "/pet/findByStatus",
notes : "Multiple status values can be provided with comma-separated strings",
summary : "Find pets by status",
method: "GET",
method: "GET",
parameters : [
param.query("status", "Status in the store", "string", true, ["available","pending","sold"], "available")
],
Expand All @@ -45,7 +45,7 @@ exports.findByStatus = {
},
responseMessages : [swe.invalid('status')],
nickname : "findPetsByStatus"
},
},
'action': function (req,res) {
var statusString = url.parse(req.url,true).query["status"];
if (!statusString) {
Expand All @@ -61,7 +61,7 @@ exports.findByTags = {
path : "/pet/findByTags",
notes : "Multiple tags can be provided with comma-separated strings. Use tag1, tag2, tag3 for testing.",
summary : "Find pets by tags",
method: "GET",
method: "GET",
parameters : [param.query("tags", "Tags to filter by", "string", true)],
type : "array",
items: {
Expand Down Expand Up @@ -89,7 +89,7 @@ exports.addPet = {
parameters : [param.body("Pet", "Pet object that needs to be added to the store", "Pet")],
responseMessages : [swe.invalid('input')],
nickname : "addPet"
},
},
'action': function(req, res) {
var body = req.body;
if(!body || !body.id){
Expand All @@ -98,20 +98,20 @@ exports.addPet = {
else{
petData.addPet(body);
res.send(200);
}
}
}
};

exports.updatePet = {
'spec': {
path : "/pet",
notes : "updates a pet in the store",
method: "PUT",
method: "PUT",
summary : "Update an existing pet",
parameters : [param.body("Pet", "Pet object that needs to be updated in the store", "Pet")],
responseMessages : [swe.invalid('id'), swe.notFound('pet'), swe.invalid('input')],
nickname : "addPet"
},
},
'action': function(req, res) {
var body = req.body;
if(!body || !body.id){
Expand All @@ -132,11 +132,37 @@ exports.deletePet = {
summary : "Remove an existing pet",
parameters : [param.path("id", "ID of pet that needs to be removed", "string")],
responseMessages : [swe.invalid('id'), swe.notFound('pet')],
nickname : "deletePet"
},
nickname : "deletePet"
},
'action': function(req, res) {
var id = parseInt(req.params.id);
petData.deletePet(id)
res.send(204);
}
};


exports.helloPet = {
spec: {
path : "/pet/hello/{name}",
notes : "says hello to a pet using pipeline",
method: "GET",
summary : "Says hello to pet",
parameters : [param.path("name", "Pet's name", "string")],
responseMessages : [swe.invalid('id'), swe.notFound('pet')],
nickname : "helloPet"
},
action: [
function(req, res, next) {
req.petFormat = 'Hello {name}!';
next();
},
function(req, res) {
var name = req.params.name;
var message = req.petFormat.replace('{name}', name);
res.json({message: message});
}
]
};


19 changes: 19 additions & 0 deletions test/sample-application.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,25 @@ describe('sample application', function(){
});
});

describe('pipeline /pet/hello/:name', function(){
it('should return message built by pipeline', function(done){
request(endpoint + '/pet/hello/fido', {json:true}, function(err, res, body){
body.message.should.equal('Hello fido!');
res.statusCode.should.equal(200);
done(err);
});
});

it('should also work with trailing slash', function(done){
request(endpoint + '/pet/hello/fido/', {json:true}, function(err, res, body){
body.message.should.equal('Hello fido!');
res.statusCode.should.equal(200);
done(err);
});
});
});



describe('error handling', function(){
it('should use the express error handler', function(done){
Expand Down