-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Use HttpClient instead of HttpWebRequest - breaking change #1406
Comments
The issue is larger, in that a new instance of I have opened an issue with .NET Core, but it seems unlikely they are going to fix despite it being a minor change. Reference Issue: dotnet/runtime#1812. |
I'd love to see RestSharp get this update. @alexeyzimarev, please reach out if there's any questions on |
I would also like to vouch for enabling the injection of an HttpClient into an IRestClient, so that we can use the clients that are being set up by
|
@TeunKooijman it won't be that straightforward. As part of the If we allow setting the |
Hello, friend, how is it going? |
Hi @alexeyzimarev, I wanted to know the progress of introducing to use HttpClient in RestSharp ? |
Some code is in the branch. The issue I am facing is how to make the API cleaner. Both |
In addition, I got a bit stuck on the There are two solutions there:
I would prefer the second option but it is very restrictive. |
Is there any workaround for this issue except rewrite to httpclientfactory? |
I studied the code of Essentially, it should work as-is already now. The problem that I see is that both Remember that since RestSharp has no access to This PR dotnet/corefx#41462 mentioned in #1322 introduced the handler caching. If you stick to only changing the settings that are used to determine if the new handler is needed, you won't encounter the issue. |
Hey, thanks for the reply. So just to confirm if I use restrequest that doesn't set parameters checked here AreParametersAcceptableForCaching (method from PR) restsharp will cache httpmessagehandler. So in this case I can freely instantiate new RestClient in my service methods or I should cache RestClient instance by myself anyway? |
RestSharp caches nothing. That's how |
Got it, but what's the preferred usage of restclient then, let's say that I have 10 services instantiated by di container, all of them send json payload and doesn't set anything specific on restclient. Should I have one instance of RestClient provided to those 10 services or 10 instances of restclient so each service has it's own instance? |
It's less about how many instances of something you have that uses RestClient. It is more about isolating an external API in a typed client and use it as a singleton, reusing the RestClient instance. RestClient supposes to be thread-safe. But, ten instances is not a problem, the issue is when a new HttpMessageHandler instance is created for each request. |
Thank you! |
@alexeyzimarev Are you still needing help on this, or do you have it covered? |
I have a branch that I can share. The struggle is around the set of settings that would require creating a new HttpMessageHandler instance. The rest is quite trivial. |
Hi, we are having big problems with this also. When are you expecting the release to be out? |
It's been about a month so I'm just checking if there are any updates on this matter. I would love to keep with RestSharp instead of switching all my code over to the HTTPClientFactory. Is there a branch accessible with what's been done so far? Thanks for all your hard work. |
@alexeyzimarev can you give us a time window on this? |
@zachrybaker sorry, but no, I can’t. I have a lid job and after half a year since RestSharp has sponsorship enabled, no one is willing to contribute depicts the package is being downloaded tens of thousands times per day. I can do charity for just as much, but no more. |
@zachrybaker @mycomycul @bluetentacle if you're not precious about RestSharp as a dependency, Refit has full support HttpClient and HttpClientFactory and is a reasonably mature library. I noticed when doing an integration with Xero their official The ability to add a custom pipeline of |
Thanks for sharing. We already implemented our own implementation for our
needs, but I will take a look!
Zachry Baker
979.255.2084
…On Fri, Nov 6, 2020 at 6:44 AM James Tayler ***@***.***> wrote:
@zachrybaker <https://github.com/zachrybaker> @mycomycul
<https://github.com/mycomycul> @bluetentacle
<https://github.com/bluetentacle> if you're not precious about RestSharp
as a dependency, Refit has full support HttpClient and HttpClientFactory
and is a reasonably mature library.
I noticed when doing an integration with Xero their official netstandard
SDK is generated using the OpenAPI csharp-netcore generator which uses
RestSharp under the hood. I have a rule to only use 3rd party SDKs if
they allow our engineers full control over the HTTP requests by using
HttpClient, so went with a hybrid solution where we used the models
generated by the OpenAPI tooling, but coupled that with a Refit client
which lets us use HttpClient.
The ability to add a custom pipeline of DelegatingHandler's to do
logging/tracing/metrics/exception
handling/rate-limiting/fault-tolerance/auth in a way that is completely
decoupled from the actual client itself has been quite a game changer in
terms of maintainability and stability of our integrations. It doesn't make
sense to not be using HttpClient in 2020. I'm glad to see support for it
in RestSharp is under consideration, as I know this library still has a
large install-base and a large part of the mindshare as the go-to solution
due to its long-standing popularity.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1406 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACDSMVCN6T63Q4PZ2ORUT3SOPVUHANCNFSM4KGPXHNA>
.
|
Is there a branch with the in-progress work? Is any assistance needed? I am also curious as to what breaking changes may be expected to |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
|
Looks this issue should be kept open. Anyway, I understand the author may not give a exact deadline on this issue since he has a full time job. And I do appreciate the great work made by the author. @alexeyzimarev |
Coming here to say that this is an important change, as right now RestSharp will not work in Blazor web assembly. |
although its irrelevant to Rest Sharp, I came across this same limitation while doing integration tests, so i instead wrote a HTTP client extension that kind of behaves like RestSharp. Hope someone finds it useful. public static class HttpClientExtensions
{
private static string BuildQuery(List<(string Key, string Value)> parameters)
{
var sb = new StringBuilder();
foreach (var parameter in parameters)
{
if (sb.Length != 0)
{
sb.Append('&');
}
sb.Append($"{parameter.Item1}={parameter.Item2}");
}
return sb.ToString();
}
public static async Task<T> MakePostRequestAsync<T>(this HttpClient httpClient, RequestModel requestModel)
{
httpClient.DefaultRequestHeaders.Clear();
requestModel.Headers.ForEach(x => httpClient.DefaultRequestHeaders.Add(x.Key, x.Value));
var queryParameter = BuildQuery(requestModel.Parameters);
var response =
await httpClient.PostAsync($"{requestModel.Url}?{queryParameter}",
new StringContent(requestModel.JsonBody, Encoding.UTF8, "application/json"));
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<T>() ?? throw new Exception("Failed to parse response");
}
var error = await response.Content.ReadAsStringAsync();
throw new Exception($"Api returned error response, Error: {error}");
}
public static async Task<T> MakeEncodedPostRequestAsync<T>(this HttpClient httpClient, RequestModel requestModel)
{
httpClient.DefaultRequestHeaders.Clear();
requestModel.Headers.ForEach(x => httpClient.DefaultRequestHeaders.Add(x.Key, x.Value));
// var queryParameter = BuildQuery(request.Parameters);
var encodedParams = new Dictionary<string, string>();
requestModel.Parameters.ForEach(x => encodedParams.Add(x.Key, x.Value));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response =
await httpClient.PostAsync(requestModel.Url,
new FormUrlEncodedContent(encodedParams));
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<T>() ?? throw new Exception("Failed to parse response");
}
var error = await response.Content.ReadAsStringAsync();
throw new Exception($"Api returned error response, Error: {error}");
}
public static async Task<T> MakeGetRequestAsync<T>(this HttpClient httpClient, RequestModel requestModel)
{
httpClient.DefaultRequestHeaders.Clear();
requestModel.Headers.ForEach(x => httpClient.DefaultRequestHeaders.Add(x.Key, x.Value));
var queryParameter = BuildQuery(requestModel.Parameters);
var response =
await httpClient.GetAsync($"{requestModel.Url}?{queryParameter}");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<T>() ?? throw new Exception("Failed to parse response");
}
throw new Exception("Api returned error response");
}
public static async Task<T> MakeDeleteRequestAsync<T>(this HttpClient httpClient, RequestModel requestModel)
{
httpClient.DefaultRequestHeaders.Clear();
requestModel.Headers.ForEach(x => httpClient.DefaultRequestHeaders.Add(x.Key, x.Value));
var queryParameter = BuildQuery(requestModel.Parameters);
var response =
await httpClient.DeleteAsync($"{requestModel.Url}?{queryParameter}");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<T>() ?? throw new Exception("Failed to parse response");
}
throw new Exception("Api returned error response");
}
}
public class RequestModel
{
public List<(string Key, string Value)> Headers { get; private set; }
public List<(string Key, string Value)> Parameters { get; private set; }
public string JsonBody { get; private set; }
public string Url { get; private set; }
public RequestModel(string url)
{
Url = url;
Headers = new List<(string Key, string Value)>();
Parameters = new List<(string Key, string Value)>();
}
public RequestModel AddHeader(string headerKey, string headerValue)
{
Headers.Add(new(headerKey, headerValue));
return this;
}
public RequestModel AddParameter(string paramKey, string paramValue)
{
Parameters.Add(new(paramKey, paramValue));
return this;
}
public RequestModel AddJsonBody<T>(T body) where T : class
{
JsonBody = JsonSerializer.Serialize(body);
return this;
}
} |
Currently, RestSharp uses
HttpWebRequest
, since that was the "way to do it" back in the days.Time passed by and
HttpClient
dominates now, so we need to move on.There are several issues with
HttpWebRequest
implementation that could be resolved by usingHttpClient
:HttpClient
for connection poolingThese are the main issues but there're advantages that overall come with more modern implementation.
In the latest versions of .NET framework (full and core),
HttpWebRequest
uses theHttpClient
anyway.The text was updated successfully, but these errors were encountered: