You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by nf...@apache.org on 2009/07/14 07:21:11 UTC

svn commit: r793795 - in /incubator/wink/trunk: wink-common/src/main/java/org/apache/wink/common/internal/providers/header/ wink-server/src/main/java/org/apache/wink/server/internal/contexts/ wink-server/src/test/java/org/apache/wink/server/internal/

Author: nfischer
Date: Tue Jul 14 05:21:10 2009
New Revision: 793795

URL: http://svn.apache.org/viewvc?rev=793795&view=rev
Log:
Fix for inconsistent behavior for mis-quoted etag header values [WINK-72]

Modified:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/EntityTagHeaderDelegate.java
    incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java
    incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/PreconditionsTest.java

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/EntityTagHeaderDelegate.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/EntityTagHeaderDelegate.java?rev=793795&r1=793794&r2=793795&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/EntityTagHeaderDelegate.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/EntityTagHeaderDelegate.java Tue Jul 14 05:21:10 2009
@@ -41,8 +41,8 @@
         }
 
         // Check that e-tag is quoted-string
-        if (!eTag.startsWith("\"") && !eTag.endsWith("\"")) {
-            throw new IllegalArgumentException(" Entity Tag " + eTag + " is not quoted");
+        if (!eTag.startsWith("\"") || !eTag.endsWith("\"")) {
+            throw new IllegalArgumentException("Entity Tag " + eTag + " is not quoted properly");
         }
 
         // Remove quotes

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java?rev=793795&r1=793794&r2=793795&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/RequestImpl.java Tue Jul 14 05:21:10 2009
@@ -27,10 +27,12 @@
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Variant;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.ext.RuntimeDelegate;
@@ -76,7 +78,13 @@
      * returns ResponseBuilder if none of the tags matched
      */
     private ResponseBuilder evaluateIfMatch(EntityTag tag, String headerValue) {
-        EntityTagMatchHeader ifMatchHeader = ifMatchHeaderDelegate.fromString(headerValue);
+        EntityTagMatchHeader ifMatchHeader = null;
+        try {
+            ifMatchHeader = ifMatchHeaderDelegate.fromString(headerValue);
+        } catch (IllegalArgumentException e) {
+            throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
+        }
+        
         if (!ifMatchHeader.isMatch(tag)) {
             // none of the tags matches the etag
             ResponseBuilder responseBuilder = delegate.createResponseBuilder();
@@ -90,7 +98,13 @@
      * returns ResponseBuilder if any of the tags matched
      */
     private ResponseBuilder evaluateIfNoneMatch(EntityTag tag, String headerValue) {
-        EntityTagMatchHeader ifNoneMatchHeader = ifMatchHeaderDelegate.fromString(headerValue);
+        EntityTagMatchHeader ifNoneMatchHeader = null;
+        try {
+            ifNoneMatchHeader = ifMatchHeaderDelegate.fromString(headerValue);
+        } catch (IllegalArgumentException e) {
+            throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
+        }
+        
         if (ifNoneMatchHeader.isMatch(tag)) {
             // some tag matched
             ResponseBuilder responseBuilder = delegate.createResponseBuilder();

Modified: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/PreconditionsTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/PreconditionsTest.java?rev=793795&r1=793794&r2=793795&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/PreconditionsTest.java (original)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/PreconditionsTest.java Tue Jul 14 05:21:10 2009
@@ -252,6 +252,84 @@
         assertEquals("status", 200, response.getStatus());
 
     }
+    
+    /**
+     * ensure multiple etags are supported
+     */
+    public void testConditionIfMatchesMultipleOnSingleHeader() throws Exception {
+        String etag = "blablabla";
+
+        // GET
+        MockHttpServletRequest request = MockRequestConstructor.constructMockRequest("GET", "get/"
+            + etag, "*/*");
+        request.addHeader(HttpHeaders.IF_MATCH, "\"atlantic\",\"" + etag + "\",\"pacific\"");
+        MockHttpServletResponse response = invoke(request);
+        assertEquals("status", 200, response.getStatus());
+
+        // PUT
+        request = MockRequestConstructor.constructMockRequest("PUT", "get/" + etag, "*/*");
+        request.addHeader(HttpHeaders.IF_MATCH, "\"atlantic\",\"" + etag + "\",\"pacific\"");
+        response = invoke(request);
+        assertEquals("status", 200, response.getStatus());
+    }
+    
+    /**
+     * ETags not wrapped in quotes are invalid.  See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11
+     */
+    public void testConditionIfMatchesUnquoted() throws Exception {
+        String etag = "blablabla";
+
+        MockHttpServletRequest request = MockRequestConstructor.constructMockRequest("GET", "get/"
+                + etag, "*/*");
+        // no quotes
+        request.addHeader(HttpHeaders.IF_MATCH, etag);
+        MockHttpServletResponse response = invoke(request);
+        assertEquals("status", 400, response.getStatus());
+        
+        request = MockRequestConstructor.constructMockRequest("GET", "get/"
+                + etag, "*/*");
+        // beginning quote only
+        request.addHeader(HttpHeaders.IF_MATCH, "\"" + etag);
+        response = invoke(request);
+        assertEquals("status", 400, response.getStatus());
+        
+        request = MockRequestConstructor.constructMockRequest("GET", "get/"
+                + etag, "*/*");
+        // end quote only
+        request.addHeader(HttpHeaders.IF_MATCH, etag + "\"");
+        response = invoke(request);
+        assertEquals("status", 400, response.getStatus());
+
+    }
+    
+    /**
+     * ETags not wrapped in quotes are invalid.  See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11
+     */
+    public void testConditionIfNoneMatchesUnquoted() throws Exception {
+        String etag = "blablabla";
+
+        MockHttpServletRequest request = MockRequestConstructor.constructMockRequest("GET", "get/"
+                + etag, "*/*");
+        // no quotes
+        request.addHeader(HttpHeaders.IF_NONE_MATCH, etag);
+        MockHttpServletResponse response = invoke(request);
+        assertEquals("status", 400, response.getStatus());
+        
+        request = MockRequestConstructor.constructMockRequest("GET", "get/"
+                + etag, "*/*");
+        // beginning quote only
+        request.addHeader(HttpHeaders.IF_NONE_MATCH, "\"" + etag);
+        response = invoke(request);
+        assertEquals("status", 400, response.getStatus());
+        
+        request = MockRequestConstructor.constructMockRequest("GET", "get/"
+                + etag, "*/*");
+        // end quote only
+        request.addHeader(HttpHeaders.IF_NONE_MATCH, etag + "\"");
+        response = invoke(request);
+        assertEquals("status", 400, response.getStatus());
+
+    }
 
     public void testConditionGetNotIfMatches() throws Exception {
         String etag = "blablabla";
@@ -288,6 +366,29 @@
         assertEquals("status", 200, response.getStatus());
 
     }
+    
+    
+    /**
+     * ensure multiple etags are supported.  These are strange tests;  I need to ensure it goes through
+     * the IF_NONE_MATCH code and hits the second string in the IF_NONE_MATCH header, so I want a 304 or 412 response.
+     */
+    public void testConditionIfNoneMatchesMultipleOnSingleHeader() throws Exception {
+        String etag = "blablabla";
+
+        // GET
+        MockHttpServletRequest request = MockRequestConstructor.constructMockRequest("GET", "get/"
+            + etag, "*/*");
+        request.addHeader(HttpHeaders.IF_NONE_MATCH, "\"atlantic\",\"" + etag + "\",\"pacific\"");
+        MockHttpServletResponse response = invoke(request);
+        assertEquals("status", 304, response.getStatus());
+
+        // PUT
+        request = MockRequestConstructor.constructMockRequest("PUT", "get/" + etag, "*/*");
+        request.addHeader(HttpHeaders.IF_NONE_MATCH, "\"atlantic\",\"" + etag + "\",\"pacific\"");
+        response = invoke(request);
+        assertEquals("status", 412, response.getStatus());
+
+    }
 
     public void testConditionNoteIfNoneMatches() throws Exception {
         String etag = "blablabla";