Skip to content

feat: server middleware API - #63

Merged
yarolegovich merged 39 commits into
mainfrom
yarolegovich/call-ctx-api
Oct 28, 2025
Merged

feat: server middleware API#63
yarolegovich merged 39 commits into
mainfrom
yarolegovich/call-ctx-api

Conversation

@yarolegovich

@yarolegovich yarolegovich commented Oct 9, 2025

Copy link
Copy Markdown
Member

Details

Changes in the a2asrv package required for providing extensions and auth support.

CallContext

CallContext struct can be accessed using CallContextFrom(context.Context) and will hold the following information:

  • RequestMeta immutable struct used for accessing data like headers, signatures, etc. Lookups are case-insensitive.
  • activatedExtensions. This list should be updated by extension implementers using CallContext.Activate(self).
  • User interface which holds auth-related information. It's an interface to allow passing custom types here.
  • Method name. Can be used call-specific request/response handling.

Transport implementations can pass RequestMeta by using ctx, callCtx := WithCallContext(ctx, toRequestMeta(transportSpecificMeta)). The returned callCtx can be used to examine which extensions were activated during request processing.

Some transports might decide whether to attach activated extensions to a response. SSE for example requires headers to be passed before the first response chunk. gRPC attaches extensions as a metadata trailer.

CallInterceptor

CallInterceptor API-wise is similar to a2aclient.CallInterceptor. Before and After methods can be used to observe, reject or modify requests and responses.
CallContext is passed to these methods explicitly because interceptors will likely be often used for extensions and auth.

InterceptedHandler

InterceptedHandler implements RequestHandler and helps to ensure correct interceptor invocations without the need to track early returns (something we would need to do if integrating interceptors into the defaultRequestHandler). It is exported so that SDK user can use it to add interceptor functionality to their RequestHandler implementation if a custom one is used.

@yarolegovich
yarolegovich marked this pull request as ready for review October 9, 2025 13:27
@yarolegovich
yarolegovich force-pushed the yarolegovich/call-ctx-api branch from b6fe833 to c6bbb24 Compare October 9, 2025 13:34
@yarolegovich

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a server-side middleware API, including support for call interceptors, which is a valuable addition for enhancing extensibility with features like authentication and logging. The implementation is generally robust, featuring a well-designed CallContext and a thorough test suite. My review highlights a few areas for improvement: a bug in the execution order of interceptors, significant code duplication that could be refactored for better maintainability, and a minor code cleanup. I have also suggested an additional test case to ensure the interceptor contract is fully verified.

Comment thread a2asrv/intercepted_handler.go Outdated
Comment thread a2asrv/auth.go Outdated
Comment thread a2asrv/intercepted_handler.go
Comment thread a2asrv/intercepted_handler_test.go
Base automatically changed from yarolegovich/req-ctx-loading to main October 21, 2025 14:29
Comment thread a2asrv/auth.go Outdated
@yarolegovich
yarolegovich merged commit 738bf85 into main Oct 28, 2025
4 checks passed
@yarolegovich
yarolegovich deleted the yarolegovich/call-ctx-api branch October 28, 2025 15:43
yarolegovich added a commit that referenced this pull request Oct 28, 2025
The integration code for server middleware added in #63:
* `a2asrv.WithCallInterceptor` option.
* `a2agrpc.Handler` support of metadata conversion.
pull Bot pushed a commit to joshuafuller/a2a-go that referenced this pull request Nov 4, 2025
🤖 I have created a release *beep* *boop*
---


## 0.3.0 (2025-11-04)


### Features

