Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit ed55856

Browse files
author
Petr Janouch
committed
SSE Events following empty events not delivered to a client
Change-Id: I3c0024836f3f79d4f85d381d85c6dd70ca069ad3
1 parent da15f3a commit ed55856

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

media/sse/src/main/java/org/glassfish/jersey/media/sse/InboundEventReader.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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

media/sse/src/test/java/org/glassfish/jersey/media/sse/InboundEventReaderTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2015-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
@@ -84,14 +84,14 @@ public class InboundEventReaderTest {
8484
@Test
8585
public void testReadWithStartsWithLF() throws Exception {
8686
InboundEvent event = parse(new ByteArrayInputStream("\nevent: custom-message".getBytes()));
87-
assertNull(event.getName());
87+
assertEquals("custom-message", event.getName());
8888
assertEquals(0, event.getRawData().length);
8989
}
9090

9191
@Test
9292
public void testReadWithStartsWithCR() throws Exception {
9393
InboundEvent event = parse(new ByteArrayInputStream("\revent: custom-message".getBytes()));
94-
assertNull(event.getName());
94+
assertEquals("custom-message", event.getName());
9595
assertEquals(0, event.getRawData().length);
9696
}
9797

0 commit comments

Comments
 (0)