Skip to content

Commit 32574ec

Browse files
committed
Add extra grpc header which is all lower case
According to https://httpwg.org/specs/rfc7540.html#HttpHeaders headers in HTTP/2 (grpc transport) must all be lower case. Thus, using A2A via grpc fails when using the HTTP header. Add specific all lowercase header for gRPC.
1 parent 8b647bd commit 32574ec

3 files changed

Lines changed: 15 additions & 14 deletions

File tree

src/a2a/extensions/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55

66
HTTP_EXTENSION_HEADER = 'X-A2A-Extensions'
7+
GRPC_EXTENSION_HEADER = 'x-a2a-extensions'
78

89

910
def get_requested_extensions(values: list[str]) -> set[str]:

src/a2a/server/request_handlers/grpc_handler.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from a2a import types
2424
from a2a.auth.user import UnauthenticatedUser
2525
from a2a.extensions.common import (
26-
HTTP_EXTENSION_HEADER,
26+
GRPC_EXTENSION_HEADER,
2727
get_requested_extensions,
2828
)
2929
from a2a.grpc import a2a_pb2
@@ -76,7 +76,7 @@ def build(self, context: grpc.aio.ServicerContext) -> ServerCallContext:
7676
user=user,
7777
state=state,
7878
requested_extensions=get_requested_extensions(
79-
_get_metadata_value(context, HTTP_EXTENSION_HEADER)
79+
_get_metadata_value(context, GRPC_EXTENSION_HEADER)
8080
),
8181
)
8282

@@ -417,7 +417,7 @@ def _set_extension_metadata(
417417
if server_context.activated_extensions:
418418
context.set_trailing_metadata(
419419
[
420-
(HTTP_EXTENSION_HEADER.lower(), e)
420+
(GRPC_EXTENSION_HEADER.lower(), e)
421421
for e in sorted(server_context.activated_extensions)
422422
]
423423
)

tests/server/request_handlers/test_grpc_handler.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pytest
66

77
from a2a import types
8-
from a2a.extensions.common import HTTP_EXTENSION_HEADER
8+
from a2a.extensions.common import GRPC_EXTENSION_HEADER
99
from a2a.grpc import a2a_pb2
1010
from a2a.server.context import ServerCallContext
1111
from a2a.server.request_handlers import GrpcHandler, RequestHandler
@@ -350,8 +350,8 @@ async def test_send_message_with_extensions(
350350
mock_grpc_context: AsyncMock,
351351
) -> None:
352352
mock_grpc_context.invocation_metadata.return_value = grpc.aio.Metadata(
353-
(HTTP_EXTENSION_HEADER.lower(), 'foo'),
354-
(HTTP_EXTENSION_HEADER.lower(), 'bar'),
353+
(GRPC_EXTENSION_HEADER.lower(), 'foo'),
354+
(GRPC_EXTENSION_HEADER.lower(), 'bar'),
355355
)
356356

357357
def side_effect(request, context: ServerCallContext):
@@ -379,8 +379,8 @@ def side_effect(request, context: ServerCallContext):
379379
mock_grpc_context.set_trailing_metadata.call_args.args[0]
380380
)
381381
assert set(called_metadata) == {
382-
(HTTP_EXTENSION_HEADER.lower(), 'foo'),
383-
(HTTP_EXTENSION_HEADER.lower(), 'baz'),
382+
(GRPC_EXTENSION_HEADER.lower(), 'foo'),
383+
(GRPC_EXTENSION_HEADER.lower(), 'baz'),
384384
}
385385

386386
async def test_send_message_with_comma_separated_extensions(
@@ -390,8 +390,8 @@ async def test_send_message_with_comma_separated_extensions(
390390
mock_grpc_context: AsyncMock,
391391
) -> None:
392392
mock_grpc_context.invocation_metadata.return_value = grpc.aio.Metadata(
393-
(HTTP_EXTENSION_HEADER.lower(), 'foo ,, bar,'),
394-
(HTTP_EXTENSION_HEADER.lower(), 'baz , bar'),
393+
(GRPC_EXTENSION_HEADER.lower(), 'foo ,, bar,'),
394+
(GRPC_EXTENSION_HEADER.lower(), 'baz , bar'),
395395
)
396396
mock_request_handler.on_message_send.return_value = types.Message(
397397
message_id='1',
@@ -415,8 +415,8 @@ async def test_send_streaming_message_with_extensions(
415415
mock_grpc_context: AsyncMock,
416416
) -> None:
417417
mock_grpc_context.invocation_metadata.return_value = grpc.aio.Metadata(
418-
(HTTP_EXTENSION_HEADER.lower(), 'foo'),
419-
(HTTP_EXTENSION_HEADER.lower(), 'bar'),
418+
(GRPC_EXTENSION_HEADER.lower(), 'foo'),
419+
(GRPC_EXTENSION_HEADER.lower(), 'bar'),
420420
)
421421

422422
async def side_effect(request, context: ServerCallContext):
@@ -450,6 +450,6 @@ async def side_effect(request, context: ServerCallContext):
450450
mock_grpc_context.set_trailing_metadata.call_args.args[0]
451451
)
452452
assert set(called_metadata) == {
453-
(HTTP_EXTENSION_HEADER.lower(), 'foo'),
454-
(HTTP_EXTENSION_HEADER.lower(), 'baz'),
453+
(GRPC_EXTENSION_HEADER.lower(), 'foo'),
454+
(GRPC_EXTENSION_HEADER.lower(), 'baz'),
455455
}

0 commit comments

Comments
 (0)