From 25037c04a6f18b2e532f5c179dae588c2eec4280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reto=20Sch=C3=BCttel?= Date: Mon, 9 May 2016 12:39:53 +0200 Subject: [PATCH] When handling OPTION calls ignore both 'Date' and 'Allow' headers to decide if call has been handeled If not, no OPTION calls will be passed down to the rack app due to the fact that some implementations of DefaultServlet (i.e. Jetty and Tomcat) already sets these fields. Fixes #205 --- .../org/jruby/rack/servlet/ResponseCapture.java | 15 +++++++++++++-- .../ruby/rack/servlet/response_capture_spec.rb | 12 +++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jruby/rack/servlet/ResponseCapture.java b/src/main/java/org/jruby/rack/servlet/ResponseCapture.java index 11e77070..9c89dd2c 100644 --- a/src/main/java/org/jruby/rack/servlet/ResponseCapture.java +++ b/src/main/java/org/jruby/rack/servlet/ResponseCapture.java @@ -12,8 +12,11 @@ import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; @@ -24,6 +27,13 @@ * Response wrapper passed to filter chain. */ public class ResponseCapture extends HttpServletResponseWrapper { + /** + * In case of OPTION calls we check what headers are set by the servlet to decide if a request is + * already handled. Some container implementation of DefaultServlet already set 'Allow' and/or 'Date' fields which + * we need to ignore when working with this approach + */ + private static final Set HEADERS_NOT_CONSIDERED_HANDLED_FOR_OPTIONS_CALL + = new HashSet(Arrays.asList("Allow", "Date")); private static final String STREAM = "stream"; private static final String WRITER = "writer"; @@ -230,9 +240,10 @@ public boolean isHandled(final HttpServletRequest request) { // not to happen but there's all kind of beasts out there return false; } + // if any other headers occur beside 'Allow' and 'Date' we consider this request handled. for ( final String headerName : headerNames ) { - if ( ! "Allow".equals( headerName ) ) { - return handled = true; // not just Allow header - consider handled + if ( !HEADERS_NOT_CONSIDERED_HANDLED_FOR_OPTIONS_CALL.contains(headerName) ) { + return handled = true; } } return false; // OPTIONS with only Allow header set - unhandled diff --git a/src/spec/ruby/rack/servlet/response_capture_spec.rb b/src/spec/ruby/rack/servlet/response_capture_spec.rb index 606dff43..8ef3e385 100644 --- a/src/spec/ruby/rack/servlet/response_capture_spec.rb +++ b/src/spec/ruby/rack/servlet/response_capture_spec.rb @@ -65,6 +65,16 @@ expect( response_capture.isHandled(servlet_request) ).to be false end + it "is not considered handled when only Allow or Date header is added with OPTIONS" do + servlet_request.method = 'OPTIONS' + + # NOTE: Jetty sets both Date and Allow in DefaultServlet#doOptions + response_capture.addHeader "Allow", "GET, POST, OPTIONS" + response_capture.addHeader "Date", Time.now.httpdate + + expect( response_capture.isHandled(servlet_request) ).to be false + end + it "is considered handled when more than Allow header is added with OPTIONS" do pending "need Servlet API 3.0" unless servlet_30? @@ -100,4 +110,4 @@ def servlet_30? Java::JavaClass.for_name('javax.servlet.AsyncContext') rescue nil end -end \ No newline at end of file +end