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 ‘<?php` tag 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 |