Skip to content

Commit c7c93da

Browse files
committed
Initial commit
0 parents  commit c7c93da

28 files changed

+1370
-0
lines changed

.editorconfig

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# EditorConfig is awesome:http://EditorConfig.org
2+
3+
# top-most EditorConfig file
4+
root = true
5+
6+
# Don't use tabs for indentation.
7+
[*]
8+
indent_style = space
9+
# (Please don't specify an indent_size here; that has too many unintended consequences.)
10+
11+
# Code files
12+
[*.{cs,csx,vb,vbx}]
13+
indent_size = 4
14+
insert_final_newline = true
15+
charset = utf-8-bom
16+
17+
# Xml project files
18+
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
19+
indent_size = 2
20+
21+
# Xml config files
22+
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
23+
indent_size = 2
24+
25+
# JSON files
26+
[*.json]
27+
indent_size = 2
28+
29+
# Dotnet code style settings:
30+
[*.{cs,vb}]
31+
# Sort using and Import directives with System.* appearing first
32+
dotnet_sort_system_directives_first = true
33+
# Avoid "this." and "Me." if not necessary
34+
dotnet_style_qualification_for_field = false:suggestion
35+
dotnet_style_qualification_for_property = false:suggestion
36+
dotnet_style_qualification_for_method = false:suggestion
37+
dotnet_style_qualification_for_event = false:suggestion
38+
39+
# Use language keywords instead of framework type names for type references
40+
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
41+
dotnet_style_predefined_type_for_member_access = true:suggestion
42+
43+
# Suggest more modern language features when available
44+
dotnet_style_object_initializer = true:suggestion
45+
dotnet_style_collection_initializer = true:suggestion
46+
dotnet_style_coalesce_expression = true:suggestion
47+
dotnet_style_null_propagation = true:suggestion
48+
dotnet_style_explicit_tuple_names = true:suggestion
49+
50+
# CSharp code style settings:
51+
[*.cs]
52+
# Prefer "var" everywhere
53+
#csharp_style_var_for_built_in_types = true:suggestion
54+
#csharp_style_var_when_type_is_apparent = false:suggestion
55+
#csharp_style_var_elsewhere = true:suggestion
56+
57+
# Prefer method-like constructs to have a expression-body
58+
csharp_style_expression_bodied_methods = true:none
59+
csharp_style_expression_bodied_constructors = true:none
60+
csharp_style_expression_bodied_operators = true:none
61+
62+
# Prefer property-like constructs to have an expression-body
63+
csharp_style_expression_bodied_properties = true:none
64+
csharp_style_expression_bodied_indexers = true:none
65+
csharp_style_expression_bodied_accessors = true:none
66+
67+
# Suggest more modern language features when available
68+
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
69+
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
70+
csharp_style_inlined_variable_declaration = true:suggestion
71+
csharp_style_throw_expression = true:suggestion
72+
csharp_style_conditional_delegate_call = true:suggestion
73+
74+
# Newline settings
75+
csharp_new_line_before_open_brace = all
76+
csharp_new_line_before_else = true
77+
csharp_new_line_before_catch = true
78+
csharp_new_line_before_finally = true
79+
csharp_new_line_before_members_in_object_initializers = true
80+
csharp_new_line_before_members_in_anonymous_types = true

