Skip to content

Commit 4ef70f4

Browse files
authored
Avoid escaping headers in CONNECT frame (#37)
1 parent ef3fb5b commit 4ef70f4

File tree

4 files changed

+13
-4
lines changed

4 files changed

+13
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ Also, I want to pointed out that:
138138

139139
- Protocol parsing is inspired by [aiostomp](https://github.com/pedrokiefer/aiostomp/blob/3449dcb53f43e5956ccc7662bb5b7d76bc6ef36b/aiostomp/protocol.py) (meaning: consumed by me and refactored from).
140140
- stompman is tested and used with [Artemis ActiveMQ](https://activemq.apache.org/components/artemis/).
141+
- Specification says that headers in CONNECT and CONNECTED frames shouldn't be escaped for backwards compatibility. stompman doesn't escape headers in CONNECT frame (outcoming), but does not unescape headers in CONNECTED (outcoming).
141142

142143
## No docs
143144

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ services:
1414
image: apache/activemq-artemis:2.34.0-alpine
1515
environment:
1616
ARTEMIS_USER: admin
17-
ARTEMIS_PASSWORD: =123
17+
ARTEMIS_PASSWORD: ":=123"
1818
ports:
1919
- 8161:8161
2020
- 61616:61616

stompman/serde.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,16 @@ def dump_header(key: str, value: str) -> bytes:
8080

8181

8282
def dump_frame(frame: AnyClientFrame | AnyServerFrame) -> bytes:
83+
sorted_headers = sorted(frame.headers.items())
84+
dumped_headers = (
85+
(f"{key}:{value}\n".encode() for key, value in sorted_headers)
86+
if isinstance(frame, ConnectFrame)
87+
else (dump_header(key, cast(str, value)) for key, value in sorted_headers)
88+
)
8389
lines = (
8490
FRAMES_TO_COMMANDS[type(frame)],
8591
NEWLINE,
86-
*(dump_header(key, cast(str, value)) for key, value in sorted(frame.headers.items())),
92+
*dumped_headers,
8793
NEWLINE,
8894
frame.body if isinstance(frame, FRAMES_WITH_BODY) else b"",
8995
NULL,

tests/integration.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
pytestmark = pytest.mark.anyio
2626

2727
CONNECTION_PARAMETERS: Final = stompman.ConnectionParameters(
28-
host=os.environ["ARTEMIS_HOST"], port=61616, login="admin", passcode="%3D123"
28+
host=os.environ["ARTEMIS_HOST"], port=61616, login="admin", passcode=":=123"
2929
)
3030

3131

@@ -163,9 +163,11 @@ def bytes_not_contains(*avoided: bytes) -> Callable[[bytes], bool]:
163163
if (parsed_header := parse_header(bytearray(header)))
164164
)
165165
)
166+
167+
FRAMES_WITH_ESCAPED_HEADERS = tuple(command for command in COMMANDS_TO_FRAMES if command != b"CONNECT")
166168
frame_strategy = strategies.just(HeartbeatFrame()) | strategies.builds(
167169
make_frame_from_parts,
168-
command=strategies.sampled_from(tuple(COMMANDS_TO_FRAMES.keys())),
170+
command=strategies.sampled_from(FRAMES_WITH_ESCAPED_HEADERS),
169171
headers=headers_strategy,
170172
body=strategies.binary().filter(bytes_not_contains(NULL)),
171173
)

0 commit comments

Comments
 (0)