Socket
Socket
Sign inDemoInstall

rpcapi

Package Overview
Dependencies
175
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.6.2 to 2.0.0

src/testServer.d.ts

5

package.json
{
"name": "rpcapi",
"version": "1.6.2",
"version": "2.0.0",
"description": "Provides a struture for hosting RPC style APIs, supports both http and websocket access out of the box",

@@ -34,2 +34,3 @@ "repository": {

"dependencies": {
"@types/cors": "^2.8.3",
"@types/debug": "^0.0.30",

@@ -39,2 +40,4 @@ "@types/express": "^4.0.39",

"@types/socket.io": "^1.4.31",
"body-parser": "^1.18.2",
"cors": "^2.8.4",
"coveralls": "^3.0.0",

@@ -41,0 +44,0 @@ "debug": "^3.1.0",

13

README.md

@@ -262,2 +262,6 @@ [![Build status](https://travis-ci.org/jyelewis/RPCAPI.svg?branch=master)](https://travis-ci.org/jyelewis/RPCAPI) [![Coverage Status](https://coveralls.io/repos/github/jyelewis/RPCAPI/badge.svg?branch=master)](https://coveralls.io/github/jyelewis/RPCAPI?branch=master)

This can be changed by passing in the `prefix` configuration parameter.
All actions must be called using the 'post' http method.
parameters can either be given as json or in a url encoded format
```javascript

@@ -269,3 +273,4 @@ const webApi = new rpcapi.WebAPIAccessMethod(api, { prefix: '/myApi' });

```
/api/{endpoint name}/{action name}?param1={value1}&param2={value2}
/api/{endpoint name}/{action name}
param1={value1}&param2={value2}
```

@@ -275,3 +280,4 @@

```
/api/login/authenticateUser?username=admin&password=Qwerty1
/api/login/authenticateUser
username=admin&password=Qwerty1
```

@@ -285,3 +291,4 @@

```
/api/calculator/sumAll?values=[1, 2, 3, 4]
/api/calculator/sumAll
values=[1, 2, 3, 4]
```

@@ -288,0 +295,0 @@

@@ -6,2 +6,3 @@ /// <reference types="express" />

prefix?: string;
outputActionErrors?: boolean;
}

@@ -8,0 +9,0 @@ export declare class WebAPIAccessMethod {

@@ -44,3 +44,4 @@ "use strict";

var defaultConfig = {
prefix: '/api'
prefix: '/api',
outputActionErrors: false
};

@@ -52,2 +53,3 @@ var WebAPIAccessMethod = /** @class */ (function () {

this.prefix = config.prefix || defaultConfig.prefix;
this.outputActionErrors = config.outputActionErrors || defaultConfig.outputActionErrors;
this.api = api;

@@ -57,8 +59,13 @@ }

var _this = this;
app.get(this.prefix + "/:endpoint(*)/:action", function (req, res) {
// we must ALWAYS use post (we dont know what kind of request it is)
// get requests can easily be forged
// technically, we dont use cookies and there is no user specific data outside of the URL
// but the endpoint may collect user information (user agent, ip, custom cookies?)
// (and its not right to just allow CSRF because we dont see the harm)
app.post(this.prefix + "/:endpoint(*)/:action", function (req, res) {
var endpointName = req.params.endpoint;
var actionName = req.params.action;
var authToken = null;
if (req.query.accessKey) {
authToken = req.query.accessKey;
if (req.body.accessKey) {
authToken = req.body.accessKey;
}

@@ -73,9 +80,9 @@ else if (req.get('Authorization')) {

res.setHeader('Content-Type', 'application/json');
_this.processRequest(endpointName, actionName, req.query, authToken)
_this.processRequest(endpointName, actionName, req.body, authToken)
.then(function (result) {
debug("Request: " + endpointName + "/" + actionName + " %o: %o", req.query, result);
debug("Request: " + endpointName + "/" + actionName + " %o: %o", req.body, result);
res.end(_this.formatResult(null, result));
}).catch(function (e) {
if (e instanceof customErrors_1.NotFoundError) {
debug("Request: " + endpointName + "/" + actionName + " %o: NotFound - " + e.message, req.query);
debug("Request: " + endpointName + "/" + actionName + " %o: NotFound - " + e.message, req.body);
res

@@ -87,3 +94,3 @@ .status(404)

if (e instanceof customErrors_1.InvalidTypeError) {
debug("Request: " + endpointName + "/" + actionName + " %o: InvalidType - " + e.message, req.query);
debug("Request: " + endpointName + "/" + actionName + " %o: InvalidType - " + e.message, req.body);
res

@@ -95,3 +102,3 @@ .status(400)

if (e instanceof errorTypes_1.AccessDeniedError) {
debug("Request: " + endpointName + "/" + actionName + " %o: AccessDenied - " + e.message, req.query);
debug("Request: " + endpointName + "/" + actionName + " %o: AccessDenied - " + e.message, req.body);
res

@@ -103,3 +110,3 @@ .status(401)

if (e instanceof errorTypes_1.ActionError) {
debug("Request: " + endpointName + "/" + actionName + " %o: ActionError - " + e.message, req.query);
debug("Request: " + endpointName + "/" + actionName + " %o: ActionError - " + e.message, req.body);
res

@@ -116,3 +123,3 @@ .status(400)

}
debug("Request: " + endpointName + "/" + actionName + " %o: Unknown error - " + e.message, req.query);
debug("Request: " + endpointName + "/" + actionName + " %o: Unknown error - " + e.message, req.body);
});

@@ -132,3 +139,3 @@ });

return __awaiter(this, void 0, void 0, function () {
var endpoint, actionParams, typedParams, paramName, actionParamType, epValue;
var endpoint, actionParams, typedParams, paramName, actionParamType, strVal, epValue;
return __generator(this, function (_a) {

@@ -153,3 +160,4 @@ switch (_a.label) {

actionParamType = actionParams[paramName];
typedParams[paramName] = convertParamType_1.convertParamType(actionParamType, paramName, strParams[paramName]);
strVal = strParams[paramName] === undefined ? undefined : strParams[paramName].toString();
typedParams[paramName] = convertParamType_1.convertParamType(actionParamType, paramName, strVal);
}

@@ -156,0 +164,0 @@ }

@@ -50,5 +50,2 @@ "use strict";

var ava_1 = require("ava");
var index_1 = require("./index");
var express = require("express");
var http = require("http");
var APIEndpoint_1 = require("../../APIEndpoint");

@@ -58,36 +55,41 @@ var API_1 = require("../../API");

var errorTypes_1 = require("../../errorTypes");
var server;
ava_1.default.before(function () {
var TestEndpoint = /** @class */ (function (_super) {
__extends(TestEndpoint, _super);
function TestEndpoint() {
return _super !== null && _super.apply(this, arguments) || this;
ava_1.default.before(function () { return __awaiter(_this, void 0, void 0, function () {
var TestEndpoint, testAPI;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
TestEndpoint = /** @class */ (function (_super) {
__extends(TestEndpoint, _super);
function TestEndpoint() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.$addParams = { a: 'number', b: 'number' };
return _this;
}
TestEndpoint.prototype.$sayHello = function () {
return { hello: 'world' };
};
TestEndpoint.prototype.$requiresAuth = function () {
if (this.accessKey !== 'myAccessKey') {
throw new errorTypes_1.AccessDeniedError('Invalid access key');
}
return { hello: 'world' };
};
TestEndpoint.prototype.$add = function (_a) {
var a = _a.a, b = _a.b;
return { value: a + b };
};
return TestEndpoint;
}(APIEndpoint_1.APIEndpoint));
testAPI = new API_1.API();
testAPI.registerEndpoint('test', TestEndpoint);
testAPI.registerEndpoint('endpoint/with/many/slashes', TestEndpoint);
return [4 /*yield*/, testAPI.listen(8057, {
webApi: {
outputActionErrors: false
}
})];
case 1:
_a.sent();
return [2 /*return*/];
}
TestEndpoint.prototype.$sayHello = function () {
return { hello: 'world' };
};
TestEndpoint.prototype.$requiresAuth = function () {
if (this.accessKey !== 'myAccessKey') {
throw new errorTypes_1.AccessDeniedError('Invalid access key');
}
return { hello: 'world' };
};
return TestEndpoint;
}(APIEndpoint_1.APIEndpoint));
var testAPI = new API_1.API();
testAPI.registerEndpoint('test', TestEndpoint);
testAPI.registerEndpoint('endpoint/with/many/slashes', TestEndpoint);
var app = express();
server = new http.Server(app);
//Setup access methods
var webapiAM = new index_1.WebAPIAccessMethod(testAPI);
webapiAM.outputActionErrors = false;
webapiAM.bind(app);
//server listen
server.listen(8057);
});
ava_1.default.after(function (t) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
server.close();
return [2 /*return*/];
});

@@ -99,3 +101,10 @@ }); });

switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/sayHello')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/sayHello', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
})];
case 1:

@@ -116,3 +125,10 @@ res = _c.sent();

switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/endpoint/with/many/slashes/sayHello')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/endpoint/with/many/slashes/sayHello', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
})];
case 1:

@@ -133,3 +149,12 @@ res = _c.sent();

switch (_e.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/requiresAuth?accessKey=myAccessKey')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/requiresAuth', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
accessKey: 'myAccessKey'
})
})];
case 1:

@@ -142,3 +167,12 @@ res1 = _e.sent();

_b.apply(_a, [_e.sent(), { error: null, result: { hello: 'world' } }]);
return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/requiresAuth?accessKey=invalidaccesskey')];
return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/requiresAuth', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
accessKey: 'invalidaccesskey'
})
})];
case 3:

@@ -155,2 +189,51 @@ res2 = _e.sent();

}); });
ava_1.default('Reads parameters from json encoded body', function (t) { return __awaiter(_this, void 0, void 0, function () {
var res1, _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/add', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 3,
b: 7
})
})];
case 1:
res1 = _c.sent();
t.is(res1.status, 200);
_b = (_a = t).deepEqual;
return [4 /*yield*/, res1.json()];
case 2:
_b.apply(_a, [_c.sent(), { error: null, result: { value: 10 } }]);
return [2 /*return*/];
}
});
}); });
ava_1.default('reads parameters from urlencoded body', function (t) { return __awaiter(_this, void 0, void 0, function () {
var res1, _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/add', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'a=3&b=7'
})];
case 1:
res1 = _c.sent();
t.is(res1.status, 200);
_b = (_a = t).deepEqual;
return [4 /*yield*/, res1.json()];
case 2:
_b.apply(_a, [_c.sent(), { error: null, result: { value: 10 } }]);
return [2 /*return*/];
}
});
}); });
ava_1.default('Allows authenticating via Bearer header', function (t) { return __awaiter(_this, void 0, void 0, function () {

@@ -161,3 +244,6 @@ var res1, _a, _b, res2, _c, _d;

case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/requiresAuth', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"Authorization": "Bearer myAccessKey"

@@ -174,3 +260,6 @@ }

return [4 /*yield*/, node_fetch_1.default('http://localhost:8057/api/test/requiresAuth', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"Authorization": "Bearer invalidaccesskey"

@@ -177,0 +266,0 @@ }

/// <reference types="node" />
import { APIEndpoint } from "./APIEndpoint";
import * as http from 'http';
import { IWebAPIAccessMethodConfig } from "./accessMethods/WebAPIAccessMethod/index";
import { IWebAPIAccessMethodConfig } from "./accessMethods/WebAPIAccessMethod";
export interface IAPIListenConfig {

@@ -6,0 +6,0 @@ webApi?: IWebAPIAccessMethodConfig;

@@ -84,3 +84,3 @@ "use strict";

switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8258/api/test/test')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:8258/api/test/test', { method: 'post' })];
case 1:

@@ -87,0 +87,0 @@ response = _c.sent();

@@ -6,7 +6,9 @@ "use strict";

var helmet = require("helmet");
var cors = require("cors");
var socketio = require("socket.io");
var http = require("http");
var index_1 = require("./accessMethods/WebAPIAccessMethod/index");
var index_2 = require("./accessMethods/WebSocketAccessMethod/index");
var WebAPIAccessMethod_1 = require("./accessMethods/WebAPIAccessMethod");
var WebSocketAccessMethod_1 = require("./accessMethods/WebSocketAccessMethod");
var isValidEndpointName_1 = require("./isValidEndpointName");
var bodyParser = require("body-parser");
var API = /** @class */ (function () {

@@ -46,7 +48,17 @@ function API() {

app.use(helmet());
app.use(cors());
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(function (err, req, res, next) {
res.status(500);
res.end('{"error":"Internal server error","result":null}');
console.error(err);
});
_this.server = new http.Server(app);
var io = socketio(_this.server);
//Setup access methods
var webApi = new index_1.WebAPIAccessMethod(_this, options.webApi);
var socketApi = new index_2.WebSocketAccessMethod(_this);
var webApi = new WebAPIAccessMethod_1.WebAPIAccessMethod(_this, options.webApi);
var socketApi = new WebSocketAccessMethod_1.WebSocketAccessMethod(_this);
webApi.bind(app);

@@ -53,0 +65,0 @@ socketApi.bind(io);

@@ -42,25 +42,17 @@ "use strict";

//Starts up a real web server and hits it
var express = require("express");
var http = require("http");
var index_1 = require("../accessMethods/WebAPIAccessMethod/index");
var API_1 = require("../API");
var CalculatorEndpoint_1 = require("../testEndpoints/CalculatorEndpoint");
ava_1.default.before(function () { return __awaiter(_this, void 0, void 0, function () {
var app, server, api, webApi;
var api;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
app = express();
server = new http.Server(app);
api = new API_1.API();
api.registerEndpoint('calculator', CalculatorEndpoint_1.CalculatorEndpoint);
webApi = new index_1.WebAPIAccessMethod(api, { prefix: '/api' });
webApi.outputActionErrors = false;
webApi.bind(app);
//server listen
return [4 /*yield*/, new Promise(function (resolve) {
return server.listen(55536, resolve);
return [4 /*yield*/, api.listen(55536, {
webApi: {
outputActionErrors: false
}
})];
case 1:
//server listen
_a.sent();

@@ -75,3 +67,13 @@ return [2 /*return*/];

switch (_a.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/add?a=1&b=2')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/add', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 1,
b: 2
})
})];
case 1:

@@ -88,3 +90,13 @@ res = _a.sent();

switch (_a.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/asdf/add?a=1&b=2')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/asdf/add', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 1,
b: 2
})
})];
case 1:

@@ -101,3 +113,13 @@ res = _a.sent();

switch (_a.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/asdf?a=1&b=2')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/asdf', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 1,
b: 2
})
})];
case 1:

@@ -114,3 +136,13 @@ res = _a.sent();

switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/add?a=1&b=2')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/add', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 1,
b: 2
})
})];
case 1:

@@ -131,3 +163,13 @@ res = _c.sent();

switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/slowAdd?a=1&b=2')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/slowAdd', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 1,
b: 2
})
})];
case 1:

@@ -148,3 +190,13 @@ res = _c.sent();

switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/add?a=a&b=2')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/add', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 'a',
b: 2
})
})];
case 1:

@@ -165,3 +217,12 @@ res = _c.sent();

switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/add?b=2')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/add', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
b: 2
})
})];
case 1:

@@ -182,3 +243,10 @@ res = _c.sent();

switch (_c.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/throws')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/throws', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
})];
case 1:

@@ -199,3 +267,14 @@ res = _c.sent();

switch (_e.label) {
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/specialAdd?a=5&b=7&strAdd=false')];
case 0: return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/specialAdd', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 5,
b: 7,
strAdd: false
})
})];
case 1:

@@ -208,3 +287,14 @@ res = _e.sent();

_b.apply(_a, [_e.sent(), { error: null, result: { value: 12 } }]);
return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/specialAdd?a=5&b=7&strAdd=true')];
return [4 /*yield*/, node_fetch_1.default('http://localhost:55536/api/calculator/specialAdd', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
a: 5,
b: 7,
strAdd: true
})
})];
case 3:

@@ -211,0 +301,0 @@ res2 = _e.sent();

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc