Skip to content
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

4.0 here we go! #788

Merged
merged 3 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion NuGet.Config
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="appveyor feed" value="https://ci.appveyor.com/nuget/flurl" />
</packageSources>
<packageRestore>
<!--Allow NuGet to download missing packages -->
Expand Down
32 changes: 15 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# Flurl

[![Build status](https://ci.appveyor.com/api/projects/status/hec8ioqg0j07ttg5/branch/master?svg=true)](https://ci.appveyor.com/project/kroniak/flurl/branch/master)
[![Flurl-stable](https://img.shields.io/nuget/v/Flurl.svg?maxAge=3600&label=Flurl%20nuget)](https://www.nuget.org/packages/Flurl/)
[![Flurl.Http-stable](https://img.shields.io/nuget/v/Flurl.Http.svg?maxAge=3600&label=Flurl.Http%20nuget)](https://www.nuget.org/packages/Flurl.Http/)
[![Flurl-pre-release](https://img.shields.io/nuget/vpre/Flurl.svg?maxAge=3600&label=Flurl%20Pre-Release%20nuget)](https://www.nuget.org/packages/Flurl/)
[![Flurl.Http-pre-release](https://img.shields.io/nuget/vpre/Flurl.Http.svg?maxAge=3600&label=Flurl.Http%20Pre-Release%20nuget)](https://www.nuget.org/packages/Flurl.Http/)
[![build](https://github.com/tmenier/Flurl/actions/workflows/ci.yml/badge.svg)](https://github.com/tmenier/Flurl/actions/workflows/ci.yml)
[![NuGet Version](http://img.shields.io/nuget/v/Flurl.Http.svg?style=flat)](https://www.nuget.org/packages/Flurl.Http/)
[![NuGet Downloads](https://img.shields.io/nuget/dt/Flurl.Http.svg)](https://www.nuget.org/packages/Flurl.Http/)

Flurl is a modern, fluent, asynchronous, testable, portable, buzzword-laden URL builder and HTTP client library.

````c#
```cs
var result = await "https://api.mysite.com"
.AppendPathSegment("person")
.SetQueryParams(new { api_key = "xyz" })
Expand All @@ -19,20 +17,20 @@ var result = await "https://api.mysite.com"
[Test]
public void Can_Create_Person() {
// fake & record all http calls in the test subject
using (var httpTest = new HttpTest()) {
// arrange
httpTest.RespondWith("OK", 200);
using var httpTest = new HttpTest();

// act
await sut.CreatePersonAsync("Claire", "Underwood");
// arrange
httpTest.RespondWith("OK", 200);

// act
await sut.CreatePersonAsync("Frank", "Reynolds");

// assert
httpTest.ShouldHaveCalled("http://api.mysite.com/*")
.WithVerb(HttpMethod.Post)
.WithContentType("application/json");
}
// assert
httpTest.ShouldHaveCalled("http://api.mysite.com/*")
.WithVerb(HttpMethod.Post)
.WithContentType("application/json");
}
````
```

Get it on NuGet:

Expand Down
3 changes: 2 additions & 1 deletion src/Flurl.Http.Newtonsoft/Flurl.Http.Newtonsoft.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
<LangVersion>9.0</LangVersion>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>Flurl.Http.Newtonsoft</PackageId>
<Version>0.9.0-pre3</Version>
<Version>0.9.0</Version>
<Authors>Todd Menier</Authors>
<Description>A Newtonsoft-based JSON serializer for Flurl.Http 4.0 and above.</Description>
<Copyright>Copyright (c) Todd Menier 2023.</Copyright>
<PackageProjectUrl>https://flurl.dev</PackageProjectUrl>
<PackageIcon>icon.png</PackageIcon>
<RepositoryUrl>https://github.com/tmenier/Flurl.git</RepositoryUrl>
Expand Down
31 changes: 6 additions & 25 deletions src/Flurl.Http/Configuration/FlurlClientCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ public interface IFlurlClientCache
/// </summary>
/// <param name="name">Name of the IFlurlClient. Serves as a cache key. Subsequent calls to Get will return this client.</param>
/// <param name="baseUrl">Optional. The base URL associated with the new client.</param>
/// <returns>A builder to further configure the new client.</returns>
IFlurlClientBuilder Add(string name, string baseUrl = null);
/// <param name="configure">Optional. Configure the builder associated with the added client.</param>
/// <returns>This IFlurlCache.</returns>
IFlurlClientCache Add(string name, string baseUrl = null, Action<IFlurlClientBuilder> configure = null);

/// <summary>
/// Gets a preconfigured named IFlurlClient.
Expand Down Expand Up @@ -54,27 +55,6 @@ public interface IFlurlClientCache
IFlurlClientCache Clear();
}

/// <summary>
/// Extension methods on IFlurlClientCache.
/// </summary>
public static class IFlurlClientCacheExtensions
{
/// <summary>
/// Adds a new IFlurlClient to this cache. Call once per client at startup to register and configure a named client.
/// Allows configuring via a nested lambda, rather than returning a builder, so multiple Add calls can be fluently chained.
/// </summary>
/// <param name="cache">This IFlurlCache</param>
/// <param name="name">Name of the IFlurlClient. Serves as a cache key. Subsequent calls to Get will return this client.</param>
/// <param name="baseUrl">The base URL associated with the new client.</param>
/// <param name="configure">Configure the builder associated with the added client.</param>
/// <returns>This IFlurlCache.</returns>
public static IFlurlClientCache Add(this IFlurlClientCache cache, string name, string baseUrl, Action<IFlurlClientBuilder> configure) {
var builder = cache.Add(name, baseUrl);
configure?.Invoke(builder);
return cache;
}
}

/// <summary>
/// Default implementation of IFlurlClientCache.
/// </summary>
Expand All @@ -84,15 +64,16 @@ public class FlurlClientCache : IFlurlClientCache
private readonly List<Action<IFlurlClientBuilder>> _defaultConfigs = new();

/// <inheritdoc />
public IFlurlClientBuilder Add(string name, string baseUrl = null) {
public IFlurlClientCache Add(string name, string baseUrl = null, Action<IFlurlClientBuilder> configure = null) {
if (name == null)
throw new ArgumentNullException(nameof(name));

var builder = CreateBuilder(baseUrl);
if (!_clients.TryAdd(name, new Lazy<IFlurlClient>(builder.Build)))
throw new ArgumentException($"A client named '{name}' was already registered. Add should be called just once per client at startup.");

return builder;
configure?.Invoke(builder);
return this;
}

/// <inheritdoc />
Expand Down
9 changes: 6 additions & 3 deletions src/Flurl.Http/Flurl.Http.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
<LangVersion>9.0</LangVersion>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>Flurl.Http</PackageId>
<Version>4.0.0-pre7</Version>
<PackageVersion>4.0.0</PackageVersion>
<Authors>Todd Menier</Authors>
<Description>A fluent, portable, testable HTTP client library.</Description>
<Description>4.0 contains breaking changes! See flurl.dev/upgrade</Description>
<Copyright>Copyright (c) Todd Menier 2023.</Copyright>
<PackageProjectUrl>https://flurl.dev</PackageProjectUrl>
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/tmenier/Flurl.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand All @@ -25,8 +27,9 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Flurl\Flurl.csproj" />
<None Include="..\..\icon.png" Pack="true" PackagePath="\" />
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
<ProjectReference Include="..\Flurl\Flurl.csproj" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>

Expand Down
6 changes: 5 additions & 1 deletion src/Flurl.Http/FlurlHttp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ public static class FlurlHttp
/// Note that if you've overridden the caching strategy to vary clients by request properties other than Url, you should instead use
/// FlurlHttp.Clients.Add(name) to ensure you are configuring the correct client.
/// </summary>
public static IFlurlClientBuilder ConfigureClientForUrl(string url) => Clients.Add(_cachingStrategy(new FlurlRequest(url)));
public static IFlurlClientBuilder ConfigureClientForUrl(string url) {
IFlurlClientBuilder builder = null;
Clients.Add(_cachingStrategy(new FlurlRequest(url)), null, b => builder = b);
return builder;
}

/// <summary>
/// Gets or creates the IFlurlClient that would be selected for sending the given IFlurlRequest when the clientless pattern is used.
Expand Down
3 changes: 2 additions & 1 deletion src/Flurl/Flurl.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
<TargetFrameworks>netstandard2.0;net461;net472</TargetFrameworks>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>Flurl</PackageId>
<Version>4.0.0-pre4</Version>
<PackageVersion>4.0.0</PackageVersion>
<Authors>Todd Menier</Authors>
<Description>A fluent, portable URL builder. To make HTTP calls off the fluent chain, check out Flurl.Http.</Description>
<Copyright>Copyright (c) Todd Menier 2023.</Copyright>
<PackageProjectUrl>https://flurl.dev</PackageProjectUrl>
<PackageIcon>icon.png</PackageIcon>
<RepositoryUrl>https://github.com/tmenier/Flurl.git</RepositoryUrl>
Expand Down
15 changes: 7 additions & 8 deletions test/Flurl.Test/Http/FlurlClientCacheTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ public class FlurlClientCacheTests
[Test]
public void can_add_and_get_client() {
var cache = new FlurlClientCache();
cache.Add("github", "https://api.github.com").WithSettings(s => s.Timeout = TimeSpan.FromSeconds(123));
cache.Add("google", "https://api.google.com").WithSettings(s => s.Timeout = TimeSpan.FromSeconds(234));
cache.Add("github", "https://api.github.com", builder =>
builder.WithSettings(s => s.Timeout = TimeSpan.FromSeconds(123)));
cache.Add("google", "https://api.google.com", builder =>
builder.WithSettings(s => s.Timeout = TimeSpan.FromSeconds(234)));

var gh = cache.Get("github");
Assert.AreEqual("https://api.github.com", gh.BaseUrl);
Expand Down Expand Up @@ -68,12 +70,9 @@ public void can_configure_defaults() {

var cli1 = cache.GetOrAdd("foo");

cache.Add("bar").WithSettings(s => {
s.Timeout = TimeSpan.FromSeconds(456);
});
cache.WithDefaults(b => b.WithSettings(s => {
s.Timeout = TimeSpan.FromSeconds(789);
}));
cache
.Add("bar", null, builder => builder.WithSettings(s => s.Timeout = TimeSpan.FromSeconds(456)))
.WithDefaults(b => b.WithSettings(s => s.Timeout = TimeSpan.FromSeconds(789)));

var cli2 = cache.GetOrAdd("bar");
var cli3 = cache.GetOrAdd("buzz");
Expand Down