mirror of
https://github.com/openwrt/luci.git
synced 2026-04-15 10:51:51 +00:00
luci-base: implement http header plugins
This implements the injection of custom http headers via the new plugin architecture. Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
@@ -13,6 +13,12 @@ import {
|
||||
stdin, stdout, mkstemp
|
||||
} from 'fs';
|
||||
|
||||
import {
|
||||
openlog, syslog, closelog, LOG_NOTICE, LOG_LOCAL0
|
||||
} from 'log';
|
||||
|
||||
import { run_plugins } from 'luciplugins';
|
||||
|
||||
// luci.http module scope
|
||||
export let HTTP_MAX_CONTENT = 1024*100; // 100 kB maximum content size
|
||||
|
||||
@@ -504,6 +510,37 @@ const Class = {
|
||||
if (!this.headers?.['x-content-type-options'])
|
||||
this.header('X-Content-Type-Options', 'nosniff');
|
||||
|
||||
/* http header plugins */
|
||||
let log_class = 'http.uc';
|
||||
openlog(log_class);
|
||||
for (let plugin_id, p_output in run_plugins('/luci/plugins/http/headers', 'http_headers_enabled')) {
|
||||
|
||||
/* header plugins shall return e.g.: ['X-Header', 'foo'] */
|
||||
if (type(p_output) !== 'array' || length(p_output) !== 2)
|
||||
continue;
|
||||
|
||||
if (type(p_output[0]) !== 'string' || type(p_output[1]) !== 'string')
|
||||
continue;
|
||||
|
||||
if (!match(p_output[0], /^[A-Za-z0-9-]+$/)) {
|
||||
syslog(LOG_NOTICE|LOG_LOCAL0,
|
||||
sprintf("Invalid header name from plugin %s output: %s", plugin_id, p_output[0]));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* header plugin values shall not contain line-feeds */
|
||||
if (match(p_output[1], /[\r\n]/)) {
|
||||
syslog(LOG_NOTICE|LOG_LOCAL0,
|
||||
sprintf("\\r and/or \\n in plugin %s output", plugin_id));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!this.headers?.[p_output[0]])
|
||||
this.header(p_output[0], p_output[1]);
|
||||
|
||||
}
|
||||
closelog();
|
||||
|
||||
this.output('Status: ');
|
||||
this.output(this.status_code);
|
||||
this.output(' ');
|
||||
|
||||
49
modules/luci-base/ucode/luciplugins.uc
Normal file
49
modules/luci-base/ucode/luciplugins.uc
Normal file
@@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import {
|
||||
lsdir
|
||||
} from 'fs';
|
||||
|
||||
import {
|
||||
syslog, LOG_NOTICE, LOG_LOCAL0
|
||||
} from 'log';
|
||||
|
||||
import { cursor } from 'uci';
|
||||
|
||||
|
||||
/* generic plugin handler */
|
||||
export function run_plugins(plugin_class_path, plugin_class_enable) {
|
||||
let uci = cursor();
|
||||
const require_path = replace(plugin_class_path, '/', '.');
|
||||
|
||||
if (uci.get('luci_plugins', 'global', 'enabled') == 1 &&
|
||||
uci.get('luci_plugins', 'global', plugin_class_enable) == 1) {
|
||||
const PLUGINS_PATH = '/usr/share/ucode' + plugin_class_path;
|
||||
const results = {};
|
||||
|
||||
for (let fn in lsdir(PLUGINS_PATH)) {
|
||||
const plugin_id = replace(fn, /.uc$/, '');
|
||||
/* plugins shall have a <32_char_UUID_no_hyphens>.uc filename */
|
||||
if (!match(plugin_id, /^[a-f0-9]+$/) || length(plugin_id) !== 32) {
|
||||
syslog(LOG_NOTICE|LOG_LOCAL0,
|
||||
sprintf("Invalid plugin name: %s", plugin_id));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uci.get('luci_plugins', plugin_id, 'enabled')) {
|
||||
const mod = require(require_path + `.${plugin_id}`);
|
||||
if (type(mod) === 'function') {
|
||||
try {
|
||||
results[plugin_id] = mod(plugin_id);
|
||||
} catch (e) {
|
||||
syslog(LOG_NOTICE|LOG_LOCAL0,
|
||||
sprintf("Could not execute plugin %s: %s",
|
||||
join('/', [PLUGINS_PATH, plugin_id]), e));
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user