luci-base: fix luci.http.close()
Ensure that `http.write()` or template rendering operations after a call to `http.close()` do not produce additional output. This is required for certain legacy Lua apps which invoke write and close operations in the middle of a server side cbi rendering process. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
f83e4a6c36
commit
e7afd0d327
3 changed files with 17 additions and 7 deletions
|
@ -775,7 +775,8 @@ function run_action(request_path, lang, tree, resolved, action) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'call':
|
case 'call':
|
||||||
http.write(render(() => {
|
http.write_headers();
|
||||||
|
http.output(render(() => {
|
||||||
runtime.call(action.module, action.function,
|
runtime.call(action.module, action.function,
|
||||||
...(action.parameters ?? []),
|
...(action.parameters ?? []),
|
||||||
...resolved.ctx.request_args
|
...resolved.ctx.request_args
|
||||||
|
@ -789,7 +790,8 @@ function run_action(request_path, lang, tree, resolved, action) {
|
||||||
assert(type(mod[action.function]) == 'function',
|
assert(type(mod[action.function]) == 'function',
|
||||||
`Module '${action.module}' does not export function '${action.function}'`);
|
`Module '${action.module}' does not export function '${action.function}'`);
|
||||||
|
|
||||||
http.write(render(() => {
|
http.write_headers();
|
||||||
|
http.output(render(() => {
|
||||||
call(mod[action.function], mod, runtime.env,
|
call(mod[action.function], mod, runtime.env,
|
||||||
...(action.parameters ?? []),
|
...(action.parameters ?? []),
|
||||||
...resolved.ctx.request_args
|
...resolved.ctx.request_args
|
||||||
|
@ -798,7 +800,8 @@ function run_action(request_path, lang, tree, resolved, action) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'cbi':
|
case 'cbi':
|
||||||
http.write(render(() => {
|
http.write_headers();
|
||||||
|
http.output(render(() => {
|
||||||
runtime.call('luci.dispatcher', 'invoke_cbi_action',
|
runtime.call('luci.dispatcher', 'invoke_cbi_action',
|
||||||
action.path, null,
|
action.path, null,
|
||||||
...resolved.ctx.request_args
|
...resolved.ctx.request_args
|
||||||
|
@ -807,7 +810,8 @@ function run_action(request_path, lang, tree, resolved, action) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'form':
|
case 'form':
|
||||||
http.write(render(() => {
|
http.write_headers();
|
||||||
|
http.output(render(() => {
|
||||||
runtime.call('luci.dispatcher', 'invoke_form_action',
|
runtime.call('luci.dispatcher', 'invoke_form_action',
|
||||||
action.path,
|
action.path,
|
||||||
...resolved.ctx.request_args
|
...resolved.ctx.request_args
|
||||||
|
|
|
@ -524,7 +524,7 @@ const Class = {
|
||||||
|
|
||||||
// If the content chunk is nil this function will automatically invoke close.
|
// If the content chunk is nil this function will automatically invoke close.
|
||||||
write: function(content) {
|
write: function(content) {
|
||||||
if (content != null) {
|
if (content != null && !this.closed) {
|
||||||
this.write_headers();
|
this.write_headers();
|
||||||
this.output(content);
|
this.output(content);
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,10 @@ const Class = {
|
||||||
let bridge = this.env.dispatcher.load_luabridge(optional);
|
let bridge = this.env.dispatcher.load_luabridge(optional);
|
||||||
|
|
||||||
if (bridge) {
|
if (bridge) {
|
||||||
|
let http = this.env.http;
|
||||||
|
|
||||||
this.L = bridge.create();
|
this.L = bridge.create();
|
||||||
this.L.set('L', proto({ write: print }, this.env));
|
this.L.set('L', proto({ write: (...args) => http.closed || print(...args) }, this.env));
|
||||||
this.L.invoke('require', 'luci.ucodebridge');
|
this.L.invoke('require', 'luci.ucodebridge');
|
||||||
|
|
||||||
this.env.lua_active = true;
|
this.env.lua_active = true;
|
||||||
|
@ -61,7 +63,11 @@ const Class = {
|
||||||
|
|
||||||
render_ucode: function(path, scope) {
|
render_ucode: function(path, scope) {
|
||||||
let tmplfunc = loadfile(path, { raw_mode: false });
|
let tmplfunc = loadfile(path, { raw_mode: false });
|
||||||
call(tmplfunc, null, scope ?? {});
|
|
||||||
|
if (this.env.http.closed)
|
||||||
|
render(call, tmplfunc, null, scope ?? {});
|
||||||
|
else
|
||||||
|
call(tmplfunc, null, scope ?? {});
|
||||||
},
|
},
|
||||||
|
|
||||||
render_lua: function(path, scope) {
|
render_lua: function(path, scope) {
|
||||||
|
|
Loading…
Reference in a new issue