Skip to content

Commit 507ed87

Browse files
alexeyzimarevfcastellsFrancesc CastellsEdLichtman
authored
* Added .NET Framework 471 as a target. .NET 5 is out * Fix the media type issue with .NET 7 restsharp#1969 * `IRestClient` Interface is back * String type for ContentType * Added Authenticator to RestRequest * Made Options immutable to make the client thread-safe * Ignore exceptions parsing response cookies (restsharp#2015) * V109 (restsharp#2010) * Added a simple factory with opt-in --------- Co-authored-by: Francesc Castells <fcastells76@gmail.com> Co-authored-by: Francesc Castells <francesc.castells@sermo.com> Co-authored-by: Edward Lichtman <E.Lichtman2@gmail.com>
1 parent 3e43c5a commit 507ed87

File tree

105 files changed

+2010
-1526
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+2010
-1526
lines changed

.github/workflows/build-dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
name: Setup .NET
2828
uses: actions/setup-dotnet@v3
2929
with:
30-
dotnet-version: '7.0'
30+
dotnet-version: '7.0.102'
3131
-
3232
name: Unshallow
3333
run: git fetch --prune --unshallow

RestSharp.sln

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RestSharp.Serializers.CsvHe
3535
EndProject
3636
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RestSharp.Tests.Serializers.Csv", "test\RestSharp.Tests.Serializers.Csv\RestSharp.Tests.Serializers.Csv.csproj", "{E6D94FFD-7811-40BE-ABC4-6D6AB41F0060}"
3737
EndProject
38+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SourceGen", "SourceGen", "{55B8F371-B2BA-4DEE-AB98-5BAB8A21B1C2}"
39+
EndProject
40+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGenerator", "gen\SourceGenerator\SourceGenerator.csproj", "{FE778406-ADCF-45A1-B775-A054B55BFC50}"
41+
EndProject
3842
Global
3943
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4044
Debug.Appveyor|Any CPU = Debug.Appveyor|Any CPU
@@ -444,6 +448,36 @@ Global
444448
{E6D94FFD-7811-40BE-ABC4-6D6AB41F0060}.Release|x64.Build.0 = Release|Any CPU
445449
{E6D94FFD-7811-40BE-ABC4-6D6AB41F0060}.Release|x86.ActiveCfg = Release|Any CPU
446450
{E6D94FFD-7811-40BE-ABC4-6D6AB41F0060}.Release|x86.Build.0 = Release|Any CPU
451+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|Any CPU.ActiveCfg = Debug|Any CPU
452+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|Any CPU.Build.0 = Debug|Any CPU
453+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|ARM.ActiveCfg = Debug|Any CPU
454+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|ARM.Build.0 = Debug|Any CPU
455+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|Mixed Platforms.ActiveCfg = Debug|Any CPU
456+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|Mixed Platforms.Build.0 = Debug|Any CPU
457+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|x64.ActiveCfg = Debug|Any CPU
458+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|x64.Build.0 = Debug|Any CPU
459+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|x86.ActiveCfg = Debug|Any CPU
460+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug.Appveyor|x86.Build.0 = Debug|Any CPU
461+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
462+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|Any CPU.Build.0 = Debug|Any CPU
463+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|ARM.ActiveCfg = Debug|Any CPU
464+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|ARM.Build.0 = Debug|Any CPU
465+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
466+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
467+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|x64.ActiveCfg = Debug|Any CPU
468+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|x64.Build.0 = Debug|Any CPU
469+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|x86.ActiveCfg = Debug|Any CPU
470+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Debug|x86.Build.0 = Debug|Any CPU
471+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|Any CPU.ActiveCfg = Release|Any CPU
472+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|Any CPU.Build.0 = Release|Any CPU
473+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|ARM.ActiveCfg = Release|Any CPU
474+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|ARM.Build.0 = Release|Any CPU
475+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
476+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|Mixed Platforms.Build.0 = Release|Any CPU
477+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|x64.ActiveCfg = Release|Any CPU
478+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|x64.Build.0 = Release|Any CPU
479+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|x86.ActiveCfg = Release|Any CPU
480+
{FE778406-ADCF-45A1-B775-A054B55BFC50}.Release|x86.Build.0 = Release|Any CPU
447481
EndGlobalSection
448482
GlobalSection(SolutionProperties) = preSolution
449483
HideSolutionNode = FALSE
@@ -461,6 +495,7 @@ Global
461495
{5A8A5BBE-28DA-4C89-B393-BE39A96E8DC0} = {9051DDA0-E563-45D5-9504-085EBAACF469}
462496
{2150E333-8FDC-42A3-9474-1A3956D46DE8} = {8C7B43EB-2F93-483C-B433-E28F9386AD67}
463497
{E6D94FFD-7811-40BE-ABC4-6D6AB41F0060} = {9051DDA0-E563-45D5-9504-085EBAACF469}
498+
{FE778406-ADCF-45A1-B775-A054B55BFC50} = {55B8F371-B2BA-4DEE-AB98-5BAB8A21B1C2}
464499
EndGlobalSection
465500
GlobalSection(ExtensibilityGlobals) = postSolution
466501
SolutionGuid = {77FF357B-03FA-4FA5-A68F-BFBE5800FEBA}

