refit
refit copied to clipboard
Refit requires base address of supplied HttpClient to not end with a slash
TL;DR:
It is unnecessarily difficult to have the same HttpClient
configuration for manual use and for use by Refit.
Refit requires the HttpClient
base address to have no trailing slash, while manual use requires that there be a slash.
Am I missing something? Is that something that could be "fixed"?
--
Original description:
I have a project where my HTTP clients are configured through the mechanisms provided by HttpClientFactory. They get policies and handlers assigned to them and I want to use that configuration everywhere.
For most endpoints, I use Refit which gets its HttpClient
supplied by the factory, but for some complex scenarios, I have to use the HttpClient directly without Refit.
My base address is in the form of http://example.com/api/
. The trailing slash is required for using HttpClient
directly, otherwise it will ignore the api
segment when forming the complete URL.
Refit seems to not play nice with that. Instead of working in harmony with that behavior, it tries to work around it. I can see in BuildVoidTaskFuncForMethod
that it takes the base path from the HttpClient
's base address in order to prepend it itself to the "relative path" in RequestBuilderImplementation.BuildRequestFactoryForMethod
. In that prepending, it expects that the base path not end with a slash, and has logic to remove the slash in the case that the base path is the root:
var urlTarget = (basePath == "/" ? string.Empty : basePath) + restMethod.RelativePath;
That "relative path" in RestMethodInfo.RelativePath
is enforced to start with a slash, despite the fact that by most if not all familiar conventions, a path that starts with a slash is supposed to be absolute.
Now if Refit creates the HttpClient
itself, then it will remove the trailing slash from the base address that it supplies to the HttpClient
, so that when it is used, it will forego the base path which has been "manually" prepended to the relative path by Refit.
However if the HttpClient
was supplied to Refit, then it has no control over the base address, and if that base address has a trailing slash, then there will be a double slash in the URL: http://example.com/api//my-resource
-
What is the best way of reconciling the direct use of
HttpClient
with using Refit on top, when the base address has a path after the domain? -
Why wasn't Refit designed to take actual relative paths (not starting with a slash) for the endpoint paths? Those slashes seem to be the source of the conflict in behavior with plain
HttpClient
. Would it be possible to add a configuration option to switch that behavior?
I've updated the title and description, hopefully someone will react to this ticket. I currently have to register 2 configurations of HttpClient
for the same endpoints because of that.
To add onto this, this behavior violates RFC 3986. From section 5.2.3:
5.2.3. Merge Paths The pseudocode above refers to a "merge" routine for merging a relative-path reference with the path of the base URI. This is accomplished as follows: o If the base URI has a defined authority component and an empty path, then return a string consisting of "/" concatenated with the reference's path; otherwise, o return a string consisting of the reference's path component appended to all but the last segment of the base URI's path (i.e., excluding any characters after the right-most "/" in the base URI path, or excluding the entire base URI path if it does not contain any "/" characters).
If documentation for C#'s Uri constructor says (and does) the same thing.
It'd be great if Refit was RFC compliant. It's causing me similar issues to the OP in my work.