seratch's weblog in Japanese

About Scala, Java and Ruby programming in Japaense. If you need English information, go to http://blog.seratch.net/

CORS に対応させるための Servlet Filter

JSON を返す API サーバのレスポンスを CORS に対応させるための Servlet フィルターを書きました。まあ「書いた」というほどのものでもないのですが。

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CORSResponseFilter implements Filter {

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    // NOOP
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletResponse _response = (HttpServletResponse)response;
    _response.setHeader("Access-Control-Allow-Origin", "*");
    chain.doFilter(request, _response);
  }

  @Override
  public void destroy() {
    // NOOP
  }

}

機密情報を含む JSON もあるかと思うので「X-Content-Type-Options: nosniff」とセットにする方がよいですね。

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;

public class JSONNoSniffResponseFilter implements Filter {

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    // NOOP
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
      private static final String CONTENT_TYPE = "Content-Type";

      private void setContentTypeOptions(String contentType) {
        if (isJsonContentType(contentType)) {
          doSetXConentTypeOptions();
        }
      }

      private void doSetXConentTypeOptions() {
        setHeader("X-Content-Type-Options", "nosniff");
      }

      private boolean isContentType(String headerName) {
        return headerName != null && headerName.equals(CONTENT_TYPE);
      }

      @Override
      public void setHeader(String name, String value) {
        if (isContentType(name)) {
          setContentTypeOptions(value);
        }
        super.setHeader(name, value);
      }

      @Override
      public void addHeader(String name, String value) {
        if (isContentType(name)) {
          setContentTypeOptions(value);
        }
        super.addHeader(name, value);
      }

      @Override
      public void setContentType(String type) {
        doSetXConentTypeOptions();
        super.setContentType(type);
      }
    });
  }

  @Override
  public void destroy() {
    // NOOP
  }

  static boolean isJsonContentType(String contentType) {
    if (contentType == null) {
      return false;
    } else {
      return contentType.matches("^application/json.*") || contentType.matches("^text/json.*");
    }
  }

}