### GET /api/secure/data without a key: the FILTER answers
HTTP 401  body={"error":"missing or wrong X-Api-Key"}
01 REQUEST  filter:raw(order 5)            before chain
02 REQUEST  filter:accessLog(order 10)     before chain GET /api/secure/data
03 REQUEST  filter:apiKey(order 20)        REJECT 401, chain stops here
04 REQUEST  filter:accessLog(order 10)     after chain status=401 asyncStarted=false
05 REQUEST  filter:raw(order 5)            after chain

### GET /api/secure/data with the key
HTTP 200  body=secret data
01 REQUEST  filter:raw(order 5)            before chain
02 REQUEST  filter:accessLog(order 10)     before chain GET /api/secure/data
03 REQUEST  filter:apiKey(order 20)        key ok, continue
04 REQUEST  servlet:DispatcherServlet      doDispatch start
05 REQUEST  interceptor:A                  preHandle  handler=HandlerMethod HelloController#secure
06 REQUEST  interceptor:B                  preHandle  handler=HandlerMethod HelloController#secure
07 REQUEST  aspect:controller              before HelloController#secure args=[]
08 REQUEST  controller                     secure()
09 REQUEST  aspect:controller              after  HelloController#secure returned=secret data (String)
10 REQUEST  interceptor:B                  postHandle status=200 modelAndView=null
11 REQUEST  interceptor:A                  postHandle status=200 modelAndView=null
12 REQUEST  interceptor:B                  afterCompletion ex=null
13 REQUEST  interceptor:A                  afterCompletion ex=null
14 REQUEST  servlet:DispatcherServlet      doDispatch end
15 REQUEST  filter:accessLog(order 10)     after chain status=200 asyncStarted=false
16 REQUEST  filter:raw(order 5)            after chain

### GET /api/admin/report as a plain user: the INTERCEPTOR denies
HTTP 403  body={"timestamp":"...","status":403,"error":"Forbidden","path":"/api/admin/report"}
01 REQUEST  filter:raw(order 5)            before chain
02 REQUEST  filter:accessLog(order 10)     before chain GET /api/admin/report
03 REQUEST  servlet:DispatcherServlet      doDispatch start
04 REQUEST  interceptor:A                  preHandle  handler=HandlerMethod HelloController#admin
05 REQUEST  interceptor:B                  preHandle  handler=HandlerMethod HelloController#admin
06 REQUEST  interceptor:role               @RequiresRole("admin") on admin, X-Role=user -> deny 403
07 REQUEST  interceptor:B                  afterCompletion ex=null
08 REQUEST  interceptor:A                  afterCompletion ex=null
09 REQUEST  servlet:DispatcherServlet      doDispatch end
10 REQUEST  filter:accessLog(order 10)     after chain status=403 asyncStarted=false
11 REQUEST  filter:raw(order 5)            after chain
12 ERROR    servlet:DispatcherServlet      doDispatch start
13 ERROR    interceptor:A                  preHandle  handler=HandlerMethod BasicErrorController#error
14 ERROR    interceptor:A                    error attributes: status=403 exception=null
15 ERROR    interceptor:B                  preHandle  handler=HandlerMethod BasicErrorController#error
16 ERROR    interceptor:B                  postHandle status=403 modelAndView=null
17 ERROR    interceptor:A                  postHandle status=403 modelAndView=null
18 ERROR    interceptor:B                  afterCompletion ex=null
19 ERROR    interceptor:A                  afterCompletion ex=null
20 ERROR    servlet:DispatcherServlet      doDispatch end

### GET /api/admin/report as admin
HTTP 200  body=admin report
01 REQUEST  filter:raw(order 5)            before chain
02 REQUEST  filter:accessLog(order 10)     before chain GET /api/admin/report
03 REQUEST  servlet:DispatcherServlet      doDispatch start
04 REQUEST  interceptor:A                  preHandle  handler=HandlerMethod HelloController#admin
05 REQUEST  interceptor:B                  preHandle  handler=HandlerMethod HelloController#admin
06 REQUEST  interceptor:role               @RequiresRole("admin") on admin, X-Role=admin -> allow
07 REQUEST  aspect:controller              before HelloController#admin args=[]
08 REQUEST  controller                     admin()
09 REQUEST  aspect:controller              after  HelloController#admin returned=admin report (String)
10 REQUEST  interceptor:B                  postHandle status=200 modelAndView=null
11 REQUEST  interceptor:A                  postHandle status=200 modelAndView=null
12 REQUEST  interceptor:B                  afterCompletion ex=null
13 REQUEST  interceptor:A                  afterCompletion ex=null
14 REQUEST  servlet:DispatcherServlet      doDispatch end
15 REQUEST  filter:accessLog(order 10)     after chain status=200 asyncStarted=false
16 REQUEST  filter:raw(order 5)            after chain

### GET /api/gated/hello: gate returns true
HTTP 200  body=gated hello
01 REQUEST  filter:raw(order 5)            before chain
02 REQUEST  filter:accessLog(order 10)     before chain GET /api/gated/hello
03 REQUEST  servlet:DispatcherServlet      doDispatch start
04 REQUEST  interceptor:A                  preHandle  handler=HandlerMethod HelloController#gated
05 REQUEST  interceptor:gate               preHandle -> true
06 REQUEST  interceptor:B                  preHandle  handler=HandlerMethod HelloController#gated
07 REQUEST  aspect:controller              before HelloController#gated args=[]
08 REQUEST  controller                     gated()
09 REQUEST  aspect:controller              after  HelloController#gated returned=gated hello (String)
10 REQUEST  interceptor:B                  postHandle status=200 modelAndView=null
11 REQUEST  interceptor:A                  postHandle status=200 modelAndView=null
12 REQUEST  interceptor:B                  afterCompletion ex=null
13 REQUEST  interceptor:A                  afterCompletion ex=null
14 REQUEST  servlet:DispatcherServlet      doDispatch end
15 REQUEST  filter:accessLog(order 10)     after chain status=200 asyncStarted=false
16 REQUEST  filter:raw(order 5)            after chain

### GET /api/gated/hello?mode=write: gate returns false after writing a 403 body
HTTP 403  body={"error":"gate closed"}
01 REQUEST  filter:raw(order 5)            before chain
02 REQUEST  filter:accessLog(order 10)     before chain GET /api/gated/hello
03 REQUEST  servlet:DispatcherServlet      doDispatch start
04 REQUEST  interceptor:A                  preHandle  handler=HandlerMethod HelloController#gated
05 REQUEST  interceptor:gate               preHandle -> FALSE (mode=write)
06 REQUEST  interceptor:A                  afterCompletion ex=null
07 REQUEST  servlet:DispatcherServlet      doDispatch end
08 REQUEST  filter:accessLog(order 10)     after chain status=403 asyncStarted=false
09 REQUEST  filter:raw(order 5)            after chain

### GET /api/gated/hello?mode=silent: gate returns false and writes nothing
HTTP 200  (empty body)
01 REQUEST  filter:raw(order 5)            before chain
02 REQUEST  filter:accessLog(order 10)     before chain GET /api/gated/hello
03 REQUEST  servlet:DispatcherServlet      doDispatch start
04 REQUEST  interceptor:A                  preHandle  handler=HandlerMethod HelloController#gated
05 REQUEST  interceptor:gate               preHandle -> FALSE (mode=silent)
06 REQUEST  interceptor:A                  afterCompletion ex=null
07 REQUEST  servlet:DispatcherServlet      doDispatch end
08 REQUEST  filter:accessLog(order 10)     after chain status=200 asyncStarted=false
09 REQUEST  filter:raw(order 5)            after chain
