11/*
22 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33 *
4- * Copyright (c) 2012-2015 Oracle and/or its affiliates. All rights reserved.
4+ * Copyright (c) 2012-2016 Oracle and/or its affiliates. All rights reserved.
55 *
66 * The contents of this file are subject to the terms of either the GNU
77 * General Public License Version 2 only ("GPL") or the Common Development
@@ -76,6 +76,7 @@ class InboundEventReader implements MessageBodyReader<InboundEvent> {
7676 private Provider <MessageBodyWorkers > messageBodyWorkers ;
7777
7878 private enum State {
79+ SKIPPING_PREPENDED_EMPTY_EVENTS ,
7980 NEW_LINE ,
8081 COMMENT ,
8182 FIELD ,
@@ -106,10 +107,31 @@ public InboundEvent readFrom(final Class<InboundEvent> type,
106107 new InboundEvent .Builder (messageBodyWorkers .get (), annotations , mediaType , headers );
107108
108109 int b = -1 ;
109- State currentState = State .NEW_LINE ;
110+ State currentState = State .SKIPPING_PREPENDED_EMPTY_EVENTS ;
110111 loop :
111112 do {
112113 switch (currentState ) {
114+ /* There is a problem with the SSE event parsing, because Jersey uses ChunkedInput to separate events.
115+ The problem is that ChunkedInput uses fixed character string as a separator, which is \r\n\r\n when it
116+ parses SSE.
117+ The problem is that SSE events are separated only by \r\n and \r\n also works as an end of a field inside
118+ the event, so the fixed separator \r\n\r\n only works if the server does not send empty events.
119+ For example:
120+
121+ event: e1\r\n
122+ data: d1\r\n
123+ \r\n
124+ \r\n
125+ event: e2\r\n
126+ data: d2\r\n
127+ \r\n
128+
129+ is a stream of <e1> <empty event> <e2>
130+ Unfortunately the ChunkedInput parser will parse it only into 2 events <e1> and <e2> and <e2> will have
131+ \r\n (an empty event) prepended at the beginning. This is not fixable on the ChunkedInput parser level,
132+ which is not SSE aware, so this InboundEventReader must be aware of this and skip any prepended empty events.
133+ Also as a result Jersey will not deliver empty events to the user. */
134+ case SKIPPING_PREPENDED_EMPTY_EVENTS :
113135 case NEW_LINE :
114136 if (b == '\r' ) {
115137 // read next byte in case of CRLF delimiter
@@ -120,6 +142,10 @@ public InboundEvent readFrom(final Class<InboundEvent> type,
120142 }
121143
122144 if (b == '\n' || b == '\r' || b == -1 ) {
145+ if (currentState == State .SKIPPING_PREPENDED_EMPTY_EVENTS ) {
146+ break ;
147+ }
148+
123149 break loop ;
124150 }
125151
0 commit comments