docs/.vuepress/config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module.exports = {
1111
themeConfig: {
1212
logo: "/restsharp.png",
1313
navbar: [
14-
{text: "Migration to v107", link: "/v107/"},
14+
{text: "Migration from legacy", link: "/v107/"},
1515
{text: "Documentation", link: "/intro.html"},
1616
{text: "Get help", link: "/support/"},
1717
{text: "NuGet", link: "https://nuget.org/packages/RestSharp"}
@@ -34,7 +34,7 @@ module.exports = {
3434
"/v107/": [
3535
{
3636
text: "",
37-
header: "Migration to v107",
37+
header: "Migration from legacy",
3838
children: [
3939
"/v107/README.md"
4040
]

docs/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ heroText: RestSharp
55
tagline: Probably, the most popular REST API client library for .NET
66
actions:
77
- text: Get Started →
8-
link: /v107/
8+
link: /intro.html
99
features:
1010
- title: Serialization
1111
details: JSON, XML and custom serialization and deserialization
@@ -24,7 +24,7 @@ footer: Apache 2.0 Licensed | Copyright (c) .NET Foundation and Contributors
2424

2525
RestSharp is probably the most popular HTTP client library for .NET. Featuring automatic serialization and deserialization, request and response type detection, variety of authentications and other useful features, it is being used by hundreds of thousands of projects.
2626

27-
RestSharp passed over 165 million downloads on NuGet, with average daily download count close to 42,000. It's being used by many popular OSS projects, including Roslyn and Swagger.
27+
RestSharp passed over 190 million downloads on NuGet, with average daily download count over 43,000. It's being used by many popular OSS projects, including Roslyn and Swagger.
2828

2929
Supported by [AWS](https://aws.amazon.com/developer/language/net/solutions/).
3030
<div style="text-align: center;"><a href="https://aws.amazon.com"><img src="/aws_logo.png" alt="AWS logo"></a></div>

docs/usage.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,28 @@ First, there's `DownloadDataAsync`, which returns `Task<byte[]`. It will read th
462462

463463
For larger responses, you can use `DownloadStreamAsync` that returns `Task<Stream>`. This function allows you to open a stream reader and asynchronously stream large responses to memory or disk.
464464

465+
466+
## Reusing HttpClient
467+
468+
RestSharp uses `HttpClient` internally to make HTTP requests. It's possible to reuse the same `HttpClient` instance for multiple `RestClient` instances. This is useful when you want to share the same connection pool between multiple `RestClient` instances.
469+
470+
One way of doing it is to use `RestClient` constructors that accept an instance of `HttpClient` or `HttpMessageHandler` as an argument. Note that in that case not all the options provided via `RestClientOptions` will be used. Here is the list of options that will work:
471+
472+
- `BaseAddress` will be used to set the base address of the `HttpClient` instance if base address is not set there already.
473+
- `MaxTimeout`
474+
- `UserAgent` will be set if the `User-Agent` header is not set on the `HttpClient` instance already.
475+
- `Expect100Continue`
476+
477+
Another option is to use a simple HTTP client factory. It is a static factory, which holds previously instantiated `HttpClient` instances. It can be used to create `RestClient` instances that share the same `HttpClient` instance. The cache key is the `BaseUrl` provided in the options. When you opt-in to use the factory and don't set `BaseUrl`, the `RestClient` constructor will crash.
478+
479+
```csharp
480+
var client = new RestClient(new Uri("https://example.org/api"), useClientFactory: true);
481+
```
482+
483+
::: warning
484+
Note that the `RestClient` constructor will not reconfigure the `HttpClient` instance if it's already in the cache. Therefore, you should not try using the factory when providing different options for the same base URL.
485+
:::
486+
465487
## Blazor support
466488

467489
Inside a Blazor webassembly app, you can make requests to external API endpoints. Microsoft examples show how to do it with `HttpClient`, and it's also possible to use RestSharp for the same purpose.

docs/v107/README.md

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
2-
title: RestSharp Next (v107)
2+
title: RestSharp Next (v107+)
33
---
44

5-
## RestSharp v107
5+
## RestSharp v107+
66

7-
The latest version of RestSharp is v107. It's a major upgrade, which contains quite a few breaking changes.
7+
RestSharp got a major upgrade in v107, which contains quite a few breaking changes.
88

99
The most important change is that RestSharp stop using the legacy `HttpWebRequest` class, and uses well-known 'HttpClient' instead.
1010
This move solves lots of issues, like hanging connections due to improper `HttpClient` instance cache, updated protocols support, and many other problems.
@@ -17,7 +17,7 @@ Finally, most of the interfaces are now gone.
1717

1818
### RestClient and options
1919

20-
The `IRestClient` interface is deprecated. You will be using the `RestClient` class instance.
20+
The `IRestClient` interface is deprecated in v107, but brought back in v109. The new interface, however, has a much smaller API compared to previous versions. You will be using the `RestClient` class instance.
2121

2222
Most of the client options are moved to `RestClientOptions`. If you can't find the option you used to set on `IRestClient`, check the options, it's probably there.
2323

@@ -187,23 +187,16 @@ The next RestSharp version presumably solves the following issues:
187187
## Deprecated interfaces
188188

189189
The following interfaces are removed from RestSharp:
190-
- `IRestClient`
191190
- `IRestRequest`
192191
- `IRestResponse`
193192
- `IHttp`
194193

195-
### Motivation
196-
197-
All the deprecated interfaces had only one implementation in RestSharp, so those interfaces were abstracting nothing. It is now unclear what was the purpose for adding those interfaces initially.
198-
199-
What about mocking it, you might ask? The answer is: what would you do if you use a plain `HttpClient` instance? It doesn't implement any interface for the same reason - there's nothing to abstract, and there's only one implementation. We don't recommend mocking `RestClient` in your tests when you are testing against APIs that are controlled by you or people in your organisation. Test your clients against the real thing, as REST calls are I/O-bound. Mocking REST calls is like mocking database calls, and lead to a lot of issues in production even if all your tests pass against mocks.
200-
201-
As mentioned in [Recommended usage](#recommended-usage), we advise against using `RestClient` in the application code, and advocate wrapping it inside particular API client classes. Those classes would be under your control, and you are totally free to use interfaces there. If you absolutely must mock, you can mock your interfaces instead.
202-
203194
### Mocking
204195

205196
Mocking an infrastructure component like RestSharp (or HttpClient) is not the best idea. Even if you check that all the parameters are added correctly to the request, your "unit test" will only give you a false sense of safety that your code actually works. But, you have no guarantee that the remote server will accept your request, or if you can handle the actual response correctly.
206197

198+
However, since v109 you can still mock the `IRestClient` interface, but you only need to implement the `ExecuteAsync` method. The `ExecuteAsync` method is the only one that actually makes a call to the remote server. All other methods are just wrappers around it.
199+
207200
The best way to test HTTP calls is to make some, using the actual service you call. However, you might still want to check if your API client forms requests in a certain way. You might also be sure about what the remote server responds to your calls with, so you can build a set of JSON (or XML) responses, so you can simulate remote calls.
208201

209202
It is perfectly doable without using interfaces. As RestSharp uses `HttpClient` internally, it certainly uses `HttpMessageHandler`. Features like delegating handlers allow you to intercept the request pipeline, inspect the request, and substitute the response. You can do it yourself, or use a library like [MockHttp](https://github.com/richardszalay/mockhttp). They have an example provided in the repository README, so we have changed it for RestClient here:

0 commit comments

Comments
 (0)