* add JSON-RPC client transport implementation
([#79](a2aproject#79))
([1690088](a2aproject@1690088))
* agent card resolver
([#48](a2aproject#48))
([0951293](a2aproject@0951293))
* blocking flag handling
([#97](a2aproject#97))
([f7aa465](a2aproject@f7aa465)),
closes [#96](a2aproject#96)
* client API proposal
([#32](a2aproject#32))
([b6ca54f](a2aproject@b6ca54f))
* client auth interceptor
([#90](a2aproject#90))
([25b9aae](a2aproject@25b9aae))
* client interceptor invocations
([#51](a2aproject#51))
([3e9f2ae](a2aproject@3e9f2ae))
* core types JSON codec
([#42](a2aproject#42))
([c5b3982](a2aproject@c5b3982))
* define core types and interfaces
([#16](a2aproject#16))
([69b96ea](a2aproject@69b96ea))
* disallow custom types and circular refs in Metadata
([#43](a2aproject#43))
([53bc928](a2aproject@53bc928))
* get task implementation
([#59](a2aproject#59))
([f74d854](a2aproject@f74d854))
* grpc authenticated agent card and producer utils
([#85](a2aproject#85))
([9d82f31](a2aproject@9d82f31)),
closes [#82](a2aproject#82)
* grpc client transport
([#66](a2aproject#66))
([fee703e](a2aproject@fee703e))
* grpc code generation from A2A .proto spec
([#11](a2aproject#11))
([2993b98](a2aproject@2993b98))
* handling artifacts and implementing send message stream
([#52](a2aproject#52))
([c3fa631](a2aproject@c3fa631))
* implement an a2aclient.Factory
([#50](a2aproject#50))
([49deee7](a2aproject@49deee7))
* implementing grpc server wrapper
([#37](a2aproject#37))
([071e952](a2aproject@071e952))
* implementing message-message interaction
([#34](a2aproject#34))
([b568979](a2aproject@b568979))
* implementing task pushes
([#86](a2aproject#86))
([c210240](a2aproject@c210240))
* input-required and auth-required handling
([#70](a2aproject#70))
([3ac89ba](a2aproject@3ac89ba))
* jsonrpc server ([#91](a2aproject#91))
([5491030](a2aproject@5491030))
* logger ([#56](a2aproject#56))
([86ab9d2](a2aproject@86ab9d2))
* request context loading
([#60](a2aproject#60))
([ab7a29b](a2aproject@ab7a29b))
* result aggregation part 1 - task store
([#38](a2aproject#38))
([d3c02f5](a2aproject@d3c02f5))
* result aggregation part 3 - concurrent task executor
([#40](a2aproject#40))
([265c3e7](a2aproject@265c3e7))
* result aggregation part 4 - integration
([#41](a2aproject#41))
([bab72d9](a2aproject@bab72d9))
* SDK type utilities
([#31](a2aproject#31))
([32b77b4](a2aproject@32b77b4))
* server middleware API
([#63](a2aproject#63))
([738bf85](a2aproject@738bf85))
* server middleware integration
([#64](a2aproject#64))
([5dc8be0](a2aproject@5dc8be0))
* smarter a2aclient
([#88](a2aproject#88))
([322d05b](a2aproject@322d05b))
* task event factory
([#95](a2aproject#95))
([fbf3bcf](a2aproject@fbf3bcf)),
closes [#84](a2aproject#84)
* task executor docs
([#36](a2aproject#36))
([b6868df](a2aproject@b6868df))
* task update logic
([0ac987f](a2aproject@0ac987f))


### Bug Fixes

* Execute() callers missing events
([#74](a2aproject#74))
([4c3389f](a2aproject@4c3389f))
* mark task failed when execution fails
([#94](a2aproject#94))
([ee0e7ed](a2aproject@ee0e7ed))
* push semantics update
([#93](a2aproject#93))
([76bff9f](a2aproject@76bff9f))
* race detector queue closed access
([c07b7d0](a2aproject@c07b7d0))
* regenerate proto and update converters
([#81](a2aproject#81))
([c732060](a2aproject@c732060))
* streaming ([#92](a2aproject#92))
([ca7a64b](a2aproject@ca7a64b))


### Miscellaneous Chores

* release 0.3.0
([fa7cfba](a2aproject@fa7cfba))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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.

2 participants