This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new 88e3eb2  CXF-8120: JAX-RS 2.1 SSE client: forbidden response without 
WebApplicationException
88e3eb2 is described below

commit 88e3eb24de7ee6498240aac557ccf3d75a1be9af
Author: reta <drr...@gmail.com>
AuthorDate: Sun Sep 22 12:26:32 2019 -0400

    CXF-8120: JAX-RS 2.1 SSE client: forbidden response without 
WebApplicationException
---
 .../org/apache/cxf/jaxrs/utils/ExceptionUtils.java | 12 ++++
 .../apache/cxf/jaxrs/client/AbstractClient.java    | 10 +---
 .../cxf/jaxrs/sse/client/SseEventSourceImpl.java   | 10 +++-
 .../jaxrs/sse/client/SseEventSourceImplTest.java   | 64 ++++++++++++++++++++--
 4 files changed, 80 insertions(+), 16 deletions(-)

diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ExceptionUtils.java
 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ExceptionUtils.java
index 5e8b014..a8c607a 100644
--- 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ExceptionUtils.java
+++ 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ExceptionUtils.java
@@ -21,6 +21,7 @@ package org.apache.cxf.jaxrs.utils;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.reflect.Constructor;
 
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
@@ -169,4 +170,15 @@ public final class ExceptionUtils {
             return toWebApplicationException(ex, response);
         }
     }
+    
+    public static WebApplicationException toWebApplicationException(Response 
response) {
+        try {
+            final Class<?> exceptionClass = 
ExceptionUtils.getWebApplicationExceptionClass(response, 
+                WebApplicationException.class);
+            final Constructor<?> ctr = 
exceptionClass.getConstructor(Response.class);
+            return (WebApplicationException)ctr.newInstance(response);
+        } catch (Throwable ex) {
+            return new WebApplicationException(response);
+        }
+    }
 }
diff --git 
a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java 
b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
index c6f6a88..80eb2cc 100644
--- a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
+++ b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
@@ -23,7 +23,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
@@ -536,14 +535,7 @@ public abstract class AbstractClient implements Client {
     }
 
     protected WebApplicationException 
