Add a response header on every request in a grails 3 incterceptor
Asked Answered
S

2

6

I want to add this custom header to every response on my rest API:

"customHeader": "foo"

For this, I have created a grails interceptor that matches every controller and allows me to modify the request.

class FooInterceptor {

    FooInterceptor() {
        matchAll()
    }

    boolean before() { true }

    boolean after() {
        header 'customHeader', "foo" //first try
        response.addHeader 'customHeader', "foo" //second try to do the same
        response.setHeader 'customHeader', "foo" //third try, setHeader doesn't work either
        true
    }

    void afterView() {
    }
}

I have debugged and I can see that the after method is called after the controller respond:

respond([status:dodes.OK], [:])

I can see clearly that my interceptor is called and the addHader is not throwing any exception but my header is just not added to the final response.

My guess here is that maybe the grail's respond method somehow "locks" the response so the header can't be added after but I am not sure.

How can I add a header to every response on grails 3 using an interceptor?

Sabinesabino answered 11/10, 2019 at 9:48 Comment(1)
I have set headers in the filter as well (not the handlerInterceptor)... as the response is already created by the time it hits your application; it just doesn't have anything in it yet.Memnon
I
2

In one of my projects I use setHeader instead of addHeader and it works.

You can try this:

class FooInterceptor {

    FooInterceptor() {
        matchAll()
    }

    boolean before() { true }

    boolean after() {
        response.setHeader('customHeader', 'foo')
        true
    }

    void afterView() {
    }
}

The response object is an instance of the Servlet API’s HttpServletResponse class. Reading the documentation I see that both methods are available. The difference is that with addHeader you can add multiple values to a particular header, whereas an initial value would be overwritten if you use the setHeader method.

You can read more about it here: https://docs.grails.org/3.3.9/ref/Controllers/response.html

Isabelisabelita answered 11/10, 2019 at 11:25 Comment(3)
This did not work for me. I think response.setHeader('x', 'y') == header 'x', 'y'Matildematin
I also tried the set header and it doesn't work either, I updated the question.Sabinesabino
Can you tell me how you render the response in controller action? For example, if I have a view associated to that action, and I just render that view, the header works fine. But if I just have a render 'OK' in that action the header is not there anymore.Isabelisabelita
M
1

The following works for me. You may need to use before() instead.

class FooInterceptor {

    FooInterceptor() {
        match controller: '*', action: '*'
    }

    boolean before() {
        response.setHeader('customHeader', "foo") 
        true
    }

    boolean after() { true }

    void afterView() {
      // no-op
    }
}
Matildematin answered 11/10, 2019 at 10:41 Comment(4)
but what I want is to add the response after every response so it doesn't seem that using the before method is the right answer =(Sabinesabino
I see and I almost feel like I've been here before myself. I don't think setting the header works in the after methods. Maybe it's because the response has already been committed at this point but open to correction from others.Matildematin
I suspect you can scratch my last comment considering the docs say the following: The after method is executed after an action executes and can halt view rendering if it returns false. The after method can also modify the view or model using the view and model properties respectively:Matildematin
changing the return to false doesn't work either mmmSabinesabino

© 2022 - 2024 — McMap. All rights reserved.