diff --git a/src/backend/internal/nginx.js b/src/backend/internal/nginx.js index 1e992992..89c43a54 100644 --- a/src/backend/internal/nginx.js +++ b/src/backend/internal/nginx.js @@ -130,6 +130,35 @@ const internalNginx = { return '/data/nginx/' + host_type + '/' + host_id + '.conf'; }, + /** + * Generates custom locations + * @param {Object} host + * @returns {Promise} + */ + renderLocations: (host) => { + return new Promise((resolve, reject) => { + let template; + + try { + template = fs.readFileSync(__dirname + '/../templates/_location.conf', {encoding: 'utf8'}); + } catch (err) { + reject(new error.ConfigurationError(err.message)); + return; + } + + let renderer = new Liquid(); + let renderedLocations = ''; + + const locationRendering = async () => { + for (let i = 0; i < host.locations.length; i++) { + renderedLocations += await renderer.parseAndRender(template, host.locations[i]); + } + } + + locationRendering().then(() => resolve(renderedLocations)); + }); + }, + /** * @param {String} host_type * @param {Object} host @@ -157,6 +186,9 @@ const internalNginx = { return; } + let locationsPromise; + let origLocations; + // Manipulate the data a bit before sending it to the template if (host_type !== 'default') { host.use_default_location = true; @@ -165,24 +197,38 @@ const internalNginx = { } } - renderEngine - .parseAndRender(template, host) - .then(config_text => { - fs.writeFileSync(filename, config_text, {encoding: 'utf8'}); - - if (debug_mode) { - logger.success('Wrote config:', filename, config_text); - } - - resolve(true); - }) - .catch(err => { - if (debug_mode) { - logger.warn('Could not write ' + filename + ':', err.message); - } - - reject(new error.ConfigurationError(err.message)); + if (host.locations) { + origLocations = [].concat(host.locations); + locationsPromise = internalNginx.renderLocations(host).then((renderedLocations) => { + host.locations = renderedLocations; }); + } else { + locationsPromise = Promise.resolve(); + } + + locationsPromise.then(() => { + renderEngine + .parseAndRender(template, host) + .then(config_text => { + fs.writeFileSync(filename, config_text, {encoding: 'utf8'}); + + if (debug_mode) { + logger.success('Wrote config:', filename, config_text); + } + + // Restore locations array + host.locations = origLocations; + + resolve(true); + }) + .catch(err => { + if (debug_mode) { + logger.warn('Could not write ' + filename + ':', err.message); + } + + reject(new error.ConfigurationError(err.message)); + }); + }); }); }, diff --git a/src/backend/migrations/20190215115310_customlocations.js b/src/backend/migrations/20190215115310_customlocations.js new file mode 100644 index 00000000..5b55dd5e --- /dev/null +++ b/src/backend/migrations/20190215115310_customlocations.js @@ -0,0 +1,37 @@ +'use strict'; + +const migrate_name = 'custom_locations'; +const logger = require('../logger').migrate; + +/** + * Migrate + * Extends proxy_host table with locations field + * + * @see http://knexjs.org/#Schema + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.up = function (knex/*, Promise*/) { + logger.info('[' + migrate_name + '] Migrating Up...'); + + return knex.schema.table('proxy_host', function (proxy_host) { + proxy_host.json('locations'); + }) + .then(() => { + logger.info('[' + migrate_name + '] proxy_host Table altered'); + }) +}; + +/** + * Undo Migrate + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.down = function (knex, Promise) { + logger.warn('[' + migrate_name + '] You can\'t migrate down this one.'); + return Promise.resolve(true); +}; diff --git a/src/backend/models/proxy_host.js b/src/backend/models/proxy_host.js index a1217236..faa5d068 100644 --- a/src/backend/models/proxy_host.js +++ b/src/backend/models/proxy_host.js @@ -47,7 +47,7 @@ class ProxyHost extends Model { } static get jsonAttributes () { - return ['domain_names', 'meta']; + return ['domain_names', 'meta', 'locations']; } static get relationMappings () { diff --git a/src/backend/schema/endpoints/proxy-hosts.json b/src/backend/schema/endpoints/proxy-hosts.json index df7cb119..cd98355f 100644 --- a/src/backend/schema/endpoints/proxy-hosts.json +++ b/src/backend/schema/endpoints/proxy-hosts.json @@ -69,6 +69,41 @@ }, "meta": { "type": "object" + }, + "locations": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "required": [ + "forward_scheme", + "forward_host", + "forward_port", + "path" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": ["integer", "null"] + }, + "path": { + "type": "string", + "minLength": 1 + }, + "forward_scheme": { + "$ref": "#/definitions/forward_scheme" + }, + "forward_host": { + "$ref": "#/definitions/forward_host" + }, + "forward_port": { + "$ref": "#/definitions/forward_port" + }, + "advanced_config": { + "type": "string" + } + } + } } }, "properties": { @@ -128,6 +163,9 @@ }, "meta": { "$ref": "#/definitions/meta" + }, + "locations": { + "$ref": "#/definitions/locations" } }, "links": [ @@ -215,6 +253,9 @@ }, "meta": { "$ref": "#/definitions/meta" + }, + "locations": { + "$ref": "#/definitions/locations" } } }, @@ -285,6 +326,9 @@ }, "meta": { "$ref": "#/definitions/meta" + }, + "locations": { + "$ref": "#/definitions/locations" } } }, diff --git a/src/backend/templates/_location.conf b/src/backend/templates/_location.conf new file mode 100644 index 00000000..d31befe8 --- /dev/null +++ b/src/backend/templates/_location.conf @@ -0,0 +1,8 @@ + location {{ path }} { + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Scheme $scheme; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}; + {{ advanced_config }} + } \ No newline at end of file diff --git a/src/backend/templates/proxy_host.conf b/src/backend/templates/proxy_host.conf index 95f850a9..fc58a43b 100644 --- a/src/backend/templates/proxy_host.conf +++ b/src/backend/templates/proxy_host.conf @@ -16,7 +16,10 @@ server { {{ advanced_config }} +{{ locations }} + {% if use_default_location %} + location / { {%- if access_list_id > 0 -%} # Access List diff --git a/src/frontend/js/app/nginx/proxy/form.ejs b/src/frontend/js/app/nginx/proxy/form.ejs index ef9b95b4..3f940f12 100644 --- a/src/frontend/js/app/nginx/proxy/form.ejs +++ b/src/frontend/js/app/nginx/proxy/form.ejs @@ -7,10 +7,22 @@