今回はサーブレットフィルタでGZIP圧縮に対応してみたいと思います。
必要なクラス
圧縮されたHTTPリクエストの解凍と、HTTPレスポンスの圧縮を実現するには、次の5つのクラスが必要です。
- GZIPFilter - Filterを実装します。HTTPヘッダを確認し、圧縮/解凍をするかどうか判断します。
- GZIPRequest - HttpServletRequestWrapperを継承します。GZIPServletInputStreamを返します。
- GZIPServletInputStream - HTTPリクエストを解凍するInputStreamです。
- GZIPResponse - HttpServletResponseWrapperを継承します。GZIPServletOutputStreamを返します。
- GZIPServletOutputStream - HTTPレスポンスを圧縮するOutputStreamです。
プログラム
GZIPFilter.java
package gzip; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class GZIPFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { if (!(req instanceof HttpServletRequest) || !(resp instanceof HttpServletResponse)) { chain.doFilter(req, resp); return; } HttpServletRequest httpReq = (HttpServletRequest) req; HttpServletResponse httpResp = (HttpServletResponse) resp; if (this.decompressRequired(httpReq)) { httpReq = new GZIPRequest(httpReq); } if (this.compressRequired(httpReq)) { httpResp = new GZIPResponse(httpResp); } chain.doFilter(httpReq, httpResp); } private boolean decompressRequired(HttpServletRequest request) { String contentEncoding = request.getHeader("Content-Encoding"); return "gzip".equals(contentEncoding); } private boolean compressRequired(HttpServletRequest request) { String acceptEncoding = request.getHeader("Accept-Encoding"); return "gzip".equals(acceptEncoding); } @Override public void init(FilterConfig filterConfig) throws ServletException { // nothing to do } @Override public void destroy() { // nothing to do } }
GZIPRequest.java
package gzip; import java.io.IOException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class GZIPRequest extends HttpServletRequestWrapper { public GZIPRequest(HttpServletRequest request) { super(request); } @Override public ServletInputStream getInputStream() throws IOException { return new GZIPServletInputStream(super.getInputStream()); } }
GZIPServletInputStream.java
package gzip; import java.io.IOException; import java.util.zip.GZIPInputStream; import javax.servlet.ServletInputStream; public class GZIPServletInputStream extends ServletInputStream { private GZIPInputStream gzipStream; public GZIPServletInputStream(ServletInputStream stream) throws IOException { this.gzipStream = new GZIPInputStream(stream); } @Override public int read() throws IOException { return gzipStream.read(); } @Override public void close() throws IOException { gzipStream.close(); } }
GZIPResponse.java
package gzip; import java.io.IOException; import java.util.zip.GZIPOutputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class GZIPResponse extends HttpServletResponseWrapper { public GZIPResponse(HttpServletResponse response) { super(response); super.setHeader("Content-Encoding", "gzip"); } @Override public ServletOutputStream getOutputStream() throws IOException { return new GZIPServletOutputStream(super.getOutputStream()); } }
GZIPServletOutputStream.java
package gzip; import java.io.IOException; import java.util.zip.GZIPOutputStream; import javax.servlet.ServletOutputStream; public class GZIPServletOutputStream extends ServletOutputStream { private final GZIPOutputStream gzipStream; public GZIPServletOutputStream (ServletOutputStream out) throws IOException { this.gzipStream = new GZIPOutputStream(out); } @Override public void write(int b) throws IOException { this.gzipStream.write(b); } @Override public void close() throws IOException { this.gzipStream.close(); } }
EchoServlet.java
package gzip; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class EchoServlet extends HttpServlet { @Override public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { InputStream in = req.getInputStream(); OutputStream out = resp.getOutputStream(); int input = 0; while (-1 != (input = in.read())) { out.write(input); } out.flush(); } }
通常であれば、HTTPサーバーで対応するのが妥当でしょう。
あえてサーブレットフィルタで実装するメリットがあるとすれば、warファイルにまとめられるので管理が楽になることでしょうか。
クライアントプログラム(C#)は次回の更新で載せる予定です。
関連
GZIP圧縮に対応したHTTPクライアントを作る
0 件のコメント:
コメントを投稿