.gitattributes

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto
3+
4+
# Custom for Visual Studio
5+
*.cs diff=csharp
6+
*.sln merge=union
7+
*.csproj merge=union

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
_ReSharper*
2+
bin
3+
obj
4+
*.suo
5+
*.user
6+
*.nupkgs
7+
.vs/*

LICENSE.txt

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) .NET StackExchange.Utils Contributors
4+
5+
All rights reserved.
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in all
15+
copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
SOFTWARE.

Readme.md

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
## Stack Exchange Utility Packages
2+
Home for the StackExchange.Util.* packages.
3+
4+
#### StackExchange.Utils.Http
5+
`Http` is a helper class for making `HttpClient` calls. The send, deserialization, options, and verb portions are exchangable. Some examples:
6+
7+
POSTing a string and expecting a string:
8+
```cs
9+
var result = await Http.Request("https://example.com")
10+
.SendPlaintext("test")
11+
.ExpectString()
12+
.PostAsync();
13+
```
14+
15+
POSTing JSON and expecting protobuf back:
16+
```cs
17+
var result = await Http.Request("https://example.com")
18+
.SendJson(new { name = "my thing" })
19+
.ExpectProtobuf<MyType>()
20+
.PostAsync();
21+
```
22+
23+
Sending nothing and GETing JSON back:
24+
```cs
25+
var result = await Http.Request("https://example.com")
26+
.ExpectJson<MyType>()
27+
.GetAsync();
28+
```
29+
30+
Sending nothing and GETing JSON back, with a timeout, ignoring 404 responses:
31+
```cs
32+
var result = await Http.Request("https://example.com")
33+
.IgnoredResponseStatuses(HttpStatusCode.NotFound)
34+
.WithTimeout(TimeSpan.FromSeconds(20))
35+
.ExpectJson<MyType>()
36+
.GetAsync();
37+
// Handle the response:
38+
if (result.Success)
39+
{
40+
//result.Data is MyType, deserialized from the returned JSON
41+
}
42+
else
43+
{
44+
// result.Error
45+
// result.StatusCode
46+
// result.RawRequest
47+
// result.RawResponse
48+
}
49+
```
50+
51+
#### License
52+
MiniProfiler is licensed under the [MIT license](https://github.com/StackExchange/StackExchange.Utils/blob/master/LICENSE.txt).

StackExchange.Utils.sln

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.27705.2000
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F0CFAC4D-516B-45DC-8F66-D58E3B1C04E1}"
7+
ProjectSection(SolutionItems) = preProject
8+
src\Directory.build.props = src\Directory.build.props
9+
EndProjectSection
10+
EndProject
11+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StackExchange.Utils.Http", "src\StackExchange.Utils.Http\StackExchange.Utils.Http.csproj", "{168B503A-428F-499D-99A7-8EFC47A5FEDF}"
12+
EndProject
13+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9133A680-3A8F-4662-AA58-B59BBDD0A60E}"
14+
ProjectSection(SolutionItems) = preProject
15+
tests\Directory.build.props = tests\Directory.build.props
16+
EndProjectSection
17+
EndProject
18+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StackExchange.Utils.Tests", "tests\StackExchange.Utils.Tests\StackExchange.Utils.Tests.csproj", "{33716E0F-FE40-4A7A-9F58-1026EF7EBCD2}"
19+
EndProject
20+
Global
21+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
22+
Debug|Any CPU = Debug|Any CPU
23+
Release|Any CPU = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
26+
{168B503A-428F-499D-99A7-8EFC47A5FEDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{168B503A-428F-499D-99A7-8EFC47A5FEDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{168B503A-428F-499D-99A7-8EFC47A5FEDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{168B503A-428F-499D-99A7-8EFC47A5FEDF}.Release|Any CPU.Build.0 = Release|Any CPU
30+
{33716E0F-FE40-4A7A-9F58-1026EF7EBCD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31+
{33716E0F-FE40-4A7A-9F58-1026EF7EBCD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
32+
{33716E0F-FE40-4A7A-9F58-1026EF7EBCD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
33+
{33716E0F-FE40-4A7A-9F58-1026EF7EBCD2}.Release|Any CPU.Build.0 = Release|Any CPU
34+
EndGlobalSection
35+
GlobalSection(SolutionProperties) = preSolution
36+
HideSolutionNode = FALSE
37+
EndGlobalSection
38+
GlobalSection(NestedProjects) = preSolution
39+
{168B503A-428F-499D-99A7-8EFC47A5FEDF} = {F0CFAC4D-516B-45DC-8F66-D58E3B1C04E1}
40+
{33716E0F-FE40-4A7A-9F58-1026EF7EBCD2} = {9133A680-3A8F-4662-AA58-B59BBDD0A60E}
41+
EndGlobalSection
42+
GlobalSection(ExtensibilityGlobals) = postSolution
43+
SolutionGuid = {F211D702-85D2-4159-9B42-60B6177497B7}
44+
EndGlobalSection
45+
EndGlobal

nuget.config

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<clear />
5+
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
6+
</packageSources>
7+
</configuration>

src/Directory.build.props

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Project>
2+
<PropertyGroup>
3+
<RootNamespace>StackExchange.Utils</RootNamespace>
4+
<OutputType>Library</OutputType>
5+
<OutputPath>bin\$(Configuration)\</OutputPath>
6+
<DebugSymbols>true</DebugSymbols>
7+
<DebugType>embedded</DebugType>
8+
<LangVersion>7.3</LangVersion>
9+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
10+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
11+
12+
<Authors>Stack Exchange</Authors>
13+
<PackageId>$(AssemblyName)</PackageId>
14+
<PackageLicenseUrl>https://opensource.org/licenses/MIT</PackageLicenseUrl>
15+
<PackageProjectUrl>https://github.com/StackExchange/StackExchange.Utils</PackageProjectUrl>
16+
</PropertyGroup>
17+
18+
<ItemGroup>
19+
<PackageReference Include="Nerdbank.GitVersioning" Version="2.1.23" PrivateAssets="all" />
20+
<PackageReference Include="SourceLink.Create.GitHub" Version="2.8.1" PrivateAssets="All" />
21+
<DotNetCliToolReference Include="dotnet-sourcelink" Version="2.8.1" />
22+
<DotNetCliToolReference Include="dotnet-sourcelink-git" Version="2.8.1" />
23+
</ItemGroup>
24+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using System.Net;
4+
using System.Net.Http;
5+
using System.Net.Http.Headers;
6+
7+
namespace StackExchange.Utils
8+
{
9+
/// <summary>
10+
/// The default implementation of <see cref="IHttpClientPool"/>.
11+
/// </summary>
12+
public class DefaultHttpClientPool : IHttpClientPool
13+
{
14+
private readonly ConcurrentDictionary<HttpClientCacheKey, HttpClient> ClientPool = new ConcurrentDictionary<HttpClientCacheKey, HttpClient>();
15+
private HttpSettings Settings { get; }
16+
17+
/// <summary>
18+
/// Creates a new <see cref="DefaultHttpClientPool"/> based on the settings.
19+
/// </summary>
20+
/// <param name="settings">The settings to based this pool on.</param>
21+
public DefaultHttpClientPool(HttpSettings settings) => Settings = settings;
22+
23+
/// <summary>
24+
/// Gets a <see cref="HttpClient"/> from the pool, based on the <see cref="IRequestBuilder"/>.
25+
/// </summary>
26+
/// <param name="builder">The builder to get a request from.</param>
27+
/// <returns>The found or created <see cref="HttpClient"/> from the pool.</returns>
28+
public HttpClient Get(IRequestBuilder builder) => ClientPool.GetOrAdd(new HttpClientCacheKey(builder.Timeout), CreateHttpClient);
29+
30+
private HttpClient CreateHttpClient(HttpClientCacheKey options)
31+
{
32+
var handler = new HttpClientHandler
33+
{
34+
UseCookies = false
35+
};
36+
if (handler.SupportsAutomaticDecompression)
37+
{
38+
handler.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
39+
}
40+
41+
var client = new HttpClient(handler)
42+
{
43+
Timeout = options.Timeout,
44+
DefaultRequestHeaders =
45+
{
46+
AcceptEncoding =
47+
{
48+
new StringWithQualityHeaderValue("gzip"),
49+
new StringWithQualityHeaderValue("deflate")
50+
}
51+
}
52+
};
53+
client.DefaultRequestHeaders.Add("User-Agent", Settings.UserAgent);
54+
return client;
55+
}
56+
57+
/// <summary>
58+
/// Clears the pool, causing all new <see cref="HttpClient"/>s to be created on the following calls.
59+
/// </summary>
60+
public void Clear() => ClientPool.Clear();
61+
62+
private struct HttpClientCacheKey
63+
{
64+
public TimeSpan Timeout { get; }
65+
66+
public HttpClientCacheKey(TimeSpan timeout) => Timeout = timeout;
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)