ASP.NET Coreバックエンドからsolvethreeを呼び出す
型付きHttpClientを登録し、タスクを一度だけ作成してから、有限の期限を設けてステータスを取得します。APIキーはサーバー側に保持し、クライアントを呼び出すアプリケーションのルートを保護してください。
以下のサンプルはreCAPTCHA Enterprise用のRESTヘルパーであり、公式C# SDKではありません。タスクの作成と取得を分離しているため、解決が完了するまでアプリケーションが1つの受信リクエストを開いたままにする必要はありません。
このページの内容
型付きクライアントを登録する
まず、コンソールでワークスペースの対象サイトのプロファイルを有効にします。ホスト名とアクションを送信しても、プロファイルは作成されません。サイトがまだ設定されていない場合は、サイトプロファイルの設定を参照してください。
ワークスペースのキーを、サーバー設定に SOLVETHREE_API_KEY として保存します。クライアントクラスを追加し、Program.cs の下に示す登録コードのコメントを解除して、builder.Build() より前に配置してください。
// CaptchaClient.cs; .NET 8+, System.Net.Http.Json and System.Text.Json.Nodes.
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json.Nodes;
public sealed class CaptchaClient(HttpClient http)
{
public async Task<JsonObject> CreateAsync(string site, string proxy, string requestId,
CancellationToken cancellationToken)
{
using var response = await http.PostAsJsonAsync("tasks?waitMs=0",
new { site, action = "login", proxy, requestId }, cancellationToken);
response.EnsureSuccessStatusCode();
return (await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken))!;
}
public async Task<JsonObject> GetAsync(string id, CancellationToken cancellationToken)
{
using var response = await http.GetAsync("tasks/" + Uri.EscapeDataString(id) + "?waitMs=15000",
cancellationToken);
response.EnsureSuccessStatusCode();
return (await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken))!;
}
}
// Program.cs, before builder.Build(), in an existing authenticated ASP.NET app:
// builder.Services.AddHttpClient<CaptchaClient>(http => {
// http.BaseAddress = new Uri("https://api.solvethree.com/v1/");
// http.Timeout = TimeSpan.FromSeconds(25);
// http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
// "Bearer", builder.Configuration["SOLVETHREE_API_KEY"]
// ?? throw new InvalidOperationException("Missing API key"));
// }).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler {
// AllowAutoRedirect = false
// });
// Inject CaptchaClient into your authenticated controller/service. Pass its
// cancellation token, create once, save id and poll GetAsync with a finite deadline.この登録では、APIのベースアドレス、Bearer認証、25秒の通信タイムアウトを設定し、自動リダイレクトを無効にします。ベースアドレス末尾のスラッシュは残してください。クライアントの相対パス tasks は、/v1/ 配下に解決される必要があります。
このヘルパーはHttpClientのJSON拡張機能を使用し、JsonObject を返します。両メソッドとも、デシリアライズ前にHTTPレスポンスが成功であることを確認します。認証済みのコントローラーまたはサービスに CaptchaClient を注入してください。ヘルパー自体は、アプリケーションの呼び出し元に対する認証や認可を行いません。
一度だけ作成し、復旧情報を保存する
- 1.
サイト、アクション、プロキシを選ぶ
siteには完全なURLではなく、対象のホスト名を渡します。このサンプルではactionをloginに固定しています。送信先が想定するアクションに変更してください。プロキシを1つ送信し、デフォルトのenterprise-v3 reCAPTCHAモードを使用します。typeフィールドやurlフィールドは追加しないでください。
- 2.
CreateAsyncを呼び出す前にrequestIdを保存する
ASCIIの英字、数字、アンダースコア、ハイフンからなる1–64文字を使用します。レスポンスが失われた場合に同じ論理タスクを復旧できるよう、正確なタスク入力値とともに保存してください。
- 3.
CreateAsyncを呼び出し、返されたタスクIDを保存する
CreateAsyncはwaitMs=0を指定してPOSTを1回実行します。呼び出し元のCancellationTokenを渡してください。タスクIDを取得したら、新たなタスクを作成せず、GetAsyncでそのタスクを取得します。
ワークスペースのクレジットを消費する権限は、アプリケーションの認可チェックで制御してください。これらの値を受信リクエストから取得する場合は、要求されたサイト、アクション、プロキシが、その呼び出し元に許可された範囲内であることを検証します。
全体の期限を設けてポーリングする
GetAsyncは既知のタスクIDをエスケープし、waitMs=15000を指定してリクエストします。HttpClientの25秒のタイムアウトは各HTTPリクエストを制限するものであり、アプリケーションがポーリングに費やす合計時間は制限しません。全体の期限を別途設定し、すべての呼び出しにキャンセルを伝播させてください。
pendingまたはsolving:ポーリングの期限内で、呼び出し元によるキャンセルがない間だけ続行します。ready:ポーリングを停止し、ソリューションを読み取ります。使用可能なソリューションがあるのは、このステータスだけです。failed:ポーリングを停止してerrorCodeとerrorを確認してください。
ブラウザー向けのアプリケーションでは、タスクが完了するまで1つの受信リクエスト内でループせず、作成とその後のステータス確認を、個別の保護された操作として扱ってください。ローカルの期限が切れてもタスクIDを保持し、後で認可されたリクエストから取得できるようにします。
トークンを本来の送信先に送信するときは、ソリューションが返したuserAgentとsecChUaの識別情報、および解決時と同じプロキシを使用してください。準備完了のタスクは、ソリューションが生成されたことを意味するだけで、アプリケーションのリクエストが成功したことを意味しません。
重複処理を作らずにタイムアウトから復旧する
- IDを受け取る前にCreateAsyncがタイムアウトするか、キャンセルされる。
サーバー側ではすでにタスクが作成されている可能性があります。ローカルでキャンセルしても、リモートの処理はキャンセルされません。
試してみましょう: 保存したrequestIdを使い、同じタスク入力値を再送して復旧します。同じIDと入力値であれば、既存のタスクが返されます。そのIDを再利用しながら入力値を変更すると、競合が発生します。
- GetAsyncがタイムアウトするか、ポーリングの期限が切れる。
タスクIDはすでに取得しているため、レスポンスがなくても代わりのタスクを作成する必要はありません。
試してみましょう: IDを保持し、後で新たに期限を設けた操作内でそのタスクを取得します。
- HTTP呼び出しが成功以外のレスポンスを返す。
EnsureSuccessStatusCodeは、ヘルパーが成功時のペイロードを読み取る前に例外をスローします。これは、ステータスがfailedのタスクを受け取ることとは異なります。
試してみましょう: HTTPエラーは別途処理してください。無効な入力値をそのまま再試行せず、修正してください。
- タスクが failed になる。
タスクの失敗については、errorCodeとerrorを確認してください。site-unreachableなどが該当します。
試してみましょう: そのタスクのポーリングを停止し、別の解決処理を開始する前に、報告された原因に対処してください。
APIリクエストの拒否と、解決処理の最終的な失敗を区別する必要がある場合は、APIエラーガイドを参照してください。
参照元とAPIリファレンス
最初のタスクを実行しましょう。
$5のワークスペースクレジットで始められます。