Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class Application extends events.EventEmitter {

createSandbox() {
const introspection = async () => [...this.api.keys()];
const application = { security, api: { introspection } };
const context = Object.freeze({});
const application = { security, api: { introspection }, context };
for (const name of this.namespaces) application[name] = this[name];
const sandbox = { console: this.logger, application, Buffer, api };
sandbox.global = sandbox;
Expand All @@ -51,7 +52,7 @@ class Application extends events.EventEmitter {
const data = await fsp.readFile(fileName, 'utf8');
const code = data.startsWith('({') ? data :
`({ access: 'logged', method: ${data.trim().slice(0, -1)} });`;
const src = `'use strict';\ncontext => ${code}`;
const src = `'use strict';\n${code}`;
const options = { filename: fileName, lineOffset: -1 };
try {
return new vm.Script(src, options);
Expand All @@ -61,9 +62,10 @@ class Application extends events.EventEmitter {
}
}

runScript(methodName, sandbox = this.sandbox) {
runScript(methodName, session) {
const { sandbox } = (session || this);
const script = this.api.get(methodName);
if (!script) throw new Error('Not found');
if (!script) return null;
return script.runInContext(sandbox, SCRIPT_OPTIONS);
}

Expand Down
5 changes: 2 additions & 3 deletions lib/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ module.exports = application => {
const fillPool = () => {
const need = SANDBOX_POOL - pool.length;
for (let i = 0; i < need; i++) {
const sandbox = application.createSandbox();
pool.push(sandbox);
pool.push(application.createSandbox());
}
};

Expand Down Expand Up @@ -90,7 +89,7 @@ module.exports = application => {
this.token = token;
this.sandbox = sandbox;
this.data = contextData;
this.context = new Proxy(contextData, contextHandler);
sandbox.context = new Proxy(contextData, contextHandler);
}
}

Expand Down
52 changes: 24 additions & 28 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ class Client {
}

static() {
const { url } = this.req;
const { req: { url }, res, application } = this;
const filePath = url === '/' ? '/index.html' : url;
const fileExt = path.extname(filePath).substring(1);
const mimeType = MIME_TYPES[fileExt] || MIME_TYPES.html;
this.res.writeHead(200, { 'Content-Type': mimeType });
const data = this.application.cache.get(filePath);
if (data) this.res.end(data);
res.writeHead(200, { 'Content-Type': mimeType });
const data = application.cache.get(filePath);
if (data) res.end(data);
else this.error(404);
}

Expand All @@ -81,44 +81,40 @@ class Client {
res.end(result);
}

async execute(method, args) {
const { application } = this;
async rpc(method, args) {
const { application, res, connection } = this;
const { semaphore } = application.server;
await semaphore.enter();
try {
await semaphore.enter();
} catch {
this.error(504);
return;
}
try {
const session = await application.auth.restore(this);
const sandbox = session ? session.sandbox : undefined;
const context = session ? session.context : {};
const exp = application.runScript(method, sandbox);
const proc = exp(context);
const proc = application.runScript(method, session);
if (!proc) {
this.error(404);
return;
}
if (!session && proc.access !== 'public') {
semaphore.leave();
throw new Error(`Forbidden: /api/${method}`);
this.error(403, new Error(`Forbidden: /api/${method}`));
return;
}
const result = await proc.method(args);
if (!session && proc.access === 'public') {
const session = application.auth.start(this, result.userId);
result.token = session.token;
}
return JSON.stringify(result);
const data = JSON.stringify(result);
if (connection) connection.send(data);
else res.end(data);
} catch (err) {
this.error(500, err);
} finally {
semaphore.leave();
}
}

async rpc(method, args) {
const { res, connection } = this;
try {
const result = await this.execute(method, args);
if (connection) connection.send(result);
else res.end(result);
} catch (err) {
if (err.message === 'Not found') this.error(404);
else if (err.message === 'Semaphore timeout') this.error(504);
else if (err.message.startsWith('Forbidden:')) this.error(403, err);
else this.error(500, err);
}
}
}

const listener = application => (req, res) => {
Expand Down