001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.hayabusa.filter; 017 018import jakarta.servlet.ServletRequest; 019import jakarta.servlet.ServletResponse; 020import jakarta.servlet.http.HttpServletRequest; 021import jakarta.servlet.http.HttpServletResponse; 022import jakarta.servlet.ServletException; 023import jakarta.servlet.http.HttpFilter; 024import jakarta.servlet.FilterChain; 025import jakarta.servlet.FilterConfig; 026import jakarta.servlet.annotation.WebFilter; 027 028import jakarta.servlet.http.HttpServletResponseWrapper; 029 030import java.io.IOException; 031 032/** 033 * CacheControlFilter は、Filter インターフェースを継承した アクセス制御クラスです。 034 * web.xml で filter 設定することにより、Webアプリケーションへのアクセスを制御できます。 035 * ※ @WebFilter アノテーションだけでは、上手く動かなかった。 036 * 037 * 本来は、org.apache.catalina.filters.ExpiresFilter を使用する所だが、単純に 038 * キャッシュさせる設定だけ入れたかっただけなので、こちらにした。 039 * 040 * Cache-Control ヘッダーに対して、private,max-age=31536000,immutable を設定します。 041 * 対象は、.css , .js , .gif , .png です。 042 * 大文字、小文字の区別有で、リクエストURIの後ろ一致で判定しています。 043 * 044 * 【WEB-INF/web.xml】 045 * <filter> 046 * <filter-name>CacheControlFilter</filter-name> 047 * <filter-class>org.opengion.hayabusa.filter.CacheControlFilter</filter-class> 048 * <init-param> 049 * <param-name>debug</param-name> 050 * <param-value>true</param-value> 051 * </init-param> 052 * </filter> 053 * 054 * <filter-mapping> 055 * <filter-name>CacheControlFilter</filter-name> 056 * <url-pattern>/*;/url-pattern> 057 * </filter-mapping> 058 * 059 * @og.group フィルター処理 060 * @og.rev 8.3.0.0 (2022/08/01) 新規追加 061 * 062 * @version 8.2 063 * @author Kazuhiko Hasegawa 064 * @since JDK17.0, 065 */ 066@WebFilter(filterName="CacheControlFilter", urlPatterns="/*") 067public final class CacheControlFilter extends HttpFilter { // HttpFilter は、Servlet 4.0 068 private static final long serialVersionUID = 830020220801L ; 069 070 private boolean isDebug ; 071 072 /** 073 * Filter インターフェースの init メソッド (何もしません)。 074 * 075 * 実行時のURLを標準出力に出力します。 076 * 077 * @og.rev 8.3.0.0 (2022/08/01) 新規追加 078 * 079 * @param filterConfig FilterConfigオブジェクト 080 */ 081 @Override // Filter 082 public void init(final FilterConfig filterConfig) { 083 isDebug = Boolean.parseBoolean( filterConfig.getInitParameter("debug") ); 084 } 085 086 /** 087 * フィルター処理本体のメソッドです。 088 * 089 * @og.rev 8.3.0.0 (2022/08/01) 新規追加 090 * 091 * @param req ServletRequestオブジェクト 092 * @param res ServletResponseオブジェクト 093 * @param chain FilterChainオブジェクト 094 * @throws IOException 入出力エラーが発生した場合、throw されます。 095 * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。 096 */ 097 @Override // HttpFilter 098 public void doFilter( final ServletRequest req, 099 final ServletResponse res, 100 final FilterChain chain ) 101 throws IOException, ServletException { 102 if( req instanceof HttpServletRequest && res instanceof HttpServletResponse ) { 103 final HttpServletRequest request = (HttpServletRequest) req; 104 final HttpServletResponse response = (HttpServletResponse) res; 105 106 final int type = checkType( request ) ; 107 if( type > 0 ) { 108 // final CCFResponseWrapper wrapResponse = new CCFResponseWrapper( hsRes,type ); 109 // chain.doFilter(req, wrapResponse); 110 chain.doFilter(req, res); 111 response.setHeader( "Cache-Control", "private,max-age=31536000,immutable" ); 112 if( type == 1 ) { 113 response.setCharacterEncoding( "UTF-8" ); 114 } 115 } 116 } 117 chain.doFilter(req, res); 118 } 119 120 /** 121 * フィルターを実行するかどうか、判定します。 122 * 123 * @og.rev 8.3.0.0 (2022/08/01) 新規追加 124 * 125 * @param request ServletRequestオブジェクト 126 * 127 * @return -1:対象外 1:テキスト 2:バイナリ 128 */ 129 private int checkType( final HttpServletRequest request ) { 130 final String url = request.getRequestURI(); 131 132 int rtnType = -1; 133 if( url.endsWith( ".css" ) || url.endsWith( ".js" ) ) { rtnType = 1; } 134 else if( url.endsWith( ".gif" ) || url.endsWith( ".png" ) ) { rtnType = 2; } 135 136 if( isDebug && rtnType > 0 ) { System.out.println( "CacheControlFilter=" + url ); } 137 138 return rtnType ; 139 } 140 141 /** 142 * ResponseWrapper の継承クラス 143 * 144 * とりあえず、Wrapper 無しでもヘッダーの設定が出来たので、今は未使用とします。 145 * 146 * @og.rev 8.3.0.0 (2022/08/01) 新規追加 147 */ 148 final static class CCFResponseWrapper extends HttpServletResponseWrapper { 149 /** オリジナルのレスポンス */ 150 protected HttpServletResponse origResponse ; 151 152 /** 153 * コンストラクター 154 * 155 * @param response HttpServletResponseオブジェクト 156 * @param type -1:対象外 1:テキスト 2:バイナリ 157 */ 158 public CCFResponseWrapper(final HttpServletResponse response , final int type) { 159 super(response); 160 origResponse = response; 161 origResponse.setHeader( "Cache-Control", "private,max-age=31536000,immutable" ); 162 if( type == 1 ) { 163 origResponse.setCharacterEncoding( "UTF-8" ); 164 } 165 // origResponse.setHeader( "Expires", null ); 166 // origResponse.setHeader( "Pragma" , null ); 167 } 168 } 169}