Socket
Socket
Sign inDemoInstall

@wix/be-server

Package Overview
Dependencies
Maintainers
4
Versions
117
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wix/be-server - npm Package Compare versions

Comparing version 1.0.5 to 1.0.6

lib/proto-modules-bindings.js

4

index.js
const {serverBuilder} = require('./lib/server-builder');
const protoModulesBindings = require('./lib/proto-modules-bindings');
module.exports = {
builder: serverBuilder
builder: serverBuilder,
fromProtoModules: protoModulesBindings
};
const url = require('url');
const UrlPattern = require('url-pattern');
const {resolveHttpRoutes} = require('@wix/be-http-binding');
const querystring = require('querystring');
module.exports = function routes(services, messageTypes) {
module.exports = function routes(bindings) {
const routes = {};
services.forEach(({service, bindings = {}}) => {
const serviceRoutes = resolveHttpRoutes(service);
bindings.forEach(({binding, invoke}) => {
binding.httpRoutes().forEach(({method, path}) => {
const httpMethodLower = method.toLowerCase();
if (!routes[httpMethodLower]) {
routes[httpMethodLower] = [];
}
Object.keys(serviceRoutes).forEach((methodName) => {
const methodRoutes = serviceRoutes[methodName];
const method = service.methods[methodName];
const requestMessage = messageTypes.lookup(method.parent, method.requestType);
Object.keys(methodRoutes).forEach((httpMethod) => {
const httpMethodLower = httpMethod.toLowerCase();
if (!routes[httpMethodLower]) {
routes[httpMethodLower] = [];
}
methodRoutes[httpMethod].forEach((path) => {
routes[httpMethodLower].push({
pattern: new UrlPattern(fromCurly(path)),
method,
requestMessage,
implementation: bindings[methodName]
});
});
routes[httpMethodLower].push({
pattern: new UrlPattern(fromCurly(path)),
method,
invoke: binding.createInvoke(invoke)
});
});
})
});
return {
resolve(httpMethod, uri) {
const parsedUri = url.parse(uri);
const methodsForHttpMethod = routes[httpMethod.toLowerCase()];
if (!methodsForHttpMethod) {
return;
return {};
}
let resolvedRoute;
let request;
let request = {};
for (let i = 0; i < methodsForHttpMethod.length; i++) {

@@ -59,3 +46,3 @@ request = methodsForHttpMethod[i].pattern.match(parsedUri.pathname);

if (parsedUri.query > '') {
if (request && parsedUri.query > '') {
const query = querystring.parse(parsedUri.query);

@@ -69,3 +56,3 @@

return {
route: resolvedRoute,
invoke: resolvedRoute ? resolvedRoute.invoke : null,
request

@@ -72,0 +59,0 @@ };

const routes = require('./routes');
const messageTypes = require('./message-types');
const {expect} = require('chai');
const protobufjs = require('protobufjs');
const {httpBinding, messageBuilder, wellKnownTypes} = require('@wix/be-http-binding');
const {http, get} = httpBinding;
describe('Routes', () => {
it('should match and resolve values in URI', () => {
const givenRoutes = routesFrom(`
service TestRoutes {
rpc Get (Message) returns (Message) {
option (google.api.http) = {
get: "/api/{valueFromPath}"
};
}
}
const echoMessage = messageBuilder().field('message', wellKnownTypes.string, 1).build();
message Message {
string value_from_path = 1;
string value_from_query = 2;
}
`);
it('should match a GET route', async() => {
const givenBinding = http(get('/echo'), echoMessage, echoMessage);
const givenRoutes = routes([{
binding: givenBinding,
invoke: (message) => message
}]);
const {request, route} = givenRoutes.resolve('GET', '/api/path-1?valueFromQuery=query-1');
const {request, invoke} = givenRoutes.resolve('GET', '/echo?message=Hello');
expect(route.method.name).to.equal('Get');
expect(request).to.deep.equal({
valueFromPath: 'path-1',
valueFromQuery: 'query-1'
});
expect(request).to.deep.equal({
message: 'Hello'
});
expect(invoke).to.exist;
expect(await invoke(request)).to.deep.equal(request);
});
it('should match and resolve values in URI', async() => {
const givenMessage = messageBuilder()
.field('valueFromPath', wellKnownTypes.string, 1)
.field('valueFromQuery', wellKnownTypes.string, 2)
.build();
const givenBinding = http(get('/api/{valueFromPath}'), givenMessage, givenMessage);
const givenRoutes = routes([{
binding: givenBinding,
invoke: (message) => message
}]);
const {request, invoke} = givenRoutes.resolve('GET', '/api/path-1?valueFromQuery=query-1');
expect(request).to.deep.equal({
valueFromPath: 'path-1',
valueFromQuery: 'query-1'
});
expect(invoke).to.exist;
expect(await invoke(request)).to.deep.equal(request);
});
it('should extract complex request arguments', () => {
const givenRoutes = routesFrom(`
service TestRoutes {
rpc Get (Empty) returns (Empty) {
option (google.api.http) = {
get: "/api/{valueFromPath}"
};
}
}
const givenMessage = messageBuilder().build();
message Empty {}
`);
const givenBinding = http(get('/api/{valueFromPath}'), givenMessage, givenMessage);
const {request, route} = givenRoutes.resolve('GET', '/api/path-1?test.arr=arr-1&test.arr=arr-2&test.bool=true&num=10');
const givenRoutes = routes([{
binding: givenBinding,
invoke: (message) => message
}]);
expect(route.method.name).to.equal('Get');
const {request, invoke} = givenRoutes.resolve('GET', '/api/path-1?test.arr=arr-1&test.arr=arr-2&test.bool=true&num=10');
expect(invoke).to.exist;
expect(request).to.deep.equal({

@@ -58,20 +73,2 @@ test: {

});
function routesFrom(source) {
const parsed = protobufjs.parse(`
syntax = "proto3";
package test;
import "google/api/http.proto";
${source}
`);
const ns = parsed.root.nested.test;
return routes(Object.values(ns.nested).filter((type) => type instanceof protobufjs.Service).map((service) => ({
service
})), messageTypes(parsed.root));
}
});

@@ -1,5 +0,2 @@

const {create} = require('@wix/proto-packages');
const startServer = require('./server');
const defaultContextDir = require('find-root')(process.argv[1]);
const messageTypes = require('./message-types');

@@ -12,52 +9,23 @@ module.exports = {

return {
withContextDir(contextDir) {
withBindings(bindings) {
return serverBuilder({
...context,
contextDir
bindings
});
},
withExtraProtoPackage(extraPackageDir) {
withBindingsSource(bindingsSource) {
return serverBuilder({
...context,
extraPackageDir
bindingsSource
});
},
withService(serviceType, implementation) {
const services = {...(context.services || {})};
services[serviceType] = implementation;
context.services = services;
return serverBuilder({
...context
});
},
async start(options) {
const protoContext = create({
contextDir: context.contextDir || defaultContextDir,
sourceRoots: ['proto'],
extraPackages: [context.extraPackageDir]
});
const sourcedBindings = context.bindingsSource ? await context.bindingsSource.bindings() : [];
const dynamicBindings = context.bindings;
const bindings = [...sourcedBindings, ...dynamicBindings];
const loadedContext = await protoContext.loadedContext();
const services = Object.keys(context.services).map((serviceName) => {
const service = loadedContext.lookupService(serviceName);
const bindings = {};
Object.values(service.methods).forEach((method) => {
bindings[method.name] = context.services[serviceName][toSmallCap(method.name)];
});
return {
service,
bindings
};
});
return startServer({
...options,
services,
messageTypes: messageTypes(loadedContext)
bindings
});

@@ -67,5 +35,1 @@ }

}
function toSmallCap(value) {
return value.charAt(0).toLowerCase() + value.slice(1);
}

@@ -5,25 +5,25 @@ const http = require('http');

module.exports = function start(options) {
const methodRoutes = routes(options.services, options.messageTypes);
const methodRoutes = routes(options.bindings);
const server = http.createServer(async(req, res) => {
try {
const {route, request} = methodRoutes.resolve(req.method, req.url);
const {invoke, request} = methodRoutes.resolve(req.method, req.url);
if (!route) {
if (!invoke) {
res.statusCode = 404;
}
} else {
const contentType = req.headers['content-type'];
const contentType = req.headers['content-type'];
if (contentType) {
await new Promise((resolve, reject) =>
req.on('data', async(data) => {
try {
resolve(await execute(route, res, request, JSON.parse(data)));
} catch(e) {
reject(e);
}
}));
} else {
await execute(route, res, request);
if (contentType) {
await new Promise((resolve, reject) =>
req.on('data', async(data) => {
try {
resolve(await execute(invoke, res, request, JSON.parse(data)));
} catch(e) {
reject(e);
}
}));
} else {
await execute(invoke, res, request);
}
}

@@ -52,11 +52,7 @@ } catch(e) {

async function execute(route, res, request, body = {}) {
const requestMessage = route.requestMessage;
async function execute(invoke, res, request, body = {}) {
const result = await invoke([request, body]);
const message = requestMessage.fromValue([request, body]);
const result = await route.implementation(message);
res.setHeader('Content-Type', 'application/json');
res.write(JSON.stringify(result));
}
{
"name": "@wix/be-server",
"version": "1.0.5",
"version": "1.0.6",
"author": "Mantas Indrašius <mantasi@wix.com>",

@@ -5,0 +5,0 @@ "publishConfig": {

@@ -5,2 +5,4 @@ const beServer = require('..');

const path = require('path');
const {httpBinding, messageBuilder, wellKnownTypes} = require('@wix/be-http-binding');
const {http, get} = httpBinding;

@@ -13,11 +15,20 @@ describe('HTTP server', function() {

const echoMessage = messageBuilder().field('message', wellKnownTypes.string, 1).build();
before(async() => {
server = await beServer.builder()
.withContextDir(path.resolve(__dirname, '..'))
.withExtraProtoPackage(path.resolve(__dirname, 'proto'))
.withService('test.EchoService', {
echo: (message) => message,
postEcho: (message) => message,
typesEcho: (message) => message,
})
.withBindingsSource(beServer.fromProtoModules({
contextDir: path.resolve(__dirname, '..'),
extraPackages: [path.resolve(__dirname, 'proto')]
}, {
'test.EchoService': {
echo: (message) => message,
postEcho: (message) => message,
typesEcho: (message) => message,
}
}))
.withBindings([{
binding: http(get('/api/dynamic-echo'), echoMessage, echoMessage),
invoke: (message) => message
}])
.start({ port: 9901 });

@@ -28,3 +39,3 @@ });

it('should call to an exposed endpoint', async() => {
it('should call an exposed endpoint', async() => {
const response = await fetch('http://localhost:9901/api/echo?message=Hello');

@@ -41,2 +52,14 @@

it('should call a dynamic endpoint', async() => {
const response = await fetch('http://localhost:9901/api/dynamic-echo?message=Hello');
expect(response.status).to.equal(200);
const body = await response.json();
expect(body).to.deep.equal({
message: 'Hello'
});
});
it('should post', async() => {

@@ -43,0 +66,0 @@ const response = await fetch('http://localhost:9901/api/echo', {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc