@@ -23,11 +23,31 @@ public CloudflareTurnstileService(HttpClient httpClient, IOptions<CloudflareTurn
2323 _logger = logger ;
2424 }
2525
26+ private static Error < CloduflareTurnstileError [ ] > CreateError ( params ReadOnlySpan < CloduflareTurnstileError > errors )
27+ {
28+ return new Error < CloduflareTurnstileError [ ] > ( errors . ToArray ( ) ) ;
29+ }
30+
31+ private static CloduflareTurnstileError MapCfError ( string error )
32+ {
33+ return error switch
34+ {
35+ "missing-input-secret" => CloduflareTurnstileError . MissingSecret ,
36+ "invalid-input-secret" => CloduflareTurnstileError . InvalidSecret ,
37+ "missing-input-response" => CloduflareTurnstileError . MissingResponse ,
38+ "invalid-input-response" => CloduflareTurnstileError . InvalidResponse ,
39+ "bad-request" => CloduflareTurnstileError . BadRequest ,
40+ "timeout-or-duplicate" => CloduflareTurnstileError . TimeoutOrDuplicate ,
41+ "internal-error" => CloduflareTurnstileError . InternalServerError ,
42+ _ => throw new ArgumentOutOfRangeException ( nameof ( error ) , error , null )
43+ } ;
44+ }
45+
2646 /// <inheritdoc />
27- public async Task < OneOf < Success , MissingInput , Error , Error < IReadOnlyList < string > > > > VerifyUserResponseToken (
47+ public async Task < OneOf < Success , Error < CloduflareTurnstileError [ ] > > > VerifyUserResponseToken (
2848 string responseToken , IPAddress ? remoteIpAddress , CancellationToken cancellationToken = default )
2949 {
30- if ( string . IsNullOrEmpty ( responseToken ) ) return new MissingInput ( ) ;
50+ if ( string . IsNullOrEmpty ( responseToken ) ) return CreateError ( CloduflareTurnstileError . MissingResponse ) ;
3151
3252#if DEBUG
3353 if ( responseToken == "dev-bypass" ) return new Success ( ) ;
@@ -46,18 +66,23 @@ public async Task<OneOf<Success, MissingInput, Error, Error<IReadOnlyList<string
4666 using var httpResponse = await _httpClient . PostAsync ( SiteVerifyEndpoint , httpContent , cancellationToken ) ;
4767 if ( ! httpResponse . IsSuccessStatusCode )
4868 {
49- _logger . LogWarning ( "Turnstile error: {StatusCode} {ReasonPhrase}" , httpResponse . StatusCode ,
50- httpResponse . ReasonPhrase ) ;
51- return new Error ( ) ;
69+ _logger . LogError ( "Turnstile error: {StatusCode} {ReasonPhrase}" , httpResponse . StatusCode , httpResponse . ReasonPhrase ) ;
70+
71+ return CreateError ( httpResponse . StatusCode == HttpStatusCode . BadRequest ? CloduflareTurnstileError . BadRequest : CloduflareTurnstileError . InternalServerError ) ;
5272 }
5373
54- var response =
55- await httpResponse . Content . ReadFromJsonAsync < CloudflareTurnstileVerifyResponseDto > (
56- cancellationToken : cancellationToken ) ;
74+ var response = await httpResponse . Content . ReadFromJsonAsync < CloudflareTurnstileVerifyResponseDto > ( cancellationToken ) ;
5775
5876 if ( response . Success ) return new Success ( ) ;
77+
78+ var errors = response . ErrorCodes . Select ( MapCfError ) . ToArray ( ) ;
79+
80+ if ( errors . All ( err => err != CloduflareTurnstileError . InvalidResponse ) )
81+ {
82+ _logger . LogError ( "Turnstile error: {StatusCode} {ReasonPhrase}" , httpResponse . StatusCode , string . Join ( " " , errors . Select ( err => err . ToString ( ) ) ) ) ;
83+ }
5984
60- return new Error < IReadOnlyList < string > > ( response . ErrorCodes ) ;
85+ return CreateError ( errors ) ;
6186 }
6287}
6388
0 commit comments