Skip to content

Commit

Permalink
Fixes Issue #530 (#543)
Browse files Browse the repository at this point in the history
`ServerSentEventDecoder` was not ignoring whitespaces before the event name, this caused the event name to be invalid (since the parser only checks for the first character).

Now, ignoring all whitespaces before the event name.
  • Loading branch information
NiteshKant authored Aug 23, 2016
1 parent 1249344 commit 7f57b71
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ protected void decode(ChannelHandlerContext ctx, HttpContent httpContent, List<O
}
break;
}
/**
/*
* Since all data is read, reset the incomplete data to null. Release of this buffer happens in
* the following ways
* 1) If this was a data buffer, it is released when ServerSentEvent is released.
Expand All @@ -250,24 +250,26 @@ protected void decode(ChannelHandlerContext ctx, HttpContent httpContent, List<O
}

private static ServerSentEvent.Type readCurrentFieldTypeFromBuffer(final ByteBuf fieldNameBuffer) {
/**
/*
* This code tries to eliminate the need of creating a string from the ByteBuf as the field names are very
* constrained. The algorithm is as follows:
*
* -- Scan the bytes in the buffer.
* -- Ignore an leading whitespaces
* -- If the first byte matches the expected field names then use the matching field name char array to verify
* the rest of the field name.
* -- If the first byte does not match, reject the field name.
* -- After the first byte, exact match the rest of the field name with the expected field name, byte by byte.
* -- If the name does not exactly match the expected value, then reject the field name.
*/
ServerSentEvent.Type toReturn = ServerSentEvent.Type.Data;
skipLineDelimiters(fieldNameBuffer);
int readableBytes = fieldNameBuffer.readableBytes();
final int readerIndexAtStart = fieldNameBuffer.readerIndex();
char[] fieldNameToVerify = DATA_FIELD_NAME;
boolean verified = false;
int actualFieldNameIndexToCheck = 0; // Starts with 1 as the first char is validated by equality.
for (int i = readerIndexAtStart; i < readableBytes; i++) {
for (int i = readerIndexAtStart; i < readerIndexAtStart + readableBytes; i++) {
final char charAtI = (char) fieldNameBuffer.getByte(i);

if (i == readerIndexAtStart) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.logging.LoggingHandler;
import io.reactivex.netty.protocol.http.sse.ServerSentEvent;
import io.reactivex.netty.protocol.http.sse.ServerSentEvent.Type;
import org.junit.Test;

import java.util.ArrayList;
Expand Down Expand Up @@ -223,6 +224,24 @@ public void testDataInMultipleChunks() throws Exception {
doTest("\n", expected);
}

@Test(timeout = 10000)
public void testLeadingNewLineInFieldName() throws Exception {
List<Object> out = new ArrayList<>();
decoder.decode(ch, toHttpContent("\n data: ad\n"), out);
assertEquals("Unexpected number of decoded messages.", 1, out.size());
}

@Test(timeout = 10000)
public void testLeadingSpaceInFieldName() throws Exception {
List<Object> out = new ArrayList<>();
decoder.decode(ch, toHttpContent(" data: ad\n"), out);
assertEquals("Unexpected number of decoded messages.", 1, out.size());

ServerSentEvent event = (ServerSentEvent) out.get(0);
assertEquals("Unexpected event type.", Type.Data, event.getType());
assertEquals("Unexpected event type.", "ad", event.contentAsString());
}

private void doTest(String eventText, ServerSentEvent... expected) throws Exception {
List<Object> out = new ArrayList<>();
decoder.decode(ch, toHttpContent(eventText), out);
Expand Down

0 comments on commit 7f57b71

Please sign in to comment.