mirror of
https://github.com/mjl-/mox.git
synced 2025-07-12 23:34:38 +03:00
improve http request handling for internal services and multiple domains
per listener, you could enable the admin/account/webmail/webapi handlers. but that would serve those services on their configured paths (/admin/, /, /webmail/, /webapi/) on all domains mox would be webserving, including any non-mail domains. so your www.example/admin/ would be serving the admin web interface, with no way to disabled that. with this change, the admin interface is only served on requests to (based on Host header): - ip addresses - the listener host name (explicitly configured in the listener, with fallback to global hostname) - "localhost" (for ssh tunnel/forwarding scenario's) the account/webmail/webapi interfaces are served on the same domains as the admin interface, and additionally: - the client settings domains, as optionally configured in each Domain in domains.conf. typically "mail.<yourdomain>". this means the internal services are no longer served on other domains configured in the webserver, e.g. www.example.org/admin/ will not be handled specially. the order of evaluation of routes/services is also changed: before this change, the internal handlers would always be evaluated first. with this change, only the system handlers for MTA-STS/autoconfig/ACME-validation will be evaluated first. then the webserver handlers. and finally the internal services (admin/account/webmail/webapi). this allows an admin to configure overrides for some of the domains (per hostname-matching rules explained above) that would normally serve these services. webserver handlers can now be configured that pass the request to an internal service: in addition to the existing static/redirect/forward config options, there is now an "internal" config option, naming the service (admin/account/webmail/webapi) for handling the request. this allows enabling the internal services on custom domains. for issue #160 by TragicLifeHu, thanks for reporting!
This commit is contained in:
@ -4537,6 +4537,10 @@ const webserver = async () => {
|
||||
root: HTMLElement
|
||||
get: () => api.WebForward
|
||||
}
|
||||
type WebInternalView = {
|
||||
root: HTMLElement
|
||||
get: () => api.WebInternal
|
||||
}
|
||||
|
||||
// Make a handler row. This is more complicated, since it can be one of the three
|
||||
// types (static, redirect, forward), and can change between those types.
|
||||
@ -4546,6 +4550,7 @@ const webserver = async () => {
|
||||
let staticView: WebStaticView | null = null
|
||||
let redirectView: WebRedirectView | null = null
|
||||
let forwardView: WebForwardView | null = null
|
||||
let internalView: WebInternalView | null = null
|
||||
|
||||
let moveButtons: HTMLElement
|
||||
|
||||
@ -4602,6 +4607,7 @@ const webserver = async () => {
|
||||
dom.option('Static', attr.selected('')),
|
||||
dom.option('Redirect'),
|
||||
dom.option('Forward'),
|
||||
dom.option('Internal'),
|
||||
function change(e: MouseEvent) {
|
||||
makeType((e.target! as HTMLSelectElement).value)
|
||||
},
|
||||
@ -4671,6 +4677,7 @@ const webserver = async () => {
|
||||
dom.option('Static'),
|
||||
dom.option('Redirect', attr.selected('')),
|
||||
dom.option('Forward'),
|
||||
dom.option('Internal'),
|
||||
function change(e: MouseEvent) {
|
||||
makeType((e.target! as HTMLSelectElement).value)
|
||||
},
|
||||
@ -4735,6 +4742,7 @@ const webserver = async () => {
|
||||
dom.option('Static', ),
|
||||
dom.option('Redirect'),
|
||||
dom.option('Forward', attr.selected('')),
|
||||
dom.option('Internal'),
|
||||
function change(e: MouseEvent) {
|
||||
makeType((e.target! as HTMLSelectElement).value)
|
||||
},
|
||||
@ -4755,6 +4763,60 @@ const webserver = async () => {
|
||||
return view
|
||||
}
|
||||
|
||||
const makeWebInternal = (wi: api.WebInternal) => {
|
||||
let view: WebInternalView
|
||||
|
||||
let basePath: HTMLInputElement
|
||||
let service: HTMLSelectElement
|
||||
|
||||
const get = (): api.WebInternal => {
|
||||
return {
|
||||
BasePath: basePath.value,
|
||||
Service: service.value,
|
||||
}
|
||||
}
|
||||
const root = dom.table(
|
||||
dom.tr(
|
||||
dom.td('Type'),
|
||||
dom.td(
|
||||
'Base path',
|
||||
attr.title('Path to use as root of internal service, e.g. /webmail/.'),
|
||||
),
|
||||
dom.td(
|
||||
'Service',
|
||||
),
|
||||
),
|
||||
dom.tr(
|
||||
dom.td(
|
||||
dom.select(
|
||||
attr.required(''),
|
||||
dom.option('Static', ),
|
||||
dom.option('Redirect'),
|
||||
dom.option('Forward'),
|
||||
dom.option('Internal', attr.selected('')),
|
||||
function change(e: MouseEvent) {
|
||||
makeType((e.target! as HTMLSelectElement).value)
|
||||
},
|
||||
),
|
||||
),
|
||||
dom.td(
|
||||
basePath=dom.input(attr.value(wi.BasePath), attr.required(''), attr.placeholder('/.../')),
|
||||
),
|
||||
dom.td(
|
||||
service=dom.select(
|
||||
dom.option('Admin', attr.value('admin')),
|
||||
dom.option('Account', attr.value('account')),
|
||||
dom.option('Webmail', attr.value('webmail')),
|
||||
dom.option('Webapi', attr.value('webapi')),
|
||||
attr.value(wi.Service),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
view = {root: root, get: get}
|
||||
return view
|
||||
}
|
||||
|
||||
let logName: HTMLInputElement
|
||||
let domain: HTMLInputElement
|
||||
let pathRegexp: HTMLInputElement
|
||||
@ -4794,6 +4856,12 @@ const webserver = async () => {
|
||||
ResponseHeaders: {},
|
||||
})
|
||||
detailsRoot(forwardView.root)
|
||||
} else if (s === 'Internal') {
|
||||
internalView = makeWebInternal(wh.WebInternal || {
|
||||
BasePath: '',
|
||||
Service: 'admin',
|
||||
})
|
||||
detailsRoot(internalView.root)
|
||||
} else {
|
||||
throw new Error('unknown handler type')
|
||||
}
|
||||
@ -4901,6 +4969,8 @@ const webserver = async () => {
|
||||
wh.WebRedirect = redirectView.get()
|
||||
} else if (handlerType === 'Forward' && forwardView !== null) {
|
||||
wh.WebForward = forwardView.get()
|
||||
} else if (handlerType === 'Internal' && internalView !== null) {
|
||||
wh.WebInternal = internalView.get()
|
||||
} else {
|
||||
throw new Error('unknown WebHandler type')
|
||||
}
|
||||
@ -4914,6 +4984,8 @@ const webserver = async () => {
|
||||
handlerType = 'Redirect'
|
||||
} else if (wh.WebForward) {
|
||||
handlerType = 'Forward'
|
||||
} else if (wh.WebInternal) {
|
||||
handlerType = 'Internal'
|
||||
} else {
|
||||
throw new Error('unknown WebHandler type')
|
||||
}
|
||||
@ -4999,7 +5071,7 @@ const webserver = async () => {
|
||||
),
|
||||
dom.br(),
|
||||
dom.h2('Handlers', attr.title('Corresponds with WebHandlers in domains.conf')),
|
||||
dom.p('Each incoming request is check against these handlers, in order. The first matching handler serves the request. Don\'t forget to save after making a change.'),
|
||||
dom.p('Each incoming request is matched against the configured handlers, in order. The first matching handler serves the request. System handlers such as for ACME validation, MTA-STS and autoconfig, come first. Then these webserver handlers. Finally the internal service handlers for admin, account, webmail and webapi configured in mox.conf. Don\'t forget to save after making a change.'),
|
||||
dom.table(dom._class('long'),
|
||||
dom.thead(
|
||||
dom.tr(
|
||||
|
Reference in New Issue
Block a user