Hi Christian,

Many thanks for your reply. Pre and Post Hooks would be great

Here is some crazy stuff I thought of  (just a skeleton).  It should allow say a code search for %((rest)|(ws)).*:((path)|(connect))to ensure that all endpoints have permissions middleware of some sort. 

Hope it is not too silly.

Adam 
/---------------------------------
import module namespace authMiddleware = 'http://middleware..auth' at '[...].xqm'

declare
  %rest:preHook:(authMiddleware:authoriseFail2BanRest):path("/main/admin"):result($vs_authKeyResult)
  %rest:postHook:(noCaching:noCacheFunc):(htmlTextConversion:text2HTMLFunc)
  %output:method("text")
function local:admin($vs_authKeyResult) {
  let $authorized := 'Welcome to the admin page'
  let $unauthorized := 'Your IP has been logged with fail2ban'
  let $result := if ($vs_authKeyResult=true()) then $authorized else $unauthorized
  return $result
};

declare
  %ws:preHook:(authMiddleware:authoriseFail2BanWS):connect('/'):result($vs_authKeyResult)
function local:connect($vs_authKeyResult) as empty-sequence() {
  let $id := ws:id()
  let $message := json:serialize(map {
    'type': 'Connect',
    'id': $id
  })
  return if ($vs_authKeyResult=true()) then ws:broadcast($message) else ()
};

/---------------------------------
module namespace authMiddleware = 'http://middleware.auth';

import module namespace loggingMiddleware = 'http://middleware.logging' at '[...].xqm'

declare
%preHook:(loggingMiddleware:functionLog):result($vs_logResult)  (:a postHook here would be before the calling function local:admin :)
%rest:query-param("vs_authKey", " {$vs_authKey}")
function authMiddleware:authoriseFail2BanRest($vs_authKey,$vs_logResult) {
  let $result := if ($vs_authKey='YKJKhh') then true() else false()
  let $result := if ($vs_logResult='override') then true() else result()
  return $result
};

/---------------------------------
module namespace loggingMiddleware = 'http://middleware.logging';
module namespace myUpdatingOutput = 'http://function.updatingOutput';

declare
%rest:query-param("vs_logAside", " {$vs_logAside}")
function loggingMiddleware:functionLog($vs_logAside) {
  let $result := if (vs_logAside != 'adminOverride*75x4558') then myUpdatingOutput:logwrite(request:remote-address()) else 'override'
  return $result
};