diff --git a/DevBase.Net/Core/BaseRequest.cs b/DevBase.Net/Core/BaseRequest.cs
index 3f0c66b..ed154fc 100644
--- a/DevBase.Net/Core/BaseRequest.cs
+++ b/DevBase.Net/Core/BaseRequest.cs
@@ -1,3 +1,4 @@
+using System.Net;
using System.Text;
using DevBase.Net.Configuration;
using DevBase.Net.Data.Body;
@@ -20,6 +21,8 @@ public abstract class BaseRequest : IDisposable, IAsyncDisposable
protected bool _validateCertificates = true;
protected bool _followRedirects = true;
protected int _maxRedirects = 50;
+ protected Version _httpVersion = new Version(3, 0);
+ protected HttpVersionPolicy _httpVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
protected bool _isBuilt;
protected bool _disposed;
@@ -66,6 +69,16 @@ public abstract class BaseRequest : IDisposable, IAsyncDisposable
///
public int MaxRedirects => this._maxRedirects;
+ ///
+ /// Gets the HTTP version for this request.
+ ///
+ public Version HttpVersion => this._httpVersion;
+
+ ///
+ /// Gets the HTTP version policy for this request.
+ ///
+ public HttpVersionPolicy HttpVersionPolicy => this._httpVersionPolicy;
+
///
/// Gets whether the request has been built.
///
diff --git a/DevBase.Net/Core/RequestConfiguration.cs b/DevBase.Net/Core/RequestConfiguration.cs
index 70af202..71728ca 100644
--- a/DevBase.Net/Core/RequestConfiguration.cs
+++ b/DevBase.Net/Core/RequestConfiguration.cs
@@ -274,4 +274,36 @@ public Request WithResponseInterceptor(IResponseInterceptor interceptor)
this._responseInterceptors.Add(interceptor);
return this;
}
+
+ ///
+ /// Sets the HTTP version for the request.
+ ///
+ /// The HTTP version to use.
+ /// The version policy. Default is RequestVersionOrLower.
+ /// The request instance for method chaining.
+ public Request WithHttpVersion(Version version, HttpVersionPolicy policy = HttpVersionPolicy.RequestVersionOrLower)
+ {
+ ArgumentNullException.ThrowIfNull(version);
+ this._httpVersion = version;
+ this._httpVersionPolicy = policy;
+ return this;
+ }
+
+ ///
+ /// Configures the request to use HTTP/1.1.
+ ///
+ /// The request instance for method chaining.
+ public Request AsHttp11() => this.WithHttpVersion(System.Net.HttpVersion.Version11);
+
+ ///
+ /// Configures the request to use HTTP/2.
+ ///
+ /// The request instance for method chaining.
+ public Request AsHttp2() => this.WithHttpVersion(System.Net.HttpVersion.Version20);
+
+ ///
+ /// Configures the request to use HTTP/3.
+ ///
+ /// The request instance for method chaining.
+ public Request AsHttp3() => this.WithHttpVersion(System.Net.HttpVersion.Version30);
}
diff --git a/DevBase.Net/Core/RequestHttp.cs b/DevBase.Net/Core/RequestHttp.cs
index b36f37e..7b76621 100644
--- a/DevBase.Net/Core/RequestHttp.cs
+++ b/DevBase.Net/Core/RequestHttp.cs
@@ -132,8 +132,8 @@ public override async Task SendAsync(CancellationToken cancellationTok
metricsBuilder.SetProxy(this._proxy != null, this._proxy?.Key);
using HttpRequestMessage httpRequest = this.ToHttpRequestMessage();
- httpRequest.Version = new Version(3, 0);
- httpRequest.VersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
+ httpRequest.Version = this._httpVersion;
+ httpRequest.VersionPolicy = this._httpVersionPolicy;
metricsBuilder.MarkConnectStart();
HttpResponseMessage httpResponse = await client.SendAsync(httpRequest,
@@ -284,6 +284,8 @@ private string BuildClientKey()
sb.Append(this._validateCertificates);
sb.Append("|redirect:");
sb.Append(this._followRedirects);
+ sb.Append("|httpver:");
+ sb.Append(this._httpVersion);
return sb.ToStringAndRelease();
}
diff --git a/DevBase.Net/DevBase.Net.csproj b/DevBase.Net/DevBase.Net.csproj
index d3da0fe..5d8a7e1 100644
--- a/DevBase.Net/DevBase.Net.csproj
+++ b/DevBase.Net/DevBase.Net.csproj
@@ -15,7 +15,7 @@
https://github.com/AlexanderDotH/DevBase.git
https://github.com/AlexanderDotH/DevBase.git
git
- 1.3.2
+ 1.4.0
MIT
false
http;client;requests;proxy;socks5;jwt;authentication;fluent-api;async;retry;rate-limiting;json;html-parsing
diff --git a/DevBase.Test/DevBaseRequests/RequestTest.cs b/DevBase.Test/DevBaseRequests/RequestTest.cs
index 1822ea0..8936e33 100644
--- a/DevBase.Test/DevBaseRequests/RequestTest.cs
+++ b/DevBase.Test/DevBaseRequests/RequestTest.cs
@@ -577,6 +577,89 @@ public async Task DisposeAsync_ClearsInterceptors()
#endregion
+ #region HTTP Version Tests
+
+ [Test]
+ public void WithHttpVersion_SetsHttpVersion()
+ {
+ var request = new Request("https://example.com")
+ .WithHttpVersion(HttpVersion.Version20);
+
+ Assert.That(request.HttpVersion, Is.EqualTo(HttpVersion.Version20));
+ }
+
+ [Test]
+ public void WithHttpVersion_WithPolicy_SetsBoth()
+ {
+ var request = new Request("https://example.com")
+ .WithHttpVersion(HttpVersion.Version20, HttpVersionPolicy.RequestVersionExact);
+
+ Assert.That(request.HttpVersion, Is.EqualTo(HttpVersion.Version20));
+ Assert.That(request.HttpVersionPolicy, Is.EqualTo(HttpVersionPolicy.RequestVersionExact));
+ }
+
+ [Test]
+ public void AsHttp11_SetsHttpVersion11()
+ {
+ var request = new Request("https://example.com")
+ .AsHttp11();
+
+ Assert.That(request.HttpVersion, Is.EqualTo(HttpVersion.Version11));
+ }
+
+ [Test]
+ public void AsHttp2_SetsHttpVersion20()
+ {
+ var request = new Request("https://example.com")
+ .AsHttp2();
+
+ Assert.That(request.HttpVersion, Is.EqualTo(HttpVersion.Version20));
+ }
+
+ [Test]
+ public void AsHttp3_SetsHttpVersion30()
+ {
+ var request = new Request("https://example.com")
+ .AsHttp3();
+
+ Assert.That(request.HttpVersion, Is.EqualTo(HttpVersion.Version30));
+ }
+
+ [Test]
+ public void DefaultHttpVersion_IsHttp3()
+ {
+ var request = new Request("https://example.com");
+
+ Assert.That(request.HttpVersion, Is.EqualTo(HttpVersion.Version30));
+ Assert.That(request.HttpVersionPolicy, Is.EqualTo(HttpVersionPolicy.RequestVersionOrLower));
+ }
+
+ [Test]
+ public void HttpVersion_CanBeSwitchedMultipleTimes()
+ {
+ var request = new Request("https://example.com")
+ .AsHttp3()
+ .AsHttp2()
+ .AsHttp11();
+
+ Assert.That(request.HttpVersion, Is.EqualTo(HttpVersion.Version11));
+ }
+
+ [Test]
+ public void FluentApi_WithHttpVersion_ChainsCorrectly()
+ {
+ var request = new Request("https://example.com")
+ .AsPost()
+ .AsHttp2()
+ .WithHeader("X-Test", "Value")
+ .Build();
+
+ Assert.That(request.Method, Is.EqualTo(HttpMethod.Post));
+ Assert.That(request.HttpVersion, Is.EqualTo(HttpVersion.Version20));
+ }
+
+ #endregion
+
#region Fluent API Tests
[Test]
diff --git a/DevBaseLive/Program.cs b/DevBaseLive/Program.cs
index 0d30afe..cea1978 100644
--- a/DevBaseLive/Program.cs
+++ b/DevBaseLive/Program.cs
@@ -15,13 +15,6 @@
namespace DevBaseLive;
-///
-/// Represents a person record.
-///
-/// The name of the person.
-/// The age of the person.
-record Person(string name, int age);
-
///
/// Entry point class for the DevBaseLive application.
///
@@ -34,41 +27,38 @@ class Program
/// Command line arguments.
public static async Task Main(string[] args)
{
- Person p = new Person("alex", 1);
-
var l = new LoggerConfiguration()
.WriteTo.Console()
.MinimumLevel.Information()
.CreateLogger();
- for (int i = 0; i < 20; i++)
- {
- Request request = new Request()
- .AsGet()
- .WithHostCheck(new HostCheckConfig())
- .UseBasicAuthentication("joe", "mama")
- .WithRetryPolicy(new RetryPolicy()
- {
- MaxRetries = 2
- })
- .WithLogging(new LoggingConfig()
- {
- Logger = l
- })
- .WithMultipleFiles(
- ("file1", AFile.ReadFileToObject("C:\\Users\\alex\\Desktop\\zoom1.txt")),
- ("file2", AFile.ReadFileToObject("C:\\Users\\alex\\Desktop\\zoom2.txt"))
- )
+
+
+ Request request = new Request()
+ .AsGet()
+ .WithHostCheck(new HostCheckConfig())
+ .UseBasicAuthentication("joe", "mama")
+ .WithRetryPolicy(new RetryPolicy()
+ {
+ MaxRetries = 2
+ })
+ .WithLogging(new LoggingConfig()
+ {
+ Logger = l
+ })
+ .WithMultipleFiles(
+ ("file1", AFile.ReadFileToObject("C:\\Users\\alex\\Desktop\\zoom1.txt")),
+ ("file2", AFile.ReadFileToObject("C:\\Users\\alex\\Desktop\\zoom2.txt"))
+ )
- .WithScrapingBypass(new ScrapingBypassConfig()
- {
- BrowserProfile = EnumBrowserProfile.Firefox
- }).WithHeader("sec-fetch-mode", "yoemamam")
- .WithUrl("https://webhook.site/bd100268-d633-43f5-b298-28ee17c97ccf");
- Response response = await request.SendAsync();
+ .WithScrapingBypass(new ScrapingBypassConfig()
+ {
+ BrowserProfile = EnumBrowserProfile.Firefox
+ }).WithHeader("sec-fetch-mode", "yoemamam")
+ .WithUrl("https://webhook.site/bd100268-d633-43f5-b298-28ee17c97ccf");
+ Response response = await request.SendAsync();
- string data = await response.GetStringAsync();
- data.DumpConsole();
- }
+ string data = await response.GetStringAsync();
+ data.DumpConsole();
}
}
\ No newline at end of file