@funduck/connectrpc-fastify 1.0.14 → 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ This library allows you to:
|
|
|
20
20
|
* Perform RPC with streaming responses
|
|
21
21
|
* Perform RPC with streaming requests
|
|
22
22
|
* Use middlewares with Fastify hooks
|
|
23
|
+
* Use interceptors for RPC-level request/response handling
|
|
23
24
|
* Access HandlerContext in controllers (headers, context values, etc.)
|
|
24
25
|
|
|
25
26
|
*Bidirectional streaming RPC is currently out of scope because it requires HTTP/2, which is unstable on public networks. In practice, HTTP/1 provides more consistent performance.*
|
|
@@ -116,6 +117,70 @@ ConnectRPC.initMiddlewares(fastify, [
|
|
|
116
117
|
await fastify.listen({ port: 3000 });
|
|
117
118
|
```
|
|
118
119
|
|
|
120
|
+
### Interceptors
|
|
121
|
+
Interceptors run at the RPC layer and have access to the full request/response context from ConnectRPC. They are executed after middlewares and before the controller method is called.
|
|
122
|
+
|
|
123
|
+
Interceptor must implement `Interceptor` interface and register itself with `ConnectRPC.registerInterceptor` in the constructor.
|
|
124
|
+
```TS
|
|
125
|
+
import { createContextKey } from '@connectrpc/connect';
|
|
126
|
+
import type { AnyFn, Interceptor } from '@funduck/connectrpc-fastify';
|
|
127
|
+
|
|
128
|
+
const reqIdKey = createContextKey('');
|
|
129
|
+
|
|
130
|
+
export class LoggingInterceptor implements Interceptor {
|
|
131
|
+
constructor() {
|
|
132
|
+
ConnectRPC.registerInterceptor(this);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
use(next: AnyFn): AnyFn {
|
|
136
|
+
return async (req) => {
|
|
137
|
+
// Access request information
|
|
138
|
+
console.log(`Method: ${req.method.name}`);
|
|
139
|
+
console.log(`Service: ${req.service.typeName}`);
|
|
140
|
+
|
|
141
|
+
// Access headers
|
|
142
|
+
const authHeader = req.header.get('authorization');
|
|
143
|
+
|
|
144
|
+
// Attach custom data to context
|
|
145
|
+
req.contextValues.set(reqIdKey, crypto.randomUUID());
|
|
146
|
+
|
|
147
|
+
// Continue with the request
|
|
148
|
+
return await next(req);
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Create an instance of the interceptor and initialize them using `ConnectRPC.init` method.
|
|
155
|
+
You can configure interceptors to run globally for all services and methods, for specific service only, or for specific method only.
|
|
156
|
+
For type safety use `interceptorConfig` helper.
|
|
157
|
+
```TS
|
|
158
|
+
import { interceptorConfig } from '@funduck/connectrpc-fastify';
|
|
159
|
+
|
|
160
|
+
const fastify = Fastify({ logger: true });
|
|
161
|
+
|
|
162
|
+
new AuthMiddleware();
|
|
163
|
+
new LoggingInterceptor();
|
|
164
|
+
new ElizaController();
|
|
165
|
+
|
|
166
|
+
await ConnectRPC.init(fastify, {
|
|
167
|
+
interceptors: [
|
|
168
|
+
interceptorConfig(LoggingInterceptor), // Global - for all services and methods
|
|
169
|
+
// interceptorConfig(LoggingInterceptor, ElizaService), // for all ElizaService methods
|
|
170
|
+
// interceptorConfig(LoggingInterceptor, ElizaService, ['say']), // for specific method only
|
|
171
|
+
],
|
|
172
|
+
middlewares: [
|
|
173
|
+
middlewareConfig(AuthMiddleware), // Global middleware
|
|
174
|
+
],
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
await fastify.listen({ port: 3000 });
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Key differences between Middlewares and Interceptors:**
|
|
181
|
+
- **Middlewares** run at the HTTP layer (Fastify hooks) with access to raw HTTP request/response objects
|
|
182
|
+
- **Interceptors** run at the RPC layer with access to parsed ConnectRPC request/response objects, typed method information, and can modify the request/response in the RPC context
|
|
183
|
+
|
|
119
184
|
## Using Context Values
|
|
120
185
|
This is original `ContextValues`, so you need to create context keys using `createContextKey` helper from Connectrpc.
|
|
121
186
|
```TS
|
|
@@ -140,5 +205,7 @@ To use context values in controller, retrieve them from `HandlerContext`.
|
|
|
140
205
|
const authValue = context.values.get(authKey);
|
|
141
206
|
```
|
|
142
207
|
|
|
208
|
+
**Note:** Context values set in middlewares are automatically available in interceptors and controllers. Interceptors can also access and modify context values using `req.contextValues`.
|
|
209
|
+
|
|
143
210
|
## Feedback
|
|
144
211
|
Please use [Discussions](https://github.com/funduck/connectrpc-fastify/discussions) or email me.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funduck/connectrpc-fastify",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"author": "Oleg Milekhin <qlfunduck@gmail.com>",
|
|
5
5
|
"description": "Wrapper for official @connectrpc/connect and fastify. Simplifies configuration, type safe binding to controller, simplifies use of middlewares and guards.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
33
33
|
"ts-jest": "^29.4.6",
|
|
34
34
|
"ts-node": "^10.9.2",
|
|
35
|
-
"typescript": "^5.9.3"
|
|
35
|
+
"typescript": "^5.9.3",
|
|
36
|
+
"reflect-metadata": "^0.2.2"
|
|
36
37
|
}
|
|
37
38
|
}
|