Files: 464b2ebf04198512fa3e2bc5a3ab92e8e799ab93 / index.js
3177 bytesRaw
1 | /* ssb-exec |
2 | * © 2019 cel @f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519 |
3 | * |
4 | * Usage of the works is permitted provided that this instrument is |
5 | * retained with the works, so that any entity that uses the works is |
6 | * notified of this instrument. |
7 | * |
8 | * DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY. |
9 | */ |
10 | |
11 | var url = require('url') |
12 | var path = require('path') |
13 | var fs = require('fs') |
14 | |
15 | var blobsDir = path.resolve(__dirname, '../../blobs') |
16 | |
17 | exports.requireBlob = function (id) { |
18 | var m = /^\&([0-9a-zA-Z\/+=]{44})\.(sha256)$/.exec(id) |
19 | if (!m) throw new Error('invalid blob id: ' + id) |
20 | var hex = new Buffer(m[1], 'base64').toString('hex') |
21 | return require(path.join(blobsDir, m[2], hex.substr(0, 2), hex.substr(2))) |
22 | } |
23 | |
24 | exports.name = 'exec' |
25 | exports.version = '1.0.0' |
26 | exports.manifest = { |
27 | } |
28 | exports.init = function (sbot, config) { |
29 | if (!sbot.ws || !sbot.ws.use) return console.trace('missing ssb-ws') |
30 | var prefix = '/exec' |
31 | var dir = path.join(config.path, 'exec') |
32 | blobsDir = path.join(config.path, 'blobs') |
33 | var mtimes = {} |
34 | console.log('[exec] init. dir:', dir, 'prefix:', prefix) |
35 | |
36 | function getModule(resolved, tried, cb) { |
37 | try { |
38 | var module = require(resolved) |
39 | return cb(null, module) |
40 | } catch(e) { |
41 | if (tried || !e || !(e.code === 'ENOENT' || e.code === 'MODULE_NOT_FOUND')) return cb(e) |
42 | var m = /(sha256)\/([0-9a-f]{2})\/([0-9a-f]{62})/.exec(e.path || e.message) |
43 | if (!m) return cb(e) |
44 | var blobId = '&' + new Buffer(m[2] + m[3], 'hex').toString('base64') + '.' + m[1] |
45 | if (!sbot.blobs) return cb(new Error('Missing ssb-blobs plugin')) |
46 | if (typeof sbot.blobs.want !== 'function') return cb(new Error('missing blobs.want method')) |
47 | return sbot.blobs.want(blobId, function (err, has) { |
48 | if (err) return cb(new Error('Unable to get blob: ' + (err.stack || err))) |
49 | if (!has) return cb(new Error('Unable to get blob')) |
50 | getModule(resolved, true, cb) |
51 | }) |
52 | } |
53 | } |
54 | |
55 | sbot.ws.use(function (req, res, next) { |
56 | if (prefix !== req.url.substr(0, prefix.length)) return next() |
57 | if (prefix === req.url) { |
58 | res.writeHead(302, {Location: path.basename(prefix) + '/'}) |
59 | return res.end() |
60 | } |
61 | try { |
62 | req.uri = url.parse(req.url.substr(prefix.length), true) |
63 | var file = path.normalize(path.join(dir, req.uri.pathname)) |
64 | if (dir !== file.substr(0, dir.length)) { |
65 | res.writeHead(403) |
66 | return res.end('Forbidden') |
67 | } |
68 | var resolved = require.resolve(file) |
69 | var prevMtime = mtimes[resolved] |
70 | var mtime = fs.statSync(resolved).mtime.getTime() |
71 | if (mtime !== prevMtime) { |
72 | delete require.cache[resolved] |
73 | mtimes[resolved] = mtime |
74 | } |
75 | getModule(resolved, false, gotModule) |
76 | } catch(e) { |
77 | return gotError(e) |
78 | } |
79 | |
80 | function gotError(err) { |
81 | try { |
82 | res.writeHead(err.code === 'ENOENT' || err.code === 'MODULE_NOT_FOUND' ? 404 : 500) |
83 | } finally { |
84 | res.end(err.stack || err) |
85 | } |
86 | } |
87 | |
88 | function gotModule(err, module) { |
89 | if (err) return gotError(err) |
90 | try { |
91 | module(req, res, sbot, config) |
92 | } catch(e) { |
93 | gotError(e) |
94 | } |
95 | } |
96 | }) |
97 | } |
98 |
Built with git-ssb-web