Skip to content

Commit 4f36835

Browse files
authored
HTTP client support enable/disable SSL validation
* HTTP client support enable/disable SSL validation * updated sonarqube analysis pipeline
1 parent afdaee5 commit 4f36835

File tree

8 files changed

+157
-13
lines changed

8 files changed

+157
-13
lines changed

.github/workflows/dotnet-core.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
name: Build .NET Library
22

33
on:
4-
push:
5-
branches: [ develop ]
64
pull_request:
75
branches: [ develop, main ]
86
release:

.github/workflows/sonarqube-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
sonarOrganization: qatoolkit
2929
dotnetBuildArguments: ./src/QAToolKit.Engine.HttpTester/QAToolKit.Engine.HttpTester.csproj
3030
dotnetTestArguments: ./src/QAToolKit.Engine.HttpTester.Test/QAToolKit.Engine.HttpTester.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
31-
sonarBeginArguments: /d:sonar.verbose="true" /d:sonar.language="cs" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" /d:sonar.coverage.exclusions="**Tests.cs"
31+
sonarBeginArguments: /d:sonar.verbose="true" /d:sonar.language="cs" /d:sonar.cs.opencover.reportsPaths="**/*opencover.xml"
3232
sonarHostname: "https://sonarcloud.io"
3333
env:
3434
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>0.1.0</Version>
3+
<Version>0.1.1</Version>
44
</PropertyGroup>
55
</Project>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using QAToolKit.Engine.HttpTester.Exceptions;
2+
using System;
3+
using Xunit;
4+
5+
namespace QAToolKit.Engine.HttpTester.Test.Exceptions
6+
{
7+
public class QAToolKitEngineHttpTesterExceptionTests
8+
{
9+
[Fact]
10+
public void CreateExceptionTest_Successful()
11+
{
12+
var exception = new QAToolKitEngineHttpTesterException("my error");
13+
14+
Assert.Equal("my error", exception.Message);
15+
}
16+
17+
[Fact]
18+
public void CreateExceptionWithInnerExceptionTest_Successful()
19+
{
20+
var innerException = new Exception("Inner");
21+
var exception = new QAToolKitEngineHttpTesterException("my error", innerException);
22+
23+
Assert.Equal("my error", exception.Message);
24+
Assert.Equal("Inner", innerException.Message);
25+
}
26+
}
27+
}

src/QAToolKit.Engine.HttpTester.Test/HttpTesterClientTests.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Threading.Tasks;
1313
using Xunit;
1414
using ExpectedObjects;
15+
using System.Security.Authentication;
1516

1617
namespace QAToolKit.Engine.HttpTester.Test
1718
{
@@ -216,5 +217,89 @@ public async Task HttpTesterClientOnlyInstantiation_Exception()
216217
await Assert.ThrowsAsync<QAToolKitEngineHttpTesterException>(async () => await client.Start());
217218
}
218219
}
220+
221+
[Fact]
222+
public async Task HttpTesterClientGetWithBodyDisableSSLValidationWithValidCert_Success()
223+
{
224+
using (var client = new HttpTesterClient())
225+
{
226+
var response = await client
227+
.CreateHttpRequest(new Uri("https://qatoolkitapi.azurewebsites.net"), false)
228+
.WithQueryParams(new Dictionary<string, string>() { { "api-version", "1" } })
229+
.WithMethod(HttpMethod.Get)
230+
.WithPath("/api/bicycles/1")
231+
.Start();
232+
233+
var msg = await response.GetResponseBody<Bicycle>();
234+
235+
var expecterResponse = BicycleFixture.GetFoil().ToExpectedObject();
236+
expecterResponse.ShouldEqual(msg);
237+
238+
Assert.True(client.Duration < 2000);
239+
Assert.True(response.IsSuccessStatusCode);
240+
Assert.Equal("Scott", msg.Brand);
241+
}
242+
}
243+
244+
[Fact]
245+
public async Task HttpTesterClientGetWithBodyDisableSSLValidationWithInvalidCert_Success()
246+
{
247+
using (var client = new HttpTesterClient())
248+
{
249+
var response = await client
250+
.CreateHttpRequest(new Uri("https://swagger-demo.qatoolkit.io/"), false)
251+
.WithQueryParams(new Dictionary<string, string>() { { "api-version", "1" } })
252+
.WithMethod(HttpMethod.Get)
253+
.WithPath("/api/bicycles/1")
254+
.Start();
255+
256+
var msg = await response.GetResponseBody<Bicycle>();
257+
258+
var expecterResponse = BicycleFixture.GetFoil().ToExpectedObject();
259+
expecterResponse.ShouldEqual(msg);
260+
261+
Assert.True(client.Duration < 2000);
262+
Assert.True(response.IsSuccessStatusCode);
263+
Assert.Equal("Scott", msg.Brand);
264+
}
265+
}
266+
267+
[Fact]
268+
public async Task HttpTesterClientGetWithBodyDisableSSLValidationWithHttpUrl_Exception()
269+
{
270+
using (var client = new HttpTesterClient())
271+
{
272+
var response = await client
273+
.CreateHttpRequest(new Uri("http://swagger-demo.qatoolkit.io/"), false)
274+
.WithQueryParams(new Dictionary<string, string>() { { "api-version", "1" } })
275+
.WithMethod(HttpMethod.Get)
276+
.WithPath("/api/bicycles/1")
277+
.Start();
278+
279+
var msg = await response.GetResponseBody<Bicycle>();
280+
281+
var expecterResponse = BicycleFixture.GetFoil().ToExpectedObject();
282+
expecterResponse.ShouldEqual(msg);
283+
284+
Assert.True(client.Duration < 2000);
285+
Assert.True(response.IsSuccessStatusCode);
286+
Assert.Equal("Scott", msg.Brand);
287+
}
288+
}
289+
290+
[Fact]
291+
public async Task HttpTesterClientGetWithBodyDisableSSLValidationWithInvalidCertAndUrl2_Exception()
292+
{
293+
using (var client = new HttpTesterClient())
294+
{
295+
var response = client
296+
.CreateHttpRequest(new Uri("http://swagger-demo.qatoolkit.io/"), true)
297+
.WithQueryParams(new Dictionary<string, string>() { { "api-version", "1" } })
298+
.WithMethod(HttpMethod.Get)
299+
.WithPath("/api/bicycles/1");
300+
301+
await Assert.ThrowsAsync<HttpRequestException>(async () => await client.Start());
302+
}
303+
}
219304
}
220305
}

