Search code examples
grails

How to add custom response headers for all actions of all controllers in Grails


Environment:

  • Grails: 5.3.3 (or Grails 6.x)
  • Java: OpenJDK 11

I need to add headers to response for all actions of all controllers. I have tried implementing an interceptor as below:

CorsInterceptor:

 class CorsInterceptor {
      CorsInterceptor() {
            matchAll()
            log.info("CorsInterceptor(): BEGIN ")

      }
      boolean before() {
            log.info("before(): BEGIN")
            true }

      boolean after() {
            response.addHeader("MyRespHeader","My dream data here")
            log.info("after(): final")
            true
      }

      void afterView() {
            log.info("afterView(): BEGIN ...")
            response.setHeader("MyRespHeader","My dream data here")
        // no-op
      }

}

log output:

2024-04-07 19:55:04.287  INFO --- [tp1902630939-52] com.example.CorsInterceptor              : before(): BEGIN
2024-04-07 19:55:04.312  INFO --- [tp1902630939-52] com.example.HomeController               : json:{
   "fieldname": "city",
   "value": "Tokyo city"
}
2024-04-07 19:55:04.319  INFO --- [tp1902630939-52] com.example.CorsInterceptor              : after(): final
2024-04-07 19:55:04.319  INFO --- [tp1902630939-52] com.example.CorsInterceptor              : afterView(): BEGIN ...

enter image description here

From the output of log I can be sure that the after() of CorsInterceptor has been executed. However, from Postman, I find no the custom response header MyRespHeader!

I know I can add:

response.addHeader("MyRespHeader","My dream data here")

to each action of each controller and it will work! But that's not a good approach.

My code is here: https://github.com/wureka/g612-demo

Any suggestion is appreciated.


Solution

  • Using the ResponseRenderer.render(CharSequence txt) method in the controller, flushes the writer of the ServletResponse and subsequently sets the response as committed. This means that the response's status code is set and its headers written and can no longer be changed.

    This is why adding a header in the CorsInterceptor.after() method has no effect.

    You can however, set the header in the CorsInterceptor.before() method.