web-dev-qa-db-fra.com

Ajout d'en-tête en réponse dans le filtre?

J'ai besoin d'ajouter l'en-tête dans chaque réponse. Je prévois de faire ci-dessous

public class MyFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        filterChain.doFilter(request, response);
            response.addHeader("Access-Control-Allow-Origin", "*"); 
    }

}

Je voudrais le faire après filterChain.doFilter(request, response) pour qu'une fois que le contrôleur le traite, j’ajoute un en-tête avant de retourner au client. Est-ce correct ?

Mais selon Comment écrire un filtre de réponse?

Après le retour de chain.doFilter, il est trop tard pour faire quoi que ce soit avec la réponse. À ce stade, l'intégralité de la réponse a déjà été envoyée au client et votre code n'y a pas accès.

La déclaration ci-dessus ne me semble pas juste. Je ne peux pas ajouter d'en-tête après filterChain.doFilter(request, response)? Si non pourquoi

j'utilise printemps MVC.

9
emilly

Après l'appel de filterChain.doFilter, il est trop tard pour faire quoi que ce soit avec la réponse. À ce stade, l'intégralité de la réponse a déjà été envoyée au client.

Vous devez créer une réponse d'encapsulation dans vos propres classes, transmettre ces wrappers à la méthode doFilter et gérer tout traitement dans vos wrappers.

Il existe déjà un encapsuleur de réponse: HttpServletResponseWrapper que vous pouvez étendre. Par exemple:

public class MyResponseRequestWrapper extends HttpServletResponseWrapper{
    public MyResponseRequestWrapper(HttpServletResponse response) {
        super(response);
    }
}

Votre filtre:

@Override
protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

    HttpServletResponse myResponse = (HttpServletResponse) response;
    MyResponseRequestWrapper responseWrapper = new MyResponseRequestWrapper(myResponse);
    responseWrapper.addHeader("Access-Control-Allow-Origin", "*");
    filterChain.doFilter(request, myResponse);
}
14
Luan

De l'article parfait

Un filtre qui modifie une réponse doit généralement capturer la réponse avant qu'elle ne soit renvoyée au client. Pour ce faire, vous transmettez un flux de remplacement au servlet qui génère la réponse. Le flux de réserve empêche le servlet de fermer le flux de réponse initial une fois terminé et permet au filtre de modifier la réponse du servlet.

Pour transmettre ce flux permanent au servlet, le filtre crée un encapsuleur de réponse qui substitue la méthode getWriter ou getOutputStream afin de renvoyer ce flux permanent. Le wrapper est transmis à la méthode doFilter de la chaîne de filtres. Les méthodes wrapper appellent par défaut jusqu'à l'objet de requête ou de réponse encapsulé. Cette approche suit le modèle bien connu Wrapper ou Decorator décrit dans Design Patterns, 

0
M Sach

C’est un peu tard, mais ce qui suit pourrait aider . Donc, si vous voulez vraiment ajouter des valeurs à un en-tête existant, ou ajouter de nouvelles valeurs à un en-tête existant, la meilleure façon possible d’écrire un wrapper et de définir le paramètre. valeur dans l'emballage.

Puis enchaîner la réponse dans le filtre

HttpServletResponse response = (HttpServletResponse) servletResponse;
ByteArrayPrinter pw = new ByteArrayPrinter();

// Create a wrapper
HttpServletResponse wrappedResp = new HttpServletResponseWrapper(response) {

    @Override
    public void setContentType(final String type) {
        super.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
    }

    @Override
    public PrintWriter getWriter() {
        return pw.getWriter();
    }

    // set the outputstream content type to JSON
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        ServletResponse response = this.getResponse();

        String ct = (response != null) ? response.getContentType() : null;
        if (ct != null && ct.contains(APPLICATION_XHTML)) {
            response.setContentType(ct + AppConstants.CONSTANT_COMMA + MediaType.APPLICATION_JSON_UTF8_VALUE);
        }
        return pw.getStream();
    }

};
chain.doFilter(httpRequest, wrappedResp);

Voici le ByteArrayPrinter.Java

public class ByteArrayPrinter {

    private ByteArrayOutputStream baos = new ByteArrayOutputStream();

    private PrintWriter pw = new PrintWriter(baos);

    private ServletOutputStream sos = new ByteArrayServletStream(baos);

    public PrintWriter getWriter() {
        return pw;
    }

    public ServletOutputStream getStream() {
        return sos;
    }

    byte[] toByteArray() {
        return baos.toByteArray();
    }
}

Et voici le ByteArrayServletOutputStream

public class ByteArrayServletStream extends ServletOutputStream {

    ByteArrayOutputStream baos;

    ByteArrayServletStream(ByteArrayOutputStream baos) {
        this.baos = baos;
    }

    @Override
    public void write(int param) throws IOException {
        baos.write(param);
    }

    @Override
    public boolean isReady() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void setWriteListener(WriteListener listener) {
        // TODO Auto-generated method stub

    }

}
0
Joey587