Reputation: 103
Am having a bit of trouble understanding how to pass encoded data in a request using flurl. We have an api that looks like:
https://servicename.com/domain/api/{identifier}?parameter=value
And in some specific cases we have identifiers which contain a forward-slash /
We are building the request using the following code:
var clientRequest = this.configuration.Client
.Request(this.configuration.RequestPath)
.AppendPathSegment(identifier)
.WithHeader("Requesting-System", "api");
And we call it using:
using (var response = await clientRequest.GetAsync(cancellationToken))
{
return await response.Content.ReadAsStringAsync();
}
Now. Taking the straightforward approach of just passing in the identifier with the forward-slash; let's say abc/123. The above code generates a clientRequest with a path of
https://servicename.com/domain/api/abc/123?parameter=value
Which, expectedly, fails with a 400 error. So the solution for this, based on our api specifications, is to encode the forward-slash as %2F, and pass that in the url. Thankfully, Flurl makes this pretty easy in theory by allowing an optional parameter in the AppendPathSegment method, which will cause the encoding. So we amend the above to use
.AppendPathSegment(identifier, true)
Which generates a clientRequest with a path of
https://servicename.com/domain/api/abc%2F123?parameter=value
Exactly what I'd expect to see. If I call to this URL using postman, then I can see the correct response that I'm expecting from the API.
However, when I call it using the GetAsync method (same as above), then I still receive the 400 Sub-Resource not recognised error; and in my logs I can see that the actual request was made to
https://servicename.com/domain/api/abc/123?parameter=value
Is there a point during the service call that Flurl decodes the url string? If so, how do I pass the %2F in?
Have tried double-encoding, so that the request contains the identifier abc%252F123. Given the above, I would have expected this to be decoded to abc%2F123, which will then be sent to our API. But in this case no decoding takes place, and the request url is
https://servicename.com/domain/api/abc%252F123?parameter=value
Many thanks in advance for the help.
Upvotes: 0
Views: 1929
Reputation: 39319
This appears to be a bug or quirk (depending on who you ask) with System.Uri
, which HttpClient
uses deep down in the call stack. The work-around is to add this to app.config or web.config:
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
All credit for this goes to this answer.
If at all possible, I'd avoid allowing reserved URL characters in your identifiers in the first place. It just seems to be inviting quirks. If that's not possible, perhaps come up with your own escape sequence to represent forward slashes.
Upvotes: 1