1
1
/*
2
2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
3
*
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.
5
5
*
6
6
* The contents of this file are subject to the terms of either the GNU
7
7
* General Public License Version 2 only ("GPL") or the Common Development
@@ -76,6 +76,7 @@ class InboundEventReader implements MessageBodyReader<InboundEvent> {
76
76
private Provider <MessageBodyWorkers > messageBodyWorkers ;
77
77
78
78
private enum State {
79
+ SKIPPING_PREPENDED_EMPTY_EVENTS ,
79
80
NEW_LINE ,
80
81
COMMENT ,
81
82
FIELD ,
@@ -106,10 +107,31 @@ public InboundEvent readFrom(final Class<InboundEvent> type,
106
107
new InboundEvent .Builder (messageBodyWorkers .get (), annotations , mediaType , headers );
107
108
108
109
int b = -1 ;
109
- State currentState = State .NEW_LINE ;
110
+ State currentState = State .SKIPPING_PREPENDED_EMPTY_EVENTS ;
110
111
loop :
111
112
do {
112
113
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 :
113
135
case NEW_LINE :
114
136
if (b == '\r' ) {
115
137
// read next byte in case of CRLF delimiter
@@ -120,6 +142,10 @@ public InboundEvent readFrom(final Class<InboundEvent> type,
120
142
}
121
143
122
144
if (b == '\n' || b == '\r' || b == -1 ) {
145
+ if (currentState == State .SKIPPING_PREPENDED_EMPTY_EVENTS ) {
146
+ break ;
147
+ }
148
+
123
149
break loop ;
124
150
}
125
151
0 commit comments