Multiple REST endpoints (one per version)

pull/1527/head
nelson.silva 2013-02-16 14:57:09 +00:00 committed by Nelson Silva
parent 8f279a6710
commit a5987285e0
1 changed files with 123 additions and 107 deletions

View File

@ -1,13 +1,9 @@
var log4js = require('log4js'); var log4js = require('log4js');
var express = require('express'); var express = require('express');
var swagger = require("swagger-node-express");
var apiHandler = require('../../handler/APIHandler'); var apiHandler = require('../../handler/APIHandler');
var apiCaller = require('./apicalls').apiCaller; var apiCaller = require('./apicalls').apiCaller;
var settings = require("../../utils/Settings"); var settings = require("../../utils/Settings");
var versions = Object.keys(apiHandler.version)
var version = versions[versions.length - 1];
var swaggerModels = { var swaggerModels = {
'models': { 'models': {
'SessionInfo' : { 'SessionInfo' : {
@ -83,14 +79,14 @@ var API = {
// Group // Group
"group": { "group": {
"create" : { "create" : {
"func" : "createGroup", "func" : "createGroup",
"description": "creates a new group", "description": "creates a new group",
"response": {"groupID":{"type":"string"}} "response": {"groupID":{"type":"string"}}
}, },
"createIfNotExistsFor" : { "createIfNotExistsFor" : {
"func": "createGroupIfNotExistsFor", "func": "createGroupIfNotExistsFor",
"description": "this functions helps you to map your application group ids to etherpad lite group ids", "description": "this functions helps you to map your application group ids to etherpad lite group ids",
"response": {"groupID":{"type":"string"}} "response": {"groupID":{"type":"string"}}
}, },
"delete" : { "delete" : {
@ -98,23 +94,23 @@ var API = {
"description": "deletes a group" "description": "deletes a group"
}, },
"listPads" : { "listPads" : {
"func": "listPads", "func": "listPads",
"description": "returns all pads of this group", "description": "returns all pads of this group",
"response": {"padIDs":{"type":"List", "items":{"type":"string"}}} "response": {"padIDs":{"type":"List", "items":{"type":"string"}}}
}, },
"createPad" : { "createPad" : {
"func": "createGroupPad", "func": "createGroupPad",
"description": "creates a new pad in this group" "description": "creates a new pad in this group"
}, },
"listSessions": { "listSessions": {
"func": "listSessionsOfGroup", "func": "listSessionsOfGroup",
"responseProcessor": sessionListResponseProcessor, "responseProcessor": sessionListResponseProcessor,
"description": "", "description": "",
"response": {"sessions":{"type":"List", "items":{"type":"SessionInfo"}}} "response": {"sessions":{"type":"List", "items":{"type":"SessionInfo"}}}
}, },
"list": { "list": {
"func": "listAllGroups", "func": "listAllGroups",
"description": "", "description": "",
"response": {"groupIDs":{"type":"List", "items":{"type":"string"}}} "response": {"groupIDs":{"type":"List", "items":{"type":"string"}}}
}, },
}, },
@ -122,24 +118,24 @@ var API = {
// Author // Author
"author": { "author": {
"create" : { "create" : {
"func" : "createAuthor", "func" : "createAuthor",
"description": "creates a new author", "description": "creates a new author",
"response": {"authorID":{"type":"string"}} "response": {"authorID":{"type":"string"}}
}, },
"createIfNotExistsFor": { "createIfNotExistsFor": {
"func": "createAuthorIfNotExistsFor", "func": "createAuthorIfNotExistsFor",
"description": "this functions helps you to map your application author ids to etherpad lite author ids", "description": "this functions helps you to map your application author ids to etherpad lite author ids",
"response": {"authorID":{"type":"string"}} "response": {"authorID":{"type":"string"}}
}, },
"listPads": { "listPads": {
"func": "listPadsOfAuthor", "func": "listPadsOfAuthor",
"description": "returns an array of all pads this author contributed to", "description": "returns an array of all pads this author contributed to",
"response": {"padIDs":{"type":"List", "items":{"type":"string"}}} "response": {"padIDs":{"type":"List", "items":{"type":"string"}}}
}, },
"listSessions": { "listSessions": {
"func": "listSessionsOfAuthor", "func": "listSessionsOfAuthor",
"responseProcessor": sessionListResponseProcessor, "responseProcessor": sessionListResponseProcessor,
"description": "returns all sessions of an author", "description": "returns all sessions of an author",
"response": {"sessions":{"type":"List", "items":{"type":"SessionInfo"}}} "response": {"sessions":{"type":"List", "items":{"type":"SessionInfo"}}}
}, },
// We need an operation that return a UserInfo so it can be picked up by the codegen :( // We need an operation that return a UserInfo so it can be picked up by the codegen :(
@ -158,7 +154,7 @@ var API = {
"session": { "session": {
"create" : { "create" : {
"func": "createSession", "func": "createSession",
"description": "creates a new session. validUntil is an unix timestamp in seconds", "description": "creates a new session. validUntil is an unix timestamp in seconds",
"response": {"sessionID":{"type":"string"}} "response": {"sessionID":{"type":"string"}}
}, },
"delete" : { "delete" : {
@ -167,7 +163,7 @@ var API = {
}, },
// We need an operation that returns a SessionInfo so it can be picked up by the codegen :( // We need an operation that returns a SessionInfo so it can be picked up by the codegen :(
"info": { "info": {
"func": "getSessionInfo", "func": "getSessionInfo",
"description": "returns informations about a session", "description": "returns informations about a session",
"responseProcessor": function(response) { "responseProcessor": function(response) {
// move this to info // move this to info
@ -177,22 +173,22 @@ var API = {
} }
}, },
"response": {"info":{"type":"SessionInfo"}} "response": {"info":{"type":"SessionInfo"}}
}, }
}, },
"pad": { "pad": {
"listAll" : { "listAll" : {
"func": "listAllPads", "func": "listAllPads",
"description": "list all the pads", "description": "list all the pads",
"response": {"padIDs":{"type":"List", "items": {"type" : "string"}}} "response": {"padIDs":{"type":"List", "items": {"type" : "string"}}}
}, },
"createDiffHTML" : { "createDiffHTML" : {
"func" : "createDiffHTML", "func" : "createDiffHTML",
"description": "", "description": "",
"response": {} "response": {}
}, },
"create" : { "create" : {
"func" : "createPad", "func" : "createPad",
"description": "creates a new (non-group) pad. Note that if you need to create a group Pad, you should call createGroupPad", "description": "creates a new (non-group) pad. Note that if you need to create a group Pad, you should call createGroupPad"
}, },
"getText" : { "getText" : {
"func" : "getText", "func" : "getText",
@ -205,7 +201,7 @@ var API = {
}, },
"getHTML": { "getHTML": {
"func" : "getHTML", "func" : "getHTML",
"description": "returns the text of a pad formatted as HTML", "description": "returns the text of a pad formatted as HTML",
"response": {"html":{"type":"string"}} "response": {"html":{"type":"string"}}
}, },
"setHTML": { "setHTML": {
@ -214,12 +210,12 @@ var API = {
}, },
"getRevisionsCount": { "getRevisionsCount": {
"func" : "getRevisionsCount", "func" : "getRevisionsCount",
"description": "returns the number of revisions of this pad", "description": "returns the number of revisions of this pad",
"response": {"revisions":{"type":"long"}} "response": {"revisions":{"type":"long"}}
}, },
"getLastEdited": { "getLastEdited": {
"func" : "getLastEdited", "func" : "getLastEdited",
"description": "returns the timestamp of the last revision of the pad", "description": "returns the timestamp of the last revision of the pad",
"response": {"lastEdited":{"type":"long"}} "response": {"lastEdited":{"type":"long"}}
}, },
"delete": { "delete": {
@ -228,16 +224,16 @@ var API = {
}, },
"getReadOnlyID": { "getReadOnlyID": {
"func" : "getReadOnlyID", "func" : "getReadOnlyID",
"description": "returns the read only link of a pad", "description": "returns the read only link of a pad",
"response": {"readOnlyID":{"type":"string"}} "response": {"readOnlyID":{"type":"string"}}
}, },
"setPublicStatus": { "setPublicStatus": {
"func": "setPublicStatus", "func": "setPublicStatus",
"description": "sets a boolean for the public status of a pad" "description": "sets a boolean for the public status of a pad"
}, },
"getPublicStatus": { "getPublicStatus": {
"func": "getPublicStatus", "func": "getPublicStatus",
"description": "return true of false", "description": "return true of false",
"response": {"publicStatus":{"type":"boolean"}} "response": {"publicStatus":{"type":"boolean"}}
}, },
"setPassword": { "setPassword": {
@ -245,27 +241,27 @@ var API = {
"description": "returns ok or a error message" "description": "returns ok or a error message"
}, },
"isPasswordProtected": { "isPasswordProtected": {
"func": "isPasswordProtected", "func": "isPasswordProtected",
"description": "returns true or false", "description": "returns true or false",
"response": {"passwordProtection":{"type":"boolean"}} "response": {"passwordProtection":{"type":"boolean"}}
}, },
"authors": { "authors": {
"func": "listAuthorsOfPad", "func": "listAuthorsOfPad",
"description": "returns an array of authors who contributed to this pad", "description": "returns an array of authors who contributed to this pad",
"response": {"authorIDs":{"type":"List", "items":{"type" : "string"}}} "response": {"authorIDs":{"type":"List", "items":{"type" : "string"}}}
}, },
"usersCount": { "usersCount": {
"func": "padUsersCount", "func": "padUsersCount",
"description": "returns the number of user that are currently editing this pad", "description": "returns the number of user that are currently editing this pad",
"response": {"padUsersCount":{"type": "long"}} "response": {"padUsersCount":{"type": "long"}}
}, },
"users": { "users": {
"func": "padUsers", "func": "padUsers",
"description": "returns the list of users that are currently editing this pad", "description": "returns the list of users that are currently editing this pad",
"response": {"padUsers":{"type":"List", "items":{"type": "UserInfo"}}} "response": {"padUsers":{"type":"List", "items":{"type": "UserInfo"}}}
}, },
"sendClientsMessage": { "sendClientsMessage": {
"func": "sendClientsMessage", "func": "sendClientsMessage",
"description": "sends a custom message of type msg to the pad" "description": "sends a custom message of type msg to the pad"
}, },
"checkToken" : { "checkToken" : {
@ -273,13 +269,13 @@ var API = {
"description": "returns ok when the current api token is valid" "description": "returns ok when the current api token is valid"
}, },
"getChatHistory": { "getChatHistory": {
"func": "getChatHistory", "func": "getChatHistory",
"description": "returns the chat history", "description": "returns the chat history",
"response": {"messages":{"type":"List", "items": {"type" : "Message"}}} "response": {"messages":{"type":"List", "items": {"type" : "Message"}}}
}, },
// We need an operation that returns a Message so it can be picked up by the codegen :( // We need an operation that returns a Message so it can be picked up by the codegen :(
"getChatHead": { "getChatHead": {
"func": "getChatHead", "func": "getChatHead",
"description": "returns the chatHead (chat-message) of the pad", "description": "returns the chatHead (chat-message) of the pad",
"responseProcessor": function(response) { "responseProcessor": function(response) {
// move this to info // move this to info
@ -334,82 +330,102 @@ for (var resource in API) {
// Store the response model id // Store the response model id
API[resource][func]["responseClass"] = responseModelId; API[resource][func]["responseClass"] = responseModelId;
// get the api function
var apiFunc = apiHandler.version[version][API[resource][func]["func"]];
// Add the api function parameters
API[resource][func]["params"] = apiFunc.map( function(param) {
return swagger.queryParam(param, param, "string");
});
} }
} }
function newSwagger() {
var swagger_module = require.resolve("swagger-node-express");
if (require.cache[swagger_module]) {
// delete the child modules from cache
require.cache[swagger_module].children.forEach(function(m) {delete require.cache[m.id];});
// delete the module from cache
delete require.cache[swagger_module];
}
return require("swagger-node-express");
}
exports.expressCreateServer = function (hook_name, args, cb) { exports.expressCreateServer = function (hook_name, args, cb) {
// Let's put this under /rest for now for (var version in apiHandler.version) {
var subpath = express();
var swagger = newSwagger();
var basePath = "/rest/" + version;
args.app.use(express.bodyParser()); // Let's put this under /rest for now
args.app.use("/rest", subpath); var subpath = express();
swagger.setAppHandler(subpath); args.app.use(express.bodyParser());
args.app.use(basePath, subpath);
swagger.addModels(swaggerModels); swagger.setAppHandler(subpath);
for (var resource in API) { swagger.addModels(swaggerModels);
for (var funcName in API[resource]) { for (var resource in API) {
var func = API[resource][funcName];
var swaggerFunc = { for (var funcName in API[resource]) {
'spec': { var func = API[resource][funcName];
"description" : func["description"],
"path" : "/" + resource + "/" + funcName,
"summary" : funcName,
"nickname" : funcName,
"method": "GET",
"params" : func["params"],
"responseClass" : func["responseClass"]
},
'action': (function(func, responseProcessor) {
return function (req,res) {
req.params.version = version;
req.params.func = func; // call the api function
//wrap the send function so we can process the response // get the api function
res.__swagger_send = res.send; var apiFunc = apiHandler.version[version][func["func"]];
res.send = function (response) {
// ugly but we need to get this as json // Skip this one if it does not exist in the version
response = JSON.parse(response); if(!apiFunc) {
// process the response if needed continue;
if (responseProcessor) { }
response = responseProcessor(response);
} var swaggerFunc = {
// Let's move everything out of "data" 'spec': {
if (response.data) { "description" : func["description"],
for(var prop in response.data) { "path" : "/" + resource + "/" + funcName,
response[prop] = response.data[prop]; "summary" : funcName,
delete response.data; "nickname" : funcName,
"method": "GET",
"params" : apiFunc.map( function(param) {
return swagger.queryParam(param, param, "string");
}),
"responseClass" : func["responseClass"]
},
'action': (function(func, responseProcessor) {
return function (req,res) {
req.params.version = version;
req.params.func = func; // call the api function
//wrap the send function so we can process the response
res.__swagger_send = res.send;
res.send = function (response) {
// ugly but we need to get this as json
response = JSON.parse(response);
// process the response if needed
if (responseProcessor) {
response = responseProcessor(response);
} }
} // Let's move everything out of "data"
response = JSON.stringify(response); if (response.data) {
res.__swagger_send(response); for(var prop in response.data) {
} response[prop] = response.data[prop];
delete response.data;
}
}
response = JSON.stringify(response);
res.__swagger_send(response);
};
apiCaller(req, res, req.query); apiCaller(req, res, req.query);
}; };
})(func["func"], func["responseProcessor"]) // must use a closure here })(func["func"], func["responseProcessor"]) // must use a closure here
}; };
swagger.addGet(swaggerFunc); swagger.addGet(swaggerFunc);
}
} }
swagger.setHeaders = function setHeaders(res) {
res.header('Access-Control-Allow-Origin', "*");
};
swagger.configureSwaggerPaths("", "/api" , "");
swagger.configure("http://" + settings.ip + ":" + settings.port + basePath, version);
} }
};
swagger.setHeaders = function setHeaders(res) {
res.header('Access-Control-Allow-Origin', "*");
};
swagger.configureSwaggerPaths("", "/api" , "");
swagger.configure("http://" + settings.ip + ":" + settings.port + "/rest", version);
}