diff --git a/src/FlareSolverrSharp/ClearanceHandler.cs b/src/FlareSolverrSharp/ClearanceHandler.cs
index e166383..a1e37f8 100644
--- a/src/FlareSolverrSharp/ClearanceHandler.cs
+++ b/src/FlareSolverrSharp/ClearanceHandler.cs
@@ -20,6 +20,7 @@ public class ClearanceHandler : DelegatingHandler
{
private readonly HttpClient _client;
private readonly string _flareSolverrApiUrl;
+ private readonly IFlaresolverrResponseStorage _responseStorage;
private FlareSolverr _flareSolverr;
private string _userAgent;
@@ -42,6 +43,17 @@ public class ClearanceHandler : DelegatingHandler
/// FlareSolverr API URL. If null or empty it will detect the challenges, but
/// they will not be solved. Example: "http://localhost:8191/"
public ClearanceHandler(string flareSolverrApiUrl)
+ : this(flareSolverrApiUrl, new DefaultFlaresolverrResponseStorage())
+ {
+ }
+
+ ///
+ /// Creates a new instance of the .
+ ///
+ /// FlareSolverr API URL. If null or empty it will detect the challenges, but
+ /// they will not be solved. Example: "http://localhost:8191/"
+ /// Storage to persist challenge responses.
+ public ClearanceHandler(string flareSolverrApiUrl, IFlaresolverrResponseStorage responseStorage)
: base(new HttpClientHandler())
{
// Validate URI
@@ -50,6 +62,7 @@ public ClearanceHandler(string flareSolverrApiUrl)
throw new FlareSolverrException("FlareSolverr URL is malformed: " + flareSolverrApiUrl);
_flareSolverrApiUrl = flareSolverrApiUrl;
+ _responseStorage = responseStorage;
_client = new HttpClient(new HttpClientHandler
{
@@ -84,36 +97,64 @@ protected override async Task SendAsync(HttpRequestMessage
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
// Detect if there is a challenge in the response
- if (ChallengeDetector.IsClearanceRequired(response))
+ if (!ChallengeDetector.IsClearanceRequired(response))
{
- if (_flareSolverr == null)
- throw new FlareSolverrException("Challenge detected but FlareSolverr is not configured");
+ return response;
+ }
- // Resolve the challenge using FlareSolverr API
- var flareSolverrResponse = await _flareSolverr.Solve(request);
+ if (_flareSolverr == null)
+ throw new FlareSolverrException("Challenge detected but FlareSolverr is not configured");
+
+ // Check if saved response exists.
+ var flareSolverrResponse = await _responseStorage.LoadAsync();
- // Save the FlareSolverr User-Agent for the following requests
- var flareSolverUserAgent = flareSolverrResponse.Solution.UserAgent;
- if (flareSolverUserAgent != null && !flareSolverUserAgent.Equals(request.Headers.UserAgent.ToString()))
+ if (flareSolverrResponse != null)
+ {
+ // Set user agent
+ if (flareSolverrResponse.Solution.UserAgent != null &&
+ !flareSolverrResponse.Solution.UserAgent.Equals(request.Headers.UserAgent.ToString()))
{
- _userAgent = flareSolverUserAgent;
-
- // Set the User-Agent if required
+ _userAgent = flareSolverrResponse.Solution.UserAgent;
SetUserAgentHeader(request);
}
- // Change the cookies in the original request with the cookies provided by FlareSolverr
+ // Retry request with saved response
InjectCookies(request, flareSolverrResponse);
response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
- // Detect if there is a challenge in the response
- if (ChallengeDetector.IsClearanceRequired(response))
- throw new FlareSolverrException("The cookies provided by FlareSolverr are not valid");
+ if (!ChallengeDetector.IsClearanceRequired(response))
+ {
+ // Success with saved response.
+ InjectSetCookieHeader(response, flareSolverrResponse);
+ return response;
+ }
+ }
+
+ // Resolve the challenge using FlareSolverr API
+ flareSolverrResponse = await _flareSolverr.Solve(request);
+
+ // Save the FlareSolverr User-Agent for the following requests
+ var flareSolverUserAgent = flareSolverrResponse.Solution.UserAgent;
+ if (flareSolverUserAgent != null && !flareSolverUserAgent.Equals(request.Headers.UserAgent.ToString()))
+ {
+ _userAgent = flareSolverUserAgent;
- // Add the "Set-Cookie" header in the response with the cookies provided by FlareSolverr
- InjectSetCookieHeader(response, flareSolverrResponse);
+ // Set the User-Agent if required
+ SetUserAgentHeader(request);
}
+ // Change the cookies in the original request with the cookies provided by FlareSolverr
+ InjectCookies(request, flareSolverrResponse);
+ response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
+
+ // Detect if there is a challenge in the response
+ if (ChallengeDetector.IsClearanceRequired(response))
+ throw new FlareSolverrException("The cookies provided by FlareSolverr are not valid");
+
+ // Add the "Set-Cookie" header in the response with the cookies provided by FlareSolverr
+ InjectSetCookieHeader(response, flareSolverrResponse);
+ await _responseStorage.SaveAsync(flareSolverrResponse);
+
return response;
}
diff --git a/src/FlareSolverrSharp/FlaresolverrResponseStorage.cs b/src/FlareSolverrSharp/FlaresolverrResponseStorage.cs
new file mode 100644
index 0000000..90703c2
--- /dev/null
+++ b/src/FlareSolverrSharp/FlaresolverrResponseStorage.cs
@@ -0,0 +1,24 @@
+using System.Threading.Tasks;
+using FlareSolverrSharp.Types;
+
+namespace FlareSolverrSharp
+{
+ public interface IFlaresolverrResponseStorage
+ {
+ Task SaveAsync(FlareSolverrResponse result);
+ Task LoadAsync();
+ }
+
+ public class DefaultFlaresolverrResponseStorage : IFlaresolverrResponseStorage
+ {
+ public Task LoadAsync()
+ {
+ return Task.FromResult(null);
+ }
+
+ public Task SaveAsync(FlareSolverrResponse result)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}