Module: TRMNLP::TransformBackend::Wrapper
- Defined in:
- lib/trmnlp/transform_backend/wrapper.rb
Overview
Code wrappers shared by Subprocess and Http backends. Each method
emits the canonical dispatch harness — read stdin → run user code
→ find run/transform/result/passthrough → serialize output — and
delegates the final write to a language-appropriate output_sink
snippet supplied by the caller. Subprocess writes to a tempfile
path, Http writes to FD 3 for the production daemon to capture.
Mirrors the hosted serverless runtime's code-wrapping behavior,
parameterized on the per-backend output sink. PHP additionally
carries a leading <?php tag the file-based Subprocess path
needs; the daemon tolerates it, so parity holds.
NOTE: output_sink is spliced verbatim into the generated script as
executable code. It MUST be trmnlp-generated (see Subprocess#sink_for
and Http#sink_for) and never derived from user input or config — an
attacker-influenced sink is arbitrary code execution in the transform
process. Only code is untrusted; the sink is part of the harness.
Class Method Summary collapse
- .for(language, code, output_sink) ⇒ Object
-
.node(code, output_sink) ⇒ Object
NOTE: node also accepts
function transform(input)for production parity. -
.php(code, output_sink) ⇒ Object
NOTE: strips a leading
<?phptag from user code so plugin authors can write the file as a standalone .php script. - .python(code, output_sink) ⇒ Object
- .ruby(code, output_sink) ⇒ Object
Class Method Details
.for(language, code, output_sink) ⇒ Object
105 106 107 108 109 110 111 112 |
# File 'lib/trmnlp/transform_backend/wrapper.rb', line 105 def for(language, code, output_sink) case language.to_s when 'python' then python(code, output_sink) when 'ruby' then ruby(code, output_sink) when 'node' then node(code, output_sink) when 'php' then php(code, output_sink) end end |
.node(code, output_sink) ⇒ Object
NOTE: node also accepts function transform(input) for
production parity. Plugins authored against the hosted service
using transform would otherwise silently pass input through.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/trmnlp/transform_backend/wrapper.rb', line 63 def node(code, output_sink) <<~JS const input = JSON.parse(require('fs').readFileSync(0, 'utf8')); #{code} let output; if (typeof run === "function") { output = run(input); } else if (typeof transform === "function") { output = transform(input); } else if (typeof result !== "undefined") { output = result; } else { output = input; } #{output_sink} JS end |
.php(code, output_sink) ⇒ Object
NOTE: strips a leading <?php tag from user code so plugin
authors can write the file as a standalone .php script. The
hosted service does the same.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/trmnlp/transform_backend/wrapper.rb', line 86 def php(code, output_sink) cleaned = code.sub(/\A\s*<\?php\s*/, '') <<~PHP <?php $input = json_decode(file_get_contents('php://stdin'), true); #{cleaned} if (function_exists('run')) { $output = run($input); } elseif (isset($result)) { $output = $result; } else { $output = $input; } #{output_sink} PHP end |
.python(code, output_sink) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/trmnlp/transform_backend/wrapper.rb', line 25 def python(code, output_sink) <<~PYTHON import sys, json, os input = json.loads(sys.stdin.read()) #{code} if callable(locals().get('run', None)): output = run(input) elif 'result' in dir(): output = result else: output = input #{output_sink} PYTHON end |
.ruby(code, output_sink) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/trmnlp/transform_backend/wrapper.rb', line 42 def ruby(code, output_sink) <<~RUBY require 'json' input = JSON.parse($stdin.read) #{code} output = if defined?(run) == 'method' run(input) elsif defined?(result) result else input end #{output_sink} RUBY end |