Filter.doFilter() is called only once, before HttpHandler.handle() is called.
This means that you cannot modify the content of the HTTP response after your handler has run. So, it's more naturally a pre-filter.
However, in your implementation of doFilter(), you can wrap the the response's OutputStream with your own FilterOutputStream, so you can intercept the calls to HttpExchange.getResponseBody().write(...).
class MyFilter extends Filter {
@Override
public void doFilter(HttpExchange exch, Chain chain) throws IOException {
exch.setStreams(null, new MyInterceptedOutputStream(exch.getResponseBody()));
chain.doFilter(exch);
}
...
}
This MyInterceptedOutputStream class will need to extend OutputStream and implement its usual methods (write() and close())
One trick: Your wrapper must ensure that it will not write anything to the original OutputStream until HttpExchange.sendResponseHeaders() has been called. This means that you have to make sure that your wrapper constructor (MyInterceptedOutputStream(OutputStream os) in the above example) doesn't not write anything, unlike GZIPOutputStream() for example!
Bonus: Example of an OutputStream wrapper that compresses the stream... and works in HttpFilter.doFilter()
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
public class GZIPDelayedOutputStream extends OutputStream {
GZIPOutputStream gzipStream;
OutputStream originalStream;
public GZIPDelayedOutputStream(OutputStream os) {
super();
originalStream = os;
}
private void createGzipStreamIfNecessary() throws IOException {
if (gzipStream == null) {
gzipStream = new GZIPOutputStream(originalStream);
}
}
@Override
public void write(int b) throws IOException {
createGzipStreamIfNecessary();
gzipStream.write(b);
}
@Override
public void write(byte buf[]) throws IOException {
createGzipStreamIfNecessary();
gzipStream.write(buf);
}
@Override
public void write(byte[] buf, int off, int len) throws IOException {
createGzipStreamIfNecessary();
gzipStream.write(buf, off, len);
}
@Override
public void close() throws IOException {
createGzipStreamIfNecessary();
gzipStream.close();
}
}