Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Refit supply a parameter in the query string automatically

Tags:

c#

.net

refit

I'm using Refit to generate a client for a web service.

All the URLs of my Web API are like this:

https://service.com/api/v3/datasets?api_key=XXXXXXX

As you see, the API key is specified in the query string instead of the header.

I would like Refit to supply my access token automatically as part of the query string without having to specify it in my service interface.

I've looked into the documentation, but I haven't found a way to do it.

like image 719
SuperJMN Avatar asked Feb 11 '20 17:02

SuperJMN


1 Answers

Finally, I created an HttpMessageHandler that intercepts the requests and injects the "api_key" in the querystring with the following code:

Service creation

service = RestService.For<IMyService>(new HttpClient(new QuerystringInjectingHttpMessageHandler(("api_key", token)))
    {
        BaseAddress = uri,
    });

Handler

public class QuerystringInjectingHttpMessageHandler : DelegatingHandler
{
    private readonly (string Key, string Value)[] injectedParameters;

    public QuerystringInjectingHttpMessageHandler(params (string key, string value)[] injectedParameters) : this()
    {
        this.injectedParameters = injectedParameters;
    }

    public QuerystringInjectingHttpMessageHandler() : base(new HttpClientHandler())
    {
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var finalUri = InjectIntoQuerystring(request.RequestUri, injectedParameters);

        request.RequestUri = finalUri;

        return base.SendAsync(request, cancellationToken);
    }

    private static Uri InjectIntoQuerystring(Uri uri, IEnumerable<(string Key, string Value)> parameters)
    {
        var uriStr = uri.ToString();

        var queryString = new string(uriStr.SkipWhile(c => c != '?').ToArray());
        var baseUri = uriStr.Substring(0, uriStr.Length - queryString.Length);
        var currentParameters = HttpUtility.ParseQueryString(queryString);

        foreach (var (key, value) in parameters)
        {
            currentParameters[key] = value;
        }

        var tuples = currentParameters.ToTuples();

        var newUri =
            string.Join("&", tuples.Select(tuple =>
            {
                if (tuple.name == null)
                {
                    return tuple.value;
                }

                return tuple.name + "=" + tuple.value;
            }));

        var suffix = newUri == "" ? "" : "?" + newUri;
        var finalUri = new Uri(baseUri + suffix);
        return finalUri;
    }
}

Extension

public static class Extensions
{
    public static IEnumerable<(string name, string value)> ToTuples(this NameValueCollection collection)
    {
        if (collection == null)
        {
            throw new ArgumentNullException("collection");
        }

        return
            from key in collection.Cast<string>()
            from value in collection.GetValues(key)
            select (key, value);
    }
}
like image 188
SuperJMN Avatar answered Sep 20 '22 03:09

SuperJMN