-
-
Notifications
You must be signed in to change notification settings - Fork 746
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
feature: Allow decoration of interface methods to be used by DelegatingHandlers #1156
Comments
Hmm... I currently solve exactly this problem today using https://github.com/App-vNext/Polly which in behind the scenes actually leverages DelegatingHandlers to do its magic. I have some endpoints in a 3rd party API I need to integrate with that have different needs with respect to when/what to retry on, and I simply grouped stuff with the same needs into one Refit client, and grouped stuff with a different set of needs into a different Refit client, and then applied the appropriate Polly policies to each Refit client separately. That worked pretty well. As for adding a new attribute, the additional complexity and effort required to add a new attribute is kind of high in conjunction with that not really being a very intuitive programming model, so I wouldn't think that's the right way to solve it. Adding MethodInfo into HttpRequestMessage.Properties/Options is potentially a better solution, as the InterfaceName is already always added there, but I would be a little bit wary of including it that entire object. To be honest I'm not even really a fan of including the interface name by default, as I think it would be better if Refit didn't have any strong opinion about what winds up in HttpRequestMessage.Properties by default as there could well be other DelegatingHandlers that we have no knowledge of that could behave in unexpected ways if we populate data into that willy nilly. For example in my case I use a DelegatingHandler to log the request/response payloads to Serilog. This includes logging the contents of HttpRequestMessage.Properties as that's where Polly stores the PollyContext which can be used for example to populate the number of retries a request has made etc. It'd be fairly nasty if Refit suddenly had the opinion that the entire object graph of MethodInfo should also be serialized into my logs. I mean, I could obviously work around that, but it's still not super nice and could very well introduce subtle and annoying bugs for consumers of the library. I do think it's an interesting use case and warrants more thought on a design that enables the kinds of extension that you want to do, as I think fundamentally that's quite worthwhile. A couple of thoughts come to mind. First off, I would only really want to see something appearing in HttpRequestMessage.Properties on a purely opt-in basis. With the right design I think that can be accomplished. Second would be doing it in a way that opened up a whole class of extensions that provides a very low friction way to annotate a method with your own custom attribute and then have access to that information inside your delegating handler. What springs to mind is something more along the lines of adding a base class attribute that you subclass and annotate your method with and then when we build the request in Refit we could inspect the custom attributes and dump those particular ones into HttpRequestMessage.Properties using a particular key like "RefitCustomAttributes" or something like this. I almost think we don't even need a base class. Just get the custom attributes and if it's not one that is part of the Refit code base, simply populate it into HttpRequestMessage.Properties with the key being the name of custom attribute. Or something like that. I think that could be quite a neat way to be able to declaratively pass through information to DelegatingHandlers without adding too much complexity or giving Refit too strong an opinion on what winds up in HttpRequestMessage.Properties.
|
Alternatively, as a thought... similar to how we have an ExceptionFactoryProvider that allows you to splice in custom behavior regarding what happens in certain error scenarios, it could be incredibly powerful to allow a PropertyFactoryProvider which allows simply hands you the |
Polly is a pretty flexible library, and it has support for Either way I'm pretty keen on the PropertyFactoryProvider idea as I think that's a real enabler of many use cases we can't anticipate and if you can splice in behavior you need to solve a problem and unblock yourself that's a plus in my book. |
I like the idea of |
I second that allowing users to extend Refit would be great. We also has the requirement of passing constant values to |
@lostincomputer working on a PR right now. Almost finished. |
@dejvid-smth / @lostincomputer PR for this is here #1180 Would be excellent to see this merged. More or less you would just have to do this:
Game changer. |
Problem:
I want to be able to make decisions in
DelegatingHandler
based on the clientinterface method being executed.
Specifically I want to apply retry logic to some requests. I would like to be able
to have one
DelegatingHandler
type for that and be able to somehow markinterface methods where retry should be allowed. Deciding only based on request
method is not enough.
Describe the solution you'd like
One possible solution is to add another property to
HttpRequestMessage.Properties/Options
that would contain
MethodInfo
of the method. Then I could define custom attribute that canmark methods where retry is enabled and my
DelegatingHandler
could look for that attribute.Another solution could be to add a new attribute like
ConstantProperty
that could be usedon method. It would work like existing
PropertyAttribute
with the difference that the valueof the property would be specified in constructor and would be constant. Again, I could look
for that property in the
DelegatingHandler
Describe alternatives you've considered
I don't really see how could this be done today in a clean way. The only way to pass additional
information to
DelegatingHandler
is throughPropertyAttribute
but that requires addingmethod parameter which is not right. Caller shouldn't have to pass another value to each
method to manage how the client works internally.
Additional context
#1150 seems like similar request
The text was updated successfully, but these errors were encountered: