Validate if STOMP frame is allowed to have a body

Issue: SPR-10890
This commit is contained in:
Rossen Stoyanchev 2013-10-14 21:37:44 -04:00
parent 7c3749769a
commit 57d127b55a
5 changed files with 40 additions and 24 deletions

View File

@ -17,10 +17,9 @@
package org.springframework.messaging.simp.stomp; package org.springframework.messaging.simp.stomp;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.springframework.messaging.simp.SimpMessageType; import org.springframework.messaging.simp.SimpMessageType;
@ -51,36 +50,38 @@ public enum StompCommand {
RECEIPT, RECEIPT,
ERROR; ERROR;
private static Map<StompCommand, SimpMessageType> messageTypes = new HashMap<StompCommand, SimpMessageType>();
private static Map<StompCommand, SimpMessageType> messageTypeLookup = new HashMap<StompCommand, SimpMessageType>(); private static Collection<StompCommand> destinationRequired = Arrays.asList(SEND, SUBSCRIBE, MESSAGE);
private static Collection<StompCommand> subscriptionIdRequired = Arrays.asList(SUBSCRIBE, UNSUBSCRIBE, MESSAGE);
private static Set<StompCommand> destinationRequiredLookup = private static Collection<StompCommand> bodyAllowed = Arrays.asList(SEND, MESSAGE, ERROR);
new HashSet<StompCommand>(Arrays.asList(SEND, SUBSCRIBE, MESSAGE));
private static Set<StompCommand> subscriptionIdRequiredLookup =
new HashSet<StompCommand>(Arrays.asList(SUBSCRIBE, UNSUBSCRIBE, MESSAGE));
static { static {
messageTypeLookup.put(StompCommand.CONNECT, SimpMessageType.CONNECT); messageTypes.put(StompCommand.CONNECT, SimpMessageType.CONNECT);
messageTypeLookup.put(StompCommand.STOMP, SimpMessageType.CONNECT); messageTypes.put(StompCommand.STOMP, SimpMessageType.CONNECT);
messageTypeLookup.put(StompCommand.SEND, SimpMessageType.MESSAGE); messageTypes.put(StompCommand.SEND, SimpMessageType.MESSAGE);
messageTypeLookup.put(StompCommand.MESSAGE, SimpMessageType.MESSAGE); messageTypes.put(StompCommand.MESSAGE, SimpMessageType.MESSAGE);
messageTypeLookup.put(StompCommand.SUBSCRIBE, SimpMessageType.SUBSCRIBE); messageTypes.put(StompCommand.SUBSCRIBE, SimpMessageType.SUBSCRIBE);
messageTypeLookup.put(StompCommand.UNSUBSCRIBE, SimpMessageType.UNSUBSCRIBE); messageTypes.put(StompCommand.UNSUBSCRIBE, SimpMessageType.UNSUBSCRIBE);
messageTypeLookup.put(StompCommand.DISCONNECT, SimpMessageType.DISCONNECT); messageTypes.put(StompCommand.DISCONNECT, SimpMessageType.DISCONNECT);
} }
public SimpMessageType getMessageType() { public SimpMessageType getMessageType() {
SimpMessageType type = messageTypeLookup.get(this); SimpMessageType type = messageTypes.get(this);
return (type != null) ? type : SimpMessageType.OTHER; return (type != null) ? type : SimpMessageType.OTHER;
} }
public boolean requiresDestination() { public boolean requiresDestination() {
return destinationRequiredLookup.contains(this); return destinationRequired.contains(this);
} }
public boolean requiresSubscriptionId() { public boolean requiresSubscriptionId() {
return subscriptionIdRequiredLookup.contains(this); return subscriptionIdRequired.contains(this);
}
public boolean isBodyAllowed() {
return bodyAllowed.contains(this);
} }
} }

View File

@ -29,9 +29,9 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
/** /**
* A decoder for STOMP frames * A decoder for STOMP frames.
* *
* @author awilkinson * @author Andy Wilkinson
* @since 4.0 * @since 4.0
*/ */
public class StompDecoder { public class StompDecoder {
@ -60,8 +60,15 @@ public class StompDecoder {
MultiValueMap<String, String> headers = readHeaders(buffer); MultiValueMap<String, String> headers = readHeaders(buffer);
byte[] payload = readPayload(buffer, headers); byte[] payload = readPayload(buffer, headers);
decodedMessage = MessageBuilder.withPayload(payload).setHeaders( StompCommand stompCommand = StompCommand.valueOf(command);
StompHeaderAccessor.create(StompCommand.valueOf(command), headers)).build(); if ((payload.length > 0) && (!stompCommand.isBodyAllowed())) {
throw new StompConversionException(stompCommand +
" isn't allowed to have a body but has payload length=" + payload.length +
", headers=" + headers);
}
decodedMessage = MessageBuilder.withPayload(payload)
.setHeaders(StompHeaderAccessor.create(stompCommand, headers)).build();
} }
else { else {
decodedMessage = MessageBuilder.withPayload(HEARTBEAT_PAYLOAD).setHeaders( decodedMessage = MessageBuilder.withPayload(HEARTBEAT_PAYLOAD).setHeaders(

View File

@ -29,7 +29,7 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.simp.SimpMessageType; import org.springframework.messaging.simp.SimpMessageType;
/** /**
* An encoder for STOMP frames * An encoder for STOMP frames.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 4.0 * @since 4.0

View File

@ -20,12 +20,15 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException; import org.springframework.messaging.MessagingException;
/** /**
* An exception raised by {@link MessageConverter} implementations.
*
* @author Mark Fisher * @author Mark Fisher
* @since 4.0 * @since 4.0
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class MessageConversionException extends MessagingException { public class MessageConversionException extends MessagingException {
public MessageConversionException(String description, Throwable cause) { public MessageConversionException(String description, Throwable cause) {
super(description, cause); super(description, cause);
} }

View File

@ -133,6 +133,11 @@ public class StompCodecTests {
assertEquals("alpha:bravo\r\n\\", headers.getFirstNativeHeader("a:\r\n\\b")); assertEquals("alpha:bravo\r\n\\", headers.getFirstNativeHeader("a:\r\n\\b"));
} }
@Test(expected=StompConversionException.class)
public void decodeFrameBodyNotAllowed() {
decode("CONNECT\naccept-version:1.2\n\nThe body of the message\0");
}
@Test @Test
public void decodeMultipleFramesFromSameBuffer() { public void decodeMultipleFramesFromSameBuffer() {
String frame1 = "SEND\ndestination:test\n\nThe body of the message\0"; String frame1 = "SEND\ndestination:test\n\nThe body of the message\0";