georchestra / georchestra-gateway

GNU General Public License v3.0
0 stars 5 forks source link

Catch application errors to display standardized error page #122

Closed emmdurin closed 3 months ago

emmdurin commented 3 months ago

We wanted to show a standardized error page when an application behind the gateway returns an HTTP 4xx or 5xx error, instead of an application specific error page.

It uses error pages templates embedded in gateway or overriden in gateway/template/error directory of datadir.

To enable it globally, add this to gateway/application.yaml of datadir :

spring:
  cloud:
    gateway:
      default-filters:
        - ApplicationError

To enable it only on some routes, add this to concerned routes in gateway/routes.yaml of datadir :

        filters:
        - name: ApplicationError

A side effect that can be discussed is that it prints a stack trace in gateway log as implementation throws an exception. Some things can be done differently, like using a more specific exception class, or catch it in a AbstractErrorWebExceptionHandler subclass to maybe avoid to print it in log, or do not throw an exception but replace content of response by content of 500.html template. Suggestions are welcome.

Example of log with printed stacktrace :

gateway-1  | 2024-05-16 07:56:41.462 DEBUG 1 --- [or-http-epoll-7] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/auth/login', method=null}
gateway-1  | 2024-05-16 07:56:41.462 DEBUG 1 --- [or-http-epoll-7] athPatternParserServerWebExchangeMatcher : Request 'GET /console/a' doesn't match 'null /auth/login'
gateway-1  | 2024-05-16 07:56:41.462 DEBUG 1 --- [or-http-epoll-7] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : No matches found
gateway-1  | 2024-05-16 07:56:41.463 DEBUG 1 --- [or-http-epoll-7] ebSessionServerSecurityContextRepository : No SecurityContext found in WebSession: 'org.springframework.web.server.session.InMemoryWebSessionStore$InMemoryWebSession@e26b7e1'
gateway-1  | 2024-05-16 07:56:41.479 ERROR 1 --- [or-http-epoll-7] a.w.r.e.AbstractErrorWebExceptionHandler : [a3de8979-61]  500 Server Error for HTTP GET "/console/a"
gateway-1  | 
gateway-1  | java.lang.RuntimeException: SERVICE ERROR
gateway-1  |    at org.georchestra.gateway.filter.headers.ServiceErrorGatewayFilterFactory$ServiceErrorGatewayFilter.lambda$filter$0(ServiceErrorGatewayFilterFactory.java:43) ~[classes/:23.1-SNAPSHOT]
gateway-1  |    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
gateway-1  | Error has been observed at the following site(s):
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.oauth2.client.web.server.authentication.OAuth2LoginAuthenticationWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.oauth2.client.web.server.OAuth2AuthorizationRequestRedirectWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
gateway-1  |    *__checkpoint ? HTTP GET "/console/a" [ExceptionHandlingWebHandler]
gateway-1  | Original Stack Trace:
gateway-1  |            at org.georchestra.gateway.filter.headers.ServiceErrorGatewayFilterFactory$ServiceErrorGatewayFilter.lambda$filter$0(ServiceErrorGatewayFilterFactory.java:43) ~[classes/:23.1-SNAPSHOT]
gateway-1  |            at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:73) ~[reactor-core-3.4.29.jar:3.4.29]
                        < stack trace continues about 50 lines >
pmauduit commented 3 months ago

poke @groldan I think DT's request is similar to what is intended here.

groldan commented 3 months ago

Also, as discussed in our meeting, it'd be great if this filter could be enabled through a config property, being disabled by default

either way, whether it's enabled or disabled by default, just make sure to add an entry in the security docs