-
-
Notifications
You must be signed in to change notification settings - Fork 412
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
Client middleware #1720
Client middleware #1720
Conversation
Hi, thank you for this contribution! As this is a breaking change (adding a publicly exposed field to a record breaks pattern-matching in consumers) and not trivial addition, would you mind adding a changelog entry? :) |
@tchoutri |
@abailly May I ask for your opinion on this? |
@tchoutri Sure, always happy to help but it's been a while since I have used servant in anger :) |
This reverts commit d4f983f.
I also added a test for "chaining middleware". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change completely makes sense and I have often wanted to have that functionality available and, as the proposer, resorted to custom ClientM
or RunClient
implementations for purposes that could have been well served by a ClientMiddleware
like authentication, logging, etc.
I have made general suggestions which seem to make sense to me but might be inappropriate because of the coding conventions in force in the codebase, so take those with a grain of salt.
@abailly |
Looks like sqlite-simple-0.4.19.0 can't be compiled with GHC 8.6.5. Since it's an obsolete version it can be safely dropped from CI. |
At work we had the following requirement: Every endpoint call with servant-client should log it's raw request and response data.
At first, it looked like this may be possible to implement with
managerModifyRequest
andmanagerModifyResponse
.However, this turned out to be not a good idea. The docs itself mention for the first function that "This function may be called more than once during request processing". And generally it was important that the logging of the request and response happens at the exact time when they orccur. And those function don't seem to give guarantees about this.
In the end our solution was roughly to create a newtype wrapper around
ClientM
with a custom instance forRunClient
, which callsperformRequest
but wrapped with some middleware functions.I wonder if there could be a way to support defining "real" middleware of type
(Request -> ClientM Response) -> (Request -> ClientM Response)
in servant-client.This PR is an implementation sketch of how I'd imagine this to work. I contains a simple testcase which should clarify the main idea.
I'd be curious to hear what people think about this approach.
Note: This PR does not cover yet how errors thrown in the middleware should be handled. One way to do this would be to extend the
ClientError
type with a new constructorMiddlewareError SomeException
.