読者です 読者をやめる 読者になる 読者になる

GeekFactory

int128.hatenablog.com

Apache Tomcat 5.5.26仕様変更対応(案)

java servlet

イコール等を含むクッキーを使用しているWebアプリケーションはTomcat 5.5.26以降で正常に動作しないようになります。改修可能な場合はまだマシなのですが、改修不可能なパッケージ等の場合は深刻な影響が考えられます。

http://d.hatena.ne.jp/int128/20081008/1223480443

上記に対応するApache Tomcatモジュールを作ってみました。このモジュールはWebアプリケーションの処理前にHTTPヘッダを書き換える処理を行います。

public class TomcatCookieHeaderValve extends ValveBase
{
	private Logger logger = Logger.getLogger(TomcatCookieHeaderValve.class.getName());
	
	public void invoke(Request req, Response res) throws IOException, ServletException
	{
		String requestCookie = req.getHeader("Cookie");
		if(requestCookie != null) {
			req.clearCookies();
			
			for(String part : requestCookie.split("; *")) {
				String key = part.substring(0, part.indexOf('='));
				String value = part.substring(part.indexOf('=')+1);
				
				Cookie cookie = new Cookie(key, value);
				req.addCookie(cookie);
				
				logger.info("Original request Cookie: " + requestCookie);
				logger.info("Fixed request Cookie: " + key + "=" + value);
			}
		}

		getNext().invoke(req, res);
		
		String responseCookie = res.getHeader("Set-Cookie");
		if(responseCookie != null) {
			String fixed = responseCookie.replace("\"", "");
			res.setHeader("Set-Cookie", fixed);
			
			logger.info("Original response Cookie: " + responseCookie);
			logger.info("Fixed response Cookie: " + fixed);
		}
	}
}
http://coderepos.org/share/browser/lang/java/misc/http-cookie-parser/trunk/src/org/hidetake/sandbox/TomcatCookieHeaderValve.java

プロジェクト全体をチェックアウトすると動作確認できます。server.xmlには下記を追記してください。

<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">
<Engine defaultHost="localhost" name="Catalina">

<!-- 追記 -->
<Valve className="org.hidetake.sandbox.TomcatCookieHeaderValve"/>

</Engine>
</Service>
</Server>

このモジュールは Valve を実装しているのですが、気になる一文が。

A Valve MUST NOT do any of the following things:

  • Change request properties that have already been used to direct the flow of processing control for this request (for instance, trying to change the virtual host to which a Request should be sent from a pipeline attached to a Host or Context in the standard implementation).
  • Create a completed Response AND pass this Request and Response on to the next Valve in the pipeline.
  • Consume bytes from the input stream associated with the Request, unless it is completely generating the response, or wrapping the request before passing it on.
  • Modify the HTTP headers included with the Response after the invokeNext() method has returned.
  • Perform any actions on the output stream associated with the specified Response after the invokeNext() method has returned.
http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/Valve.html#invoke(org.apache.catalina.connector.Request,%20org.apache.catalina.connector.Response)

invoke()の中で、Webアプリケーション処理後のHTTPヘッダを書き換えてはいけないと書いてあります。現状は動いてるけどルール違反だから無理なのかな。根の深い問題ですね。