弊社はSeleniumを用いたガチなE2Eテストを全ての受託案件で実施しており、 CI環境では24H365Dで膨大なSeleniumスクリプトが動いています。
つい先日、CI環境のTomcatのバージョンを8.5.8に上げた所、意味不明なエラーが出てテストが失敗するようになりました。 こんな感じ。
10-Dec-2016 15:54:56.761 INFO [http-apr-8080-exec-2] org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:417) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:667) ...
はい?何?と思ってHTTPログを見てみると、当該エラーが発生したHTTPリクエストは次のようになっています。
127.0.0.1 - - [10/Dec/2016:15:54:56] "GET /foo.js HTTP/1.1" 200 123 ←普通の応答 127.0.0.1 - - [10/Dec/2016:15:54:56] "-" 400 - ←なにこれ??
で、現象としてはJSファイルのダウンロードのHTTPリクエストが失敗しているために、画面が正しく動作せずテスト失敗になるようです。
結論→FirefoxのHTTP PipeliningをOFFにしたら治った
色々試行錯誤してみたのですが、結果としてはFirefoxのHTTP PipeliningをOFFにしたら治まりました。
HTTP PipeliningはデフォルトでOFFになっているのですが、 「もしかしたらテスト実行が早くなるかな―」と淡い期待とともにONにしていたものです。
Tomcat-8.5.6までは何の問題もなく動作していたわけなので、「Tomcat-8.5.8以降ではHTTPパイプラインは動作しない」ということになります。(8.5.9でもダメだったので)
誰もHTTPパイプラインなんて使っていない?
Wikipediaによると(wikipedia:HTTPパイプライン)、
近年のウェブブラウザでは、Prestoを搭載していた時代のOperaのみがパイプライン化を完全に実装し既定で有効としていた。他のブラウザは、パイプライン化を実装しているものの問題があることから既定では無効化していた、あるいは実装していない。
だそうです。