Skip to content
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
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ Http2Client requires the native TLS library from the original [bogdanfinn/tls-cl
**Installation Instructions:**

1. Download the appropriate library file for your platform from the table above
2. Place the native library in your application's output directory, or
3. Specify the custom path using the `WithLibraryPath()` method in your code
2. Place the native library in your application's output directory, or specify a custom path
3. Initialize the library once at application startup using `Http2Client.Initialize()`

**Example for Windows:**
```csharp
// Initialize once at application startup
Http2Client.Initialize("tls-client-windows-64-1.11.0.dll");

// Create clients as needed
using var client = new HttpClientBuilder()
.WithLibraryPath("tls-client-windows-64-1.11.0.dll")
.Build();
```

Expand All @@ -56,9 +59,11 @@ using Http2Client.Builders;
using Http2Client.Core.Enums;
using Http2Client.Core.Request;

// Initialize native library once at application startup
Http2Client.Initialize("tls-client-windows-64-1.11.0.dll");

// Create an Http2Client instance using the builder
using var client = new HttpClientBuilder()
.WithLibraryPath("tls-client-windows-64-1.11.0.dll")
.WithBrowserType(BrowserType.Chrome133)
.WithUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
.WithTimeout(TimeSpan.FromSeconds(30))
Expand Down Expand Up @@ -118,7 +123,6 @@ using var client = new HttpClientBuilder()

| Method | Description |
|--------|-------------|
| `WithLibraryPath(string)` | Sets the path to the native TLS library. |
| `WithBrowserType(BrowserType)` | Sets the browser fingerprint to mimic. |
| `WithUserAgent(string)` | Sets the User-Agent header. |
| `WithTimeout(TimeSpan)` | Sets the request timeout. |
Expand All @@ -142,8 +146,10 @@ using var client = new HttpClientBuilder()
### Advanced Example

```csharp
// Initialize library once at startup
Http2Client.Initialize("tls-client-windows-64-1.11.0.dll");

using var client = new HttpClientBuilder()
.WithLibraryPath("tls-client-windows-64-1.11.0.dll")
.WithBrowserType(BrowserType.Firefox132)
.WithUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
.WithProxy("http://127.0.0.1:8888", isRotating: true)
Expand Down Expand Up @@ -228,7 +234,6 @@ var request = new HttpRequest

```csharp
using var client = new HttpClientBuilder()
.WithLibraryPath("tls-client-windows-64-1.11.0.dll")
.WithBrowserType(BrowserType.Chrome133)
.Build();

Expand Down Expand Up @@ -265,7 +270,6 @@ var response = client.Send(request);

```csharp
using var client = new HttpClientBuilder()
.WithLibraryPath("tls-client-windows-64-1.11.0.dll")
.WithBrowserType(BrowserType.Chrome133)
.WithProxy("http://proxy.example.com:8080")
.Build();
Expand Down
26 changes: 14 additions & 12 deletions examples/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@

internal class Program
{
private const string PATH_LIB = "Native\\tls-client-windows-64-1.11.0.dll";

private static void Main()
{
//BasicGetRequest();
//PostJsonRequest();
//CookieHandling();
//HeadersAndProxy();
ErrorHandlingAndTimeouts();
Http2Client.Http2Client.Initialize("Native\\tls-client-windows-64-1.11.0.dll");

try
{
BasicGetRequest();
PostJsonRequest();
CookieHandling();
HeadersAndProxy();
ErrorHandlingAndTimeouts();
}
finally
{
Http2Client.Http2Client.Cleanup();
}

Console.ReadLine();
}
Expand All @@ -27,7 +34,6 @@ private static void BasicGetRequest()

using var client = new HttpClientBuilder()
.WithUserAgent("Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36")
.WithLibraryPath(PATH_LIB)
.WithRandomTlsExtensions()
.Build();

Expand All @@ -50,7 +56,6 @@ private static void PostJsonRequest()

using var client = new HttpClientBuilder()
.WithUserAgent("Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36")
.WithLibraryPath(PATH_LIB)
.WithHeader("Content-Type", "application/json")
.WithCookies()
.Build();
Expand Down Expand Up @@ -83,7 +88,6 @@ private static void CookieHandling()

using var client = new HttpClientBuilder()
.WithUserAgent("Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36")
.WithLibraryPath(PATH_LIB)
.WithCookies(true)
.Build();

Expand Down Expand Up @@ -118,7 +122,6 @@ private static void HeadersAndProxy()

using var client = new HttpClientBuilder()
.WithUserAgent("Custom-Agent/1.0")
.WithLibraryPath(PATH_LIB)
.WithHeader("Accept", "application/json")
.WithHeader("Accept-Language", "en-US,en;q=0.9")
.WithHeader("Accept-Encoding", "gzip, deflate, br")
Expand Down Expand Up @@ -150,7 +153,6 @@ private static void ErrorHandlingAndTimeouts()

using var client = new HttpClientBuilder()
.WithUserAgent("Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36")
.WithLibraryPath(PATH_LIB)
.WithTimeout(TimeSpan.FromSeconds(10))
.WithCatchPanics(true)
.WithInsecureSkipVerify(false)
Expand Down
11 changes: 0 additions & 11 deletions src/Builders/HttpClientBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,17 +195,6 @@ public HttpClientBuilder WithRandomTlsExtensions(bool enable = true)
return this;
}

/// <summary>
/// Sets native library path. Auto-detected if not set.
/// </summary>
public HttpClientBuilder WithLibraryPath(string libraryPath)
{
ThrowException.FileNotExists(libraryPath, nameof(libraryPath));

_options.LibraryPath = libraryPath;
return this;
}

/// <summary>
/// Sets User-Agent header.
/// </summary>
Expand Down
40 changes: 29 additions & 11 deletions src/Http2Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ namespace Http2Client;
public sealed class Http2Client : IDisposable
{
private readonly Http2ClientOptions _options;
private readonly NativeWrapper _wrapper;
private bool _disposed;

/// <summary>
Expand All @@ -33,6 +32,11 @@ public sealed class Http2Client : IDisposable
/// </summary>
public bool IsDisposed => _disposed;

/// <summary>
/// True if native library is loaded and ready to use.
/// </summary>
public static bool IsInitialized => NativeWrapper.IsInitialized;

/// <summary>
/// Create client with custom options.
/// </summary>
Expand All @@ -41,7 +45,6 @@ public Http2Client(Http2ClientOptions options)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_options.Validate();
_wrapper = NativeWrapper.Load(_options.LibraryPath);
}

/// <summary>
Expand All @@ -51,6 +54,23 @@ public Http2Client() : this(new Http2ClientOptions())
{
}

/// <summary>
/// Initialize native library once. Call this before creating any Http2Client instances.
/// </summary>
/// <param name="path">Path to native TLS library</param>
public static void Initialize(string path)
{
NativeWrapper.Initialize(path);
}

/// <summary>
/// Cleanup native library resources. Call at application shutdown.
/// </summary>
public static void Cleanup()
{
NativeWrapper.Cleanup();
}

/// <summary>
/// Send HTTP request. Main method for making requests.
/// </summary>
Expand All @@ -67,7 +87,7 @@ public Http2Client() : this(new Http2ClientOptions())

try
{
var responseJson = _wrapper.Request(Serializer.SerializeToBytes(prepared));
var responseJson = NativeWrapper.Request(Serializer.SerializeToBytes(prepared));
response = Serializer.Deserialize<HttpResponse>(responseJson);
return response;
}
Expand All @@ -80,7 +100,7 @@ public Http2Client() : this(new Http2ClientOptions())
// Clean up native memory for this response
if (response != null && !string.IsNullOrEmpty(response.Id))
{
_wrapper.FreeMemory(response.Id);
NativeWrapper.FreeMemory(response.Id);
}
}
}
Expand All @@ -100,7 +120,7 @@ public Http2Client() : this(new Http2ClientOptions())
SessionId = _options.SessionId,
};

var responseJson = _wrapper.GetCookiesFromSession(Serializer.SerializeToBytes(payload));
var responseJson = NativeWrapper.GetCookiesFromSession(Serializer.SerializeToBytes(payload));
return Serializer.Deserialize<CookiesResponse>(responseJson);
}

Expand All @@ -122,7 +142,7 @@ public Http2Client() : this(new Http2ClientOptions())
Cookies = [.. cookies]
};

var responseJson = _wrapper.AddCookiesToSession(Serializer.SerializeToBytes(payload));
var responseJson = NativeWrapper.AddCookiesToSession(Serializer.SerializeToBytes(payload));
return Serializer.Deserialize<CookiesResponse>(responseJson);
}

Expand All @@ -135,7 +155,7 @@ public bool DestroySession()
try
{
var payload = new { sessionId = _options.SessionId };
var responseJson = _wrapper.DestroySession(Serializer.SerializeToBytes(payload));
var responseJson = NativeWrapper.DestroySession(Serializer.SerializeToBytes(payload));
return !string.IsNullOrEmpty(responseJson);
}
catch
Expand All @@ -153,7 +173,7 @@ public bool DestroyAllSessions()
{
try
{
var responseJson = _wrapper.DestroyAllSessions();
var responseJson = NativeWrapper.DestroyAllSessions();
return !string.IsNullOrEmpty(responseJson);
}
catch
Expand Down Expand Up @@ -286,11 +306,9 @@ private void Dispose(bool disposing)
}
catch
{
// If session cleanup fails, we still want to dispose the wrapper
// If session cleanup fails, we still want to continue disposal
// Better to leak a session than crash during disposal
}

_wrapper?.Dispose();
}

_disposed = true;
Expand Down
2 changes: 1 addition & 1 deletion src/Http2Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<Platforms>AnyCPU;x64</Platforms>
<PackageId>Http2Client</PackageId>
<Version>1.1.3</Version>
<Version>1.1.4</Version>
<Authors>Rckov</Authors>
<Company>Rckov</Company>
<Product>Http2Client</Product>
Expand Down
18 changes: 0 additions & 18 deletions src/Http2ClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,6 @@ public class Http2ClientOptions
/// </summary>
public bool WithRandomTlsExtensionOrder { get; set; }

/// <summary>
/// Path to native TLS library. Auto-detected if not specified.
/// </summary>
public string? LibraryPath { get; set; } = GetDefaultLibraryPath();

/// <summary>
/// User-Agent header value.
/// </summary>
Expand All @@ -132,8 +127,6 @@ public string? UserAgent
/// </summary>
public void Validate()
{
ThrowException.FileNotExists(LibraryPath, nameof(LibraryPath));

if (!string.IsNullOrEmpty(ProxyUrl))
{
ThrowException.IsUri(ProxyUrl, nameof(ProxyUrl));
Expand Down Expand Up @@ -178,7 +171,6 @@ public Http2ClientOptions Clone()
WithDefaultCookieJar = WithDefaultCookieJar,
WithoutCookieJar = WithoutCookieJar,
WithRandomTlsExtensionOrder = WithRandomTlsExtensionOrder,
LibraryPath = LibraryPath
};

// Deep copy headers so changes to the clone don't mess with the original
Expand All @@ -189,14 +181,4 @@ public Http2ClientOptions Clone()

return clone;
}

/// <summary>
/// Gets default native library path for current platform.
/// </summary>
private static string GetDefaultLibraryPath()
{
// .dll / .so / .dylib
var extension = PlatformSupport.GetNativeLibraryExtension();
return PlatformSupport.GetRuntimePath($"tls-client.{extension}");
}
}
Loading