From 833aab30007fa38130b659eef55b93de589c0334 Mon Sep 17 00:00:00 2001 From: "Mahlon E. Smith" Date: Sun, 4 Apr 2021 15:56:16 -0700 Subject: [PATCH] Fix value encoding to conform to spec. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Marcelo Módolo for the heads up. --- src/stomp.nim | 40 ++++++++++++++++++++++++++++------------ stomp.nimble | 2 +- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/stomp.nim b/src/stomp.nim index 26c8667..14b3e22 100644 --- a/src/stomp.nim +++ b/src/stomp.nim @@ -1,6 +1,6 @@ # vim: set et nosta sw=4 ts=4 ft=nim : # -# Copyright (c) 2016-2019, Mahlon E. Smith +# Copyright (c) 2016-2021, Mahlon E. Smith # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -102,6 +102,17 @@ type proc printf( formatstr: cstring ) {.header: "", varargs.} +proc encode( str: string ): string = + ## Encode value value strings per the "Value Encoding" section + ## of the Stomp 1.2 spec. + result = str + result = result. + replace( "\r", "\\r" ). + replace( "\n", "\\n" ). + replace( "\\", "\\\\" ). + replace( ":", "\\c" ) + + #------------------------------------------------------------------- # R E S P O N S E #------------------------------------------------------------------- @@ -270,7 +281,7 @@ proc newStompClient*( s: Socket, uri: string ): StompClient = ## .. code-block:: nim ## ## var socket = newSocket() - ## var stomp = newStompClient( socket, "stomp://test:test@example.com/%2Fvhost" ) + ## var stomp = newStompClient( socket, "stomp://test:test@example.com/vhost" ) ## ## or if connecting with SSL, when compiled with -d:ssl: ## @@ -279,7 +290,7 @@ proc newStompClient*( s: Socket, uri: string ): StompClient = ## var socket = newSocket() ## let sslContext = newContext( verifyMode = CVerifyNone ) ## sslContext.wrapSocket(socket) - ## var stomp = newStompClient( socket, "stomp+ssl://test:test@example.com/%2Fvhost" ) + ## var stomp = newStompClient( socket, "stomp+ssl://test:test@example.com/vhost" ) ## let @@ -327,7 +338,10 @@ proc newStompClient*( s: Socket, uri: string ): StompClient = result.port = Port( port ) # Decode URI encoded slashes for vhosts. - result.vhost = result.vhost.replace( "%2f", "/" ).replace( "%2F", "/" ).replace( "//", "/" ) + result.vhost = result.vhost. + replace( "%2f", "/" ). + replace( "%2F", "/" ). + replace( "//", "/" ) proc socksend( c: StompClient, data: string ): void = @@ -437,7 +451,7 @@ proc send*( c: StompClient, if not c.connected: raise newException( StompError, "Client is not connected." ) c.socksend( "SEND" & CRLF ) - c.socksend( "destination:" & destination & CRLF ) + c.socksend( "destination:" & destination.encode & CRLF ) c.socksend( "content-length:" & $message.len & CRLF ) if not ( contenttype == "" ): c.socksend( "content-type:" & contenttype & CRLF ) @@ -447,7 +461,7 @@ proc send*( c: StompClient, var txn_seen = false for header in headers: if header.name == "transaction": txn_seen = true - c.socksend( header.name & ":" & header.value & CRLF ) + c.socksend( header.name & ":" & header.value.encode & CRLF ) if not txn_seen: c.add_txn if message == "": @@ -473,7 +487,7 @@ proc subscribe*( c: StompClient, if not c.connected: raise newException( StompError, "Client is not connected." ) c.socksend( "SUBSCRIBE" & CRLF ) - c.socksend( "destination:" & destination & CRLF ) + c.socksend( "destination:" & destination.encode & CRLF ) if id == "": c.socksend( "id:" & $c.subscriptions.len & CRLF ) @@ -486,7 +500,7 @@ proc subscribe*( c: StompClient, if ack != "auto": raise newException( StompError, "Unknown ack type: " & ack ) for header in headers: - c.socksend( header.name & ":" & header.value & CRLF ) + c.socksend( header.name & ":" & header.value.encode & CRLF ) c.finmsg c.subscriptions.add( destination ) @@ -513,7 +527,7 @@ proc unsubscribe*( c: StompClient, c.socksend( "UNSUBSCRIBE" & CRLF ) c.socksend( "id:" & $sub_id & CRLF ) for header in headers: - c.socksend( header.name & ":" & header.value & CRLF ) + c.socksend( header.name & ":" & header.value.encode & CRLF ) c.finmsg c.subscriptions[ sub_id ] = "" @@ -707,7 +721,9 @@ You can also run a naive benchmark (deliveries/sec): It will set messages to require acknowledgement, and nack everything, causing a delivery loop for 10 seconds. -If your vhost requires slashes, use URI escaping: /%2Ftest + +With older version of RabbitMQ, If your vhost requires slashes, you'll +need to URI escape: /%2Ftest """ @@ -751,8 +767,8 @@ If your vhost requires slashes, use URI escaping: /%2Ftest of "RECEIPT": discard of "MESSAGE": - let body = r.payload - let id = r[ "ack" ] + discard r.payload + discard r[ "ack" ] proc seen_heartbeat( c: StompClient, r: StompResponse ) = heartbeats = heartbeats + 1 diff --git a/stomp.nimble b/stomp.nimble index 0376d0a..105edd0 100644 --- a/stomp.nimble +++ b/stomp.nimble @@ -1,7 +1,7 @@ # Package -version = "0.1.1" +version = "0.1.2" author = "Mahlon E. Smith " description = "A pure-nim implementation of the STOMP protocol for machine messaging." license = "MIT"