src/QAToolKit.Engine.HttpTester/HttpTesterClient.cs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,57 @@ public class HttpTesterClient : IHttpTesterClient, IDisposable
2525
private HttpMethod _httpMethod;
2626
private Dictionary<string, string> _queryParameters = null;
2727
private HttpResponseMessage _responseMessage = null;
28+
2829
/// <summary>
2930
/// Measured HTTP request duration
3031
/// </summary>
3132
public long Duration { get; private set; }
3233

3334
/// <summary>
34-
/// Create HTTP request client
35+
/// Create HTTP request client with or without certificate validation
3536
/// </summary>
36-
/// <param name="baseAddress"></param>
37+
/// <param name="baseAddress">Base address of the API, can be http or https.</param>
38+
/// <param name="validateCertificate">Validate certificate, default is true and it's ignored if http is used.</param>
3739
/// <returns></returns>
38-
public IHttpTesterClient CreateHttpRequest(Uri baseAddress)
40+
public IHttpTesterClient CreateHttpRequest(Uri baseAddress, bool validateCertificate = true)
3941
{
40-
HttpClient = new HttpClient
42+
if (!validateCertificate &&
43+
(baseAddress.Scheme == Uri.UriSchemeHttp || baseAddress.Scheme == Uri.UriSchemeHttps))
44+
{
45+
NonValidatingClient(baseAddress);
46+
}
47+
else
48+
{
49+
ValidatingClient(baseAddress);
50+
}
51+
52+
return this;
53+
}
54+
55+
private void ValidatingClient(Uri baseAddress)
56+
{
57+
HttpClient = new HttpClient()
4158
{
4259
BaseAddress = baseAddress
4360
};
61+
}
4462

45-
return this;
63+
private void NonValidatingClient(Uri baseAddress)
64+
{
65+
var handler = new HttpClientHandler
66+
{
67+
ClientCertificateOptions = ClientCertificateOption.Manual,
68+
ServerCertificateCustomValidationCallback =
69+
(httpRequestMessage, cert, cetChain, policyErrors) =>
70+
{
71+
return true;
72+
}
73+
};
74+
75+
HttpClient = new HttpClient(handler)
76+
{
77+
BaseAddress = baseAddress
78+
};
4679
}
4780

4881
/// <summary>

src/QAToolKit.Engine.HttpTester/IHttpTesterClient.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ public interface IHttpTesterClient
1414
/// Create HTTP request client
1515
/// </summary>
1616
/// <param name="baseAddress"></param>
17+
/// <param name="validateCertificate"></param>
1718
/// <returns></returns>
18-
IHttpTesterClient CreateHttpRequest(Uri baseAddress);
19+
IHttpTesterClient CreateHttpRequest(Uri baseAddress, bool validateCertificate);
1920
/// <summary>
2021
/// Add URL path to the HTTP client
2122
/// </summary>

src/QAToolKit.Engine.HttpTester/QAToolKit.Engine.HttpTester.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
</Description>
1717
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
1818
<PackageLicenseFile>LICENSE</PackageLicenseFile>
19-
<PackageProjectUrl>https://github.com/qatoolkit/qatoolkit-core-net</PackageProjectUrl>
19+
<PackageProjectUrl>https://github.com/qatoolkit/qatoolkit-engine-httptester-net</PackageProjectUrl>
2020
<PackageIcon>qatoolkit-64x64.png</PackageIcon>
2121
<RepositoryUrl>https://github.com/qatoolkit/qatoolkit-core-net</RepositoryUrl>
22-
<PackageTags>qatoolkit-core-net;.net;c#;f#;dotnet;netstandard;net5</PackageTags>
23-
<Configurations>Debug;Release;Debug With Project References</Configurations>
22+
<PackageTags>qatoolkit-engine-httptester-net;.net;c#;f#;dotnet;netstandard;net5</PackageTags>
23+
<Configurations>Debug;Release</Configurations>
2424
</PropertyGroup>
2525

2626
<PropertyGroup>

0 commit comments

Comments
 (0)