convertToWebApplicationException(Response r) {
-        try {
-            Class<?> exceptionClass = 
ExceptionUtils.getWebApplicationExceptionClass(r,
-                                       WebApplicationException.class);
-            Constructor<?> ctr = exceptionClass.getConstructor(Response.class);
-            return (WebApplicationException)ctr.newInstance(r);
-        } catch (Throwable ex2) {
-            return new WebApplicationException(r);
-        }
+        return ExceptionUtils.toWebApplicationException(r);
     }
 
     protected <T> T readBody(Response r, Message outMessage, Class<T> cls,
diff --git 
a/rt/rs/sse/src/main/java/org/apache/cxf/jaxrs/sse/client/SseEventSourceImpl.java
 
b/rt/rs/sse/src/main/java/org/apache/cxf/jaxrs/sse/client/SseEventSourceImpl.java
index 3a7f78e..f0c2acf 100644
--- 
a/rt/rs/sse/src/main/java/org/apache/cxf/jaxrs/sse/client/SseEventSourceImpl.java
+++ 
b/rt/rs/sse/src/main/java/org/apache/cxf/jaxrs/sse/client/SseEventSourceImpl.java
@@ -41,6 +41,7 @@ import javax.ws.rs.sse.SseEventSource;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.utils.ExceptionUtils;
 
 /**
  * SSE Event Source implementation 
@@ -191,13 +192,20 @@ public class SseEventSourceImpl implements SseEventSource 
{
 
             // A client can be told to stop reconnecting using the HTTP 204 No 
Content 
             // response code. In this case, we should give up.
-            if (response.getStatus() == 204) {
+            final int status = response.getStatus();
+            if (status == 204) {
                 LOG.fine("SSE endpoint " + target.getUri() + " returns no 
data, disconnecting");
                 state.set(SseSourceState.CLOSED);
                 response.close();
                 return;
             }
 
+            // Convert unsuccessful responses to instances of 
WebApplicationException
+            if (status != 304 && status >= 300) {
+                LOG.fine("SSE connection to " + target.getUri() + " returns " 
+ status);
+                throw ExceptionUtils.toWebApplicationException(response);
+            }
+
             // Should not happen but if close() was called from another 
thread, we could
             // end up there.
             if (state.get() == SseSourceState.CLOSED) {
diff --git 
a/rt/rs/sse/src/test/java/org/apache/cxf/jaxrs/sse/client/SseEventSourceImplTest.java
 
b/rt/rs/sse/src/test/java/org/apache/cxf/jaxrs/sse/client/SseEventSourceImplTest.java
index 1c0ae15..787b5d5 100644
--- 
a/rt/rs/sse/src/test/java/org/apache/cxf/jaxrs/sse/client/SseEventSourceImplTest.java
+++ 
b/rt/rs/sse/src/test/java/org/apache/cxf/jaxrs/sse/client/SseEventSourceImplTest.java
@@ -34,6 +34,8 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.client.ClientBuilder;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.sse.InboundSseEvent;
 import javax.ws.rs.sse.SseEventSource;
 
@@ -57,7 +59,8 @@ public class SseEventSourceImplTest {
 
     enum Type {
         NO_CONTENT, NO_SERVER, BUSY,
-        EVENT, EVENT_JUST_DATA, EVENT_JUST_NAME, EVENT_NO_RETRY, 
EVENT_BAD_RETRY, EVENT_MIXED, EVENT_BAD_NEW_LINES;
+        EVENT, EVENT_JUST_DATA, EVENT_JUST_NAME, EVENT_NO_RETRY, 
EVENT_BAD_RETRY, EVENT_MIXED, EVENT_BAD_NEW_LINES,
+        EVENT_NOT_AUTHORIZED;
     }
 
     private static final String EVENT = "event: event\n"
@@ -276,6 +279,36 @@ public class SseEventSourceImplTest {
     }
 
     @Test
+    public void testReconnectAndNotAuthorized() throws InterruptedException, 
IOException {
+        try (SseEventSource eventSource = 
withReconnect(Type.EVENT_NOT_AUTHORIZED)) {
+            eventSource.open();
+            assertThat(eventSource.isOpen(), equalTo(false));
+            assertThat(errors.size(), equalTo(1));
+
+            // Allow the event processor to pull for events (150ms)
+            Thread.sleep(150L);
+        }
+        
+        assertThat(errors.size(), equalTo(2));
+        assertThat(events.size(), equalTo(0));
+    }
+
+    @Test
+    public void testNoReconnectAndNotAuthorized() throws InterruptedException, 
IOException {
+        try (SseEventSource eventSource = 
withNoReconnect(Type.EVENT_NOT_AUTHORIZED)) {
+            eventSource.open();
+            assertThat(eventSource.isOpen(), equalTo(false));
+            assertThat(errors.size(), equalTo(1));
+
+            // Allow the event processor to pull for events (150ms)
+            Thread.sleep(150L);
+        }
+        
+        assertThat(errors.size(), equalTo(1));
+        assertThat(events.size(), equalTo(0));
+    }
+
+    @Test
     public void testNoReconnectAndCloseTheStreamWhileEventIsBeingReceived() 
throws InterruptedException, IOException {
         try (SseEventSource eventSource = withNoReconnect(Type.BUSY)) {
             eventSource.open();
@@ -343,11 +376,8 @@ public class SseEventSourceImplTest {
         startServer(Type.NO_CONTENT, null);
         // Type.NO_SERVER
 
-        Type type = Type.BUSY;
-        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
-        sf.setAddress(LOCAL_ADDRESS + type.name());
-        sf.setServiceBean(new BusyEventServer());
-        SERVERS.put(type, sf.create());
+        startBusyServer(Type.BUSY);
+        startNotAuthorizedServer(Type.EVENT_NOT_AUTHORIZED);
 
         startServer(Type.EVENT, EVENT);
         startServer(Type.EVENT_JUST_DATA, EVENT_JUST_DATA);
@@ -358,6 +388,20 @@ public class SseEventSourceImplTest {
         startServer(Type.EVENT_BAD_NEW_LINES, EVENT_BAD_NEW_LINES);
     }
 
+    private static void startNotAuthorizedServer(Type type) {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setAddress(LOCAL_ADDRESS + type.name());
+        sf.setServiceBean(new ProtectedEventServer());
+        SERVERS.put(type, sf.create());
+    }
+
+    private static void startBusyServer(Type type) {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setAddress(LOCAL_ADDRESS + type.name());
+        sf.setServiceBean(new BusyEventServer());
+        SERVERS.put(type, sf.create());
+    }
+
     private static void startServer(Type type, String payload) {
         JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
         sf.setAddress(LOCAL_ADDRESS + type.name());
@@ -401,4 +445,12 @@ public class SseEventSourceImplTest {
         }
     }
 
+    public static class ProtectedEventServer {
+        @GET
+        @Produces(MediaType.SERVER_SENT_EVENTS)
+        public Response event() {
+            return Response.status(Status.UNAUTHORIZED).build();
+        }
+    }
+
 }

Reply via email to