-
-
Notifications
You must be signed in to change notification settings - Fork 564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interceptors Proposal #3614
Comments
I'm trying #3616. Is this possible? // Create interceptors
interceptors := &genservice.ServerInterceptors{
AuditInterceptor: AuditInterceptor,
RetryInterceptor: RetryInterceptor,
}
// Create endpoints with interceptors
endpoints := genservice.NewEndpoints(svc, interceptors) |
Good catch, that's not how interceptors ended up being implemented. Instead there is a single generated interface that exposes all the interceptors. The end user provides the implementation for this interface and Goa calls the right interceptors at the right time. I've added an example: https://github.com/goadesign/examples/tree/features/interceptors/interceptors. |
I'm working on adding streaming support for interceptors by adding |
Just to help with that: maybe you could create a branch in the goa.design/examples repo, add streaming endpoints to the interceptors example and write the code that should be generated. That way we can review what the output ought to be and the example can be used as a reference when working on the code generation. Also https://github.com/goadesign/goa/blob/v3/codegen/service/interceptors.md contains the details of how the current interceptors were implemented. |
In addition to adding the I also have a proposed addition to Clue of a generic interceptor for tracing individual messages on a stream with OpenTelemetry that works with Goa interceptors: goadesign/clue#520. |
I updated the proposal with the final design and implementation. |
Interceptors in Goa
Overview
This proposal introduces typed interceptors to Goa's design DSL. Interceptors provide a type-safe mechanism for injecting cross-cutting concerns into method execution. They support both server-side and client-side interception, with clean interfaces for reading and modifying payloads and results, including support for streaming operations.
Requirements
Design
DSL Example
The DSL allows developers to define interceptors with explicit read and write permissions for payloads and results. Here's an example showing different types of interceptors:
For streaming operations, the DSL provides additional constructs to handle streaming payloads and results:
Interceptors can be applied at both service and method levels:
Generated Code Structure and Implementation
Type-Safe Info Types
For each interceptor, Goa generates an Info type that provides context about the interception and safe access to the request data:
Accessor Interfaces
To ensure type-safe access to payload and result fields, Goa generates interfaces based on the read/write permissions defined in the design:
Private Implementation Types
The actual implementation of these interfaces is handled by private types that safely wrap the underlying data:
Interceptor Interfaces
Goa generates separate interfaces for server and client interceptors, each with the appropriate methods based on the design:
Code Generation and Implementation
The interceptor system is built using a set of template-driven code generators that work together to create a complete, type-safe interception framework. Let's walk through how this system works.
Generated Code Overview
At the heart of the system are three main types of generated code. First, the core interceptor interfaces are generated in separate files for client and server sides. These files define the fundamental contract that interceptors must implement, with distinct interfaces for client and server operations.
The second key component is the access types generation. This creates the interfaces and structs that enable safe access to payloads and results. Each interceptor gets its own Info struct that provides context about the current operation and safe access to request data. For example, a JWT authentication interceptor might get types like this:
Finally, endpoint wrapper code is generated to handle the actual interception chain. These wrappers manage the order of interceptor execution, context propagation, and error handling. They ensure that interceptors run in the correct sequence and that data flows properly through the system.
The Data Model
Code generation is driven by a hierarchical data model that captures the complete interceptor configuration. The model starts at the service level and drills down to individual fields:
This model drives the generation of type-safe interceptor code. For example, when defining a JWT authentication interceptor in the design:
Type Safety and Execution
The generated code creates a chain of type-safe interceptors. Here's how a server-side authentication and logging interceptor chain might look:
For streaming operations, special wrapper types maintain type safety throughout the stream's lifetime:
All of this machinery works together to provide a seamless interception system that's both powerful and safe to use. Developers can focus on implementing their interceptor logic while the generated code handles all the complexity of type safety, proper execution order, and data flow management.
Key Features
Type-Safe Access
Flexible Interception Points
Clean Integration
Comprehensive Features
The text was updated successfully, but these errors were encountered: