-
Notifications
You must be signed in to change notification settings - Fork 424
Support for client interceptors #235
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
Comments
I like the concept! It reminds me of their server-side equivalent, which are called Middlewares in Swift-Vapor. In fact, my server-side request handlers are wrapped in a quick-and-dirty "middleware" call to log errors (just for illustration purposes):
A few remarks:
|
P.S.: not sure when SwiftNIO support for iOS is going to materialize, though, so this definitely has merit for the current implementation as well. |
Thanks for the feedback @MrMage! Item 1 Item 2 Item 3 Personally, I like the async approach to interceptors as opposed to the synchronous route. The primary reason I targeted a synchronous implementation was to try to provide a similar interface to what other gRPC language implementations do (like Java/PHP). I did notice that Go seems to have a different version that allows for multiple callbacks as streams continue, so it doesn't seem like consistency is a huge concern. If we're okay with being a little different, I'm definitely up for having Swift use an async approach and calling the interceptors as parts of RPC streams are sent/received. I can also update the proposal to flesh out the async design based on what's already there and the discussion from above if that's the direction we want to take. Thoughts? (Would also like to see what @timburks thinks of this.) Item 4 |
I think there are good reasons where you'd e.g. like to pass a parameter to an Interceptor, so I think you should be able to pass an Interceptor instance to the channel constructor. One Interceptor per channel is probably fine; I don't see why it should be different for each request.
I guess that would work, just wanted to point it out. Would you mind elaborating the kind of work Interceptors could perform on the request/response protos that are piped through them? At the moment, it feels like the proposal only describes intercepting call results, but not actual data. This makes me start to wonder whether we should instead indeed have a per-request interceptor (created e.g. via an interceptor factory) with an interface similar to this (just a very rough sketch):
Some notes on this:
I think in this case, async Interceptors with a callback are fine. We essentially just move from returning a result to sending the result in a callback, so it's not hugely different. We just need to document that the callback MUST be called.
The SwiftNIO implementation will most likely entirely be different from the current implementation, as that one is very much based on gRPC-Core and its approach. On the other hand, SwiftNIO for iOS is uncertain, so we would probably get by without interceptors in the NIO-based implementation early on anyway. |
Item 1
Sure, that's fair. My main concern with having a single interceptor instance per channel is that I've seen usages where the interceptor itself maintains some state based on the requests it's passed. Simple example of where having a single interceptor instance could be difficult: final class MyInterceptor {
private var analyticsEvent: SomeEvent?
func handleRequest(...) {
self.analyticsEvent = ...
}
func handleResponse(...) {
self.analyticsEvent.update(...)
// If this instance handles multiple requests, how do we track this one piece of state?
}
} Item 2
Based on these and my understanding of how interceptors in other languages have been implemented, it probably makes sense to stick to the catch-all approach for now though it could definitely be feasible to add request-specific interceptors if needed. Regarding the
Could you add some examples of how this would be used? Trying to visualize it a bit better. Items 3-4 make total sense 👍 |
Agreed, that's why I backtracked on that in my reply to item 2 :-)
Makes sense; let's not overcomplicate it. If users really want to, I suppose they could have their interceptor manually decode the proto data, modify it, then serialize it again. That way, we could have an interface like this (I think):
Scratch that, it would just overcomplicate things ;-) |
Sorry for the delayed response 😄looks like we're on the same page, though! I went ahead and updated the proposal document and split it into 2 implementation options (sync and async). Please take a look when you get a chance - the async approach is very similar to what we discussed above, with a few additional tweaks. Sounds like that's the approach both of us prefer at the moment. One note on the |
Looks good; I prefer the async approach (mostly looked at that one). A few remarks:
|
Good callouts, updated accordingly. Regarding the second point about canceling a request, I went with |
SGTM, we can still add it later on :-) |
@MrMage Is the interceptor or middleware functionality added in grpc for ios? |
No. |
The CgRPC implementation is now officially deprecated; closing this for now — we would probably want a new proposal for the |
@MrMage What should I do if I need the Client Interceptor to attach my JWT token with the metadata. |
We do not support client interceptors. You will need to create a metadata object containing the JWT token, then set that as the |
@MrMage Thank you for your help! I just need one more help "How can I do this with every request?" without manually setting the metadata object every time? Any workaround? |
As I said before, rest the metadata field on the entire service.
… On 24. Mar 2020, at 18:15, Varun Raj ***@***.***> wrote:
@MrMage Thank you for your help!
I just need one more help "How can I do this with every request?" without manually setting the metadata object every time? Any workaround?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Ohhh got this! Thanks! Take care man! |
Hey @MrMage , I just have one more questions I didn't find it anywhere. The situation is when the
Thanks in advance! |
Please don't mention me personally, this is a forum for everyone.
gRPC doesn't offer built-in support for that; you will need to manually fetch a new token, update the metadata, then send a new request with the new metadata. |
I've written up a proposal to add support for client interceptors here: https://github.com/grpc/grpc-swift/wiki/Interceptors-Proposal (feedback welcome!)
This issue should serve to track the status of that proposal and its implementation.
The text was updated successfully, but these errors were encountered: