LoginSignup
7
8

More than 5 years have passed since last update.

SpringのCORS機能がRFC 3986なホスト名に対応してなかった・・・

Posted at

java.net.URIで扱えるホスト名はRFC 2396 (RFC 3986じゃない・・)」を投稿するきっかけとなったSpring WebのCORS(Cross-Origin Resource Sharing)機能のエラーは、Spring Frameworkのバグでした・・・ :persevere:
バグ内容は、SPR-14305を参照してくだい。

なお、このバグは、最新の開発ライン(投稿時点では未リリース)であるSpring Framework 4.3(Spring Boot 1.4)では既に解消されており、Spring Framework 4.2.7.RELEASEへバックポートされる予定です。

環境

  • Java SE 8
  • Spring Framework 4.2.6.RELEASE(Spring Boot 1.3.5.RELEASE)

事象

リクエストにOriginヘッダーがあるとCORS(Cross-Origin Resource Sharing)関連の処理が動き、その処理の中でリクエストURLをjava.net.URIに変換するロジックがあります。URIクラスはRFC 3986に対応していないため、例えばリクエストURLが「 http://spring_app/」だとホスト名がnullになり、Spring側の処理の中でNPEが発生しています。

スタックトレースの抜粋
...
2016-05-25 04:46:48.890 ERROR 84097 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null
    at org.springframework.web.util.WebUtils.isSameOrigin(WebUtils.java:816) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.cors.DefaultCorsProcessor.processRequest(DefaultCorsProcessor.java:76) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMapping$CorsInterceptor.preHandle(AbstractHandlerMapping.java:503) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:134) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:956) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.0.33.jar:8.0.33]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
...

この事象を再現するプロジェクトは、https://github.com/spring-projects/spring-framework-issues/blob/master/SPR-14305/ にあります。具体的な発生条件は、 テストコード ReproTests.javaをごらんください。

対処方法

基本的には・・・
Spring Framework 4.3.0(2016/6/8リリース予定) or 4.2.7(2016/7/20リリース予定)がリリースされるのを待ちましょう!!

どうしてもリリースを待てない場合は、org.springframework.web.cors.DefaultCorsProcessorprocessRequestメソッドをオーバーライドし、拡張したクラスをSpring MVC(AbstractHandlerMappingcorsProcessorプロパティ)に適用することでエラーを回避することは可能です。

まとめ

今回の事象はSpringのバグでしたが、Javaのjava.net.URIクラスがRFC 3986に対応していないことがそもそもの原因です・・・。RFC 3986サポート用のIssueはあがっているようですが、残念ながら完全に放置状態です :sob:
今回のように使用しているライブラリにバグや改善の余地がある場合は、オレオレ拡張などで個別(アドホック)に対応するのではなく、ライブラリ側にIssueをあげてライブラリ本家に取り込んでもらえるように働きかけるようにしましょう!!!

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8