価格スクレイピング
以下のテンプレートを使用して、製品の詳細が表示されるWorkersのデモアプリケーションを作成できますが、価格情報はTurnstileウィジェットが解決されるまで公開されません。
以下のスクリプトは、ルートパス <YOUR-HOSTNAME-HERE>/ }} に適用され、Turnstileウィジェットが埋め込まれるページを提供します。
const someHTML = `<head> <title>Turnstile価格スクレイピングデモ</title> <script src="https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback" async defer></script> <script src="<YOUR-HOSTNAME-HERE>/pricing.js"></script></head><body> <h3>価格:</h3> <div id="price-box"></div> <div class="cf-turnstile" id="price-widget"></div></body>`
export default { async fetch(request, env, ctx) { let returnHTMLResponse = new Response(someHTML); returnHTMLResponse.headers.set('content-type','text/html') return returnHTMLResponse },};以下のスクリプトは、ルート <YOUR-HOSTNAME-HERE>/pricing.js に適用され、Turnstileウィジェットを埋め込むクライアントスクリプトを返します。
const clientScript = `async function getPrice(token){ // 価格情報を取得するためのエンドポイント const priceInfoURL = "/get-price" // 価格情報を追加する要素のID const priceBox = document.getElementById('price-box');
// Turnstileサーバーサイドバリデーションで保護された価格エンドポイントからの応答を待つ const response = await fetch( priceInfoURL, { headers : { 'cf-token' : token } } ); // 価格エンドポイントからの価格情報を待つ const price = await response.json(); // コールバックで返された価格情報を設定する priceBox.innerText = price.pricing}function init(){ window.onloadTurnstileCallback = function () { turnstile.render('#price-widget', { sitekey: '<YOUR-SITEKEY-GOES-HERE>', callback: function(token) { getPrice(token) }, }); };}window.addEventListener ?window.addEventListener("load", init, false) :window.attachEvent && window.attachEvent("onload", init)` export default { async fetch(request, env, ctx) { if(clientScript == null || undefined){ let response = new Response("// スクリプトが利用できません!") const { headers } = response; headers.append('content-type', 'application/javascript'); return response; } else { let response = new Response(clientScript); const { headers } = response; headers.append('content-type', 'application/javascript'); return response; } }};以下のスクリプトは、ルート <YOUR-HOSTNAME-HERE>/get-price に適用され、Turnstileトークンを検証し、APIまたはJSON形式の価格応答を返します。
// これはデモ用の秘密鍵です。本番環境では、// 秘密鍵を安全に保管することをお勧めします。const SECRET_KEY = '<SECRET-KEY>';
async function handlePost(request) {
const token = request.headers.get('cf-token'); const ip = request.headers.get('CF-Connecting-IP');
// "/siteverify" APIエンドポイントを呼び出してトークンを検証します。 let formData = new FormData(); formData.append('secret', SECRET_KEY); formData.append('response', token); formData.append('remoteip', ip);
const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'; const result = await fetch(url, { body: formData, method: 'POST' });
const outcome = await result.json();
// これは特定のユースケースに合わせてカスタマイズできる条件ブロックです if (outcome.success) {
// トークン検証成功のロジック
// この例では静的変数を使用していますが、KVを使用すればカタログリストを参照できます let response = new Response('{"pricing":"$99.99"}'); response.headers.append("content-type", "application/json"); return response;
} else {
// トークン検証失敗のロジック
let response = new Response('{"pricing":"$XX.XX"}') response.headers.append("content-type", "application/json"); return response;
}
}
export default { async fetch(request, env, ctx) { try { return await handlePost(request) } catch(error){ return new Response(`{"err":"${error}"}`); } },};