Skip to content

Fix inline redis protocol consuming HTTP/2 connection preface (#3109)#3338

Open
rajvarun77 wants to merge 1 commit into
apache:masterfrom
rajvarun77:fix-redis-inline-protocol-h2-preface
Open

Fix inline redis protocol consuming HTTP/2 connection preface (#3109)#3338
rajvarun77 wants to merge 1 commit into
apache:masterfrom
rajvarun77:fix-redis-inline-protocol-h2-preface

Conversation

@rajvarun77

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: #3109

Problem Summary:

Inline redis protocol support (#3024) accepts any alpha-leading line as an inline command. The HTTP/2 client connection preface (PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n) is alpha-leading, so RedisCommandParser::ConsumeImpl parsed it as an inline command (first token PRI) and returned PARSE_OK instead of PARSE_ERROR_TRY_OTHERS.

As a result, protocol auto-detection in InputMessenger never fell through to the HTTP/2 handler, and a gRPC client calling a brpc server with redis_service enabled failed with:

code = Unavailable desc = connection closed before server preface received

What is changed and the side effects?

Changed:

  • In the inline branch of RedisCommandParser::ConsumeImpl (src/brpc/redis_command.cpp), detect the HTTP/2 connection preface — both a full match and a not-yet-complete prefix — and return PARSE_ERROR_TRY_OTHERS, leaving the buffer untouched so detection falls through to the HTTP/2 protocol.
  • The check is gated on the first byte ('P') to avoid overhead on normal inline commands.

Why match the preface rather than blacklist command names: some HTTP methods are also valid redis commands (e.g. GET), so a name-based blacklist is inherently ambiguous. The HTTP/2 preface is a fixed magic string that no redis command begins with, so matching it is unambiguous and has no false positives (no redis command starts with PR…).

  • Added RedisTest.inline_does_not_eat_h2_preface (test/brpc_redis_unittest.cpp) covering: the full preface → TRY_OTHERS; a partial prefix → TRY_OTHERS; and a genuine inline command sharing the leading byte (PING) → PARSE_OK.

Side effects:

  • Performance effects: negligible — one extra first-byte comparison per inline command, and a short memcmp only when it is 'P'.

…#3109)

Inline redis protocol support (apache#3024) accepts any alpha-leading line as
an inline command. The HTTP/2 client connection preface
("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n") is alpha-leading, so it was parsed
as an inline command instead of returning PARSE_ERROR_TRY_OTHERS. This
prevented protocol auto-detection from falling through to HTTP/2, and
gRPC clients calling a server with redis_service enabled failed with
"connection closed before server preface received".

Detect the HTTP/2 preface (fully, or as a not-yet-complete prefix) in
the inline branch of RedisCommandParser::ConsumeImpl and defer to other
protocols. A command-name blacklist is not viable because some HTTP
methods are also valid redis commands (e.g. GET), whereas the preface
is a fixed magic string that no redis command begins with, making the
check unambiguous.

Add RedisTest.inline_does_not_eat_h2_preface covering the full preface,
a partial prefix, and a genuine inline command sharing the leading byte.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant