استدعاء CAPTCHA API من Cloudflare Workers

بقلم solvethreeمدة القراءة: 3 دقيقة

استخدم Worker لاستدعاء API مهام solvethree باستخدام fetch على جانب الخادم. احتفظ بمفتاح API لمساحة العمل في ربط سري، وثبّت مدخلات الهدف في Worker، ولا تُعد استجابات المهام إلا إلى الجهة المخوّلة المستدعية من تطبيقك.

في هذه الصفحة

إعداد الهدف والأسرار

أولًا، فعّل ملف تعريف الموقع المستهدف لمساحة عملك في لوحة التحكم. إرسال اسم مضيف وإجراء لن ينشئ ملفًا. راجع إعداد ملف تعريف الموقع إذا لم يُستوفَ هذا المتطلب بعد.

  • SOLVETHREE_API_KEY: مفتاح API لمساحة عملك، محفوظ بوصفه سرًا في Worker.
  • INTEGRATION_KEY: سر منفصل يجب أن ترسله الجهة المستدعية من تطبيقك في x-integration-key.
  • SOLVETHREE_PROXY: عنوان URL للوكيل المستخدم للحل. احفظه بوصفه سرًا إذا كان يحتوي على بيانات اعتماد.
  • CAPTCHA_SITE: اسم المضيف المستهدف، وليس عنوان URL كاملًا.

يثبّت المثال الإجراء على login ويوفّر وكيلًا واحدًا. غيّر هذه المدخلات المنشورة لتطابق تكاملك؛ ولا تقبل مدخلات هدف عشوائية من الجهات المستدعية. عند إغفال recaptchaType، تستخدم API افتراضيًا reCAPTCHA Enterprise v3.

استخدم مفتاح التكامل بين جهة مستدعية موثوقة من التطبيق وWorker، وليس في شيفرة متصفح تُوزَّع للعامة. إنه بيانات اعتماد مشتركة، وليس تفويضًا للمهام على مستوى كل مستخدم.

إنشاء المهام واسترجاعها

Worker · استدعاءات REST للإنشاء والاسترجاع مع المصادقة
export default {
  async fetch(request, env) {
    if (!env.INTEGRATION_KEY || request.headers.get('x-integration-key') !== env.INTEGRATION_KEY) {
      return new Response('Unauthorized', { status: 401 });
    }
    const url = new URL(request.url);
    const headers = { Authorization: `Bearer ${env.SOLVETHREE_API_KEY}`, 'Content-Type': 'application/json' };
    let response;
    if (request.method === 'POST') {
      const requestId = request.headers.get('x-request-id');
      if (!requestId || !/^[A-Za-z0-9_-]{1,64}$/.test(requestId)) return new Response('Provide X-Request-ID', { status: 400 });
      response = await fetch('https://api.solvethree.com/v1/tasks?waitMs=0', {
        method: 'POST', headers, redirect: 'error', signal: AbortSignal.timeout(20000),
        body: JSON.stringify({ site: env.CAPTCHA_SITE, action: 'login', proxy: env.SOLVETHREE_PROXY, requestId }),
      });
    } else if (request.method === 'GET') {
      const id = url.searchParams.get('id');
      if (!id || !/^[A-Za-z0-9_-]{1,128}$/.test(id)) return new Response('Provide a valid id', { status: 400 });
      response = await fetch(`https://api.solvethree.com/v1/tasks/${encodeURIComponent(id)}?waitMs=15000`, {
        headers, redirect: 'error', signal: AbortSignal.timeout(25000),
      });
    } else return new Response('Use POST or GET', { status: 405 });
    if (!response.ok) return Response.json({ error: 'Solver API request failed', status: response.status }, { status: response.status });
    return Response.json(await response.json(), { headers: { 'Cache-Control': 'no-store' } });
  },
};
// Store keys in Worker secret bindings. The task proxy field does not add a
// generic HTTP proxy option to Workers fetch; another client must submit through it.
  1. 1.

    إنشاء مهمة

    أرسل طلب POST إلى Worker مع x-integration-key وx-request-id. اختر معرّف طلب يتكون من 1–64 حرفًا أو رقمًا أو شرطة سفلية أو واصلة من ASCII. يبني Worker جسم طلب المهمة من الهدف والوكيل المحددين في إعداداته؛ ولا يستخدم جسم طلب توفّره الجهة المستدعية.

  2. 2.

    الاحتفاظ بمعرّف المهمة

    يُعيد Worker استجابة JSON من خدمة الحل. احفظ معرّف المهمة المُعاد واحتفظ بمعرّف الطلب المستخدم لإنشائها.

  3. 3.

    استرجاع النتيجة

    أرسل طلب GET إلى Worker مع معرّف المهمة في معامل الاستعلام id وترويسة مفتاح التكامل نفسها. يتحقق المعالج من صحة صيغة المعرّف ويسترجع تلك المهمة من solvethree.

تتم مصادقة كلا الطلبين إلى الخدمة باستخدام مفتاح مساحة العمل. يمرّر المعالج رموز حالة HTTP غير الناجحة مع جسم خطأ عام، ويضع Cache-Control: no-store في استجابات JSON الناجحة. ولا يتحقق من ملكية المهمة بما يتجاوز مفتاح التكامل المشترك؛ أضف هذا التفويض قبل إتاحة الاسترجاع لمستخدمين منفصلين.

عالج انتهاء المهل دون إنشاء مهمة أخرى

يستخدم الإنشاء waitMs=0 مع مهلة fetch تبلغ 20 ثانية. ويستخدم الاسترجاع waitMs=15000 مع مهلة fetch تبلغ 25 ثانية. تحدّ هذه القيم من مدة كل استدعاء HTTP، وليس من العمر الكامل للمهمة.

إذا انتهت مهلة الإنشاء قبل تلقي معرّف المهمة، فأعد طلب المهمة نفسه باستخدام معرّف الطلب نفسه. يستردّ ذلك المهمة الحالية إن كانت قد أُنشئت. لا تُنشئ معرّفًا جديدًا لمجرد فشل الاتصال: فقد يكون الطلب الأول قد وصل بالفعل إلى solvethree. تؤدي إعادة استخدام معرّف مع مدخلات مختلفة إلى تعارض.

لا يلتقط المثال استثناءات fetch، بما فيها انتهاء المهلة. أضف معالجة للاستثناءات إذا كانت الجهة المستدعية تحتاج إلى استجابة خطأ منظّمة، لكن أبقِ معرّف الطلب متاحًا للاسترداد.

  • pending أو solving: استرجع المهمة نفسها مجددًا، مع الالتزام بمهلة إجمالية لدى الجهة المستدعية.
  • ready: الحل متاح؛ أوقف الاستقصاء ومرّره إلى عميل الإرسال.
  • failed: أوقف الاستقصاء وافحص errorCode وerror. أصلح المشكلة المُبلّغ عنها قبل إنشاء مهمة أخرى.

خطأ HTTP ومهمة حالتها failed نوعان مختلفان من الإخفاق. يتحقق المعالج من حالة HTTP أولًا؛ لكن يظل على الجهة المستدعية فحص حالة المهمة في الاستجابة الناجحة. للتشخيص، راجع أخطاء CAPTCHA API.

الإرسال عبر عميل يمكنه استخدام الوكيل

يستدعي مثال Worker خدمة solvethree فقط. يخبر الحقل proxy في المهمة خدمة الحل بالوكيل الذي يجب استخدامه؛ ولا يغيّر توجيه شبكة Worker. لا يوفّر fetch في Workers خيارًا عامًا لعنوان URL للوكيل.

أرسل الحل الجاهز إلى عميل يمكنه الإرسال إلى الهدف المقصود عبر الوكيل نفسه. استخدم userAgent وsecChUa المُعادين مع الحل بدلًا من ترويسات متصفح لا صلة لها به. تعني المهمة الجاهزة أن solvethree أنشأ حلًا؛ أما القبول فيعتمد على الطلب اللاحق إلى الهدف.

شغّل مهمتك الأولى.

ابدأ برصيد قدره $5 في مساحة العمل.

إنشاء مساحة عمل
استدعاء CAPTCHA API من Cloudflare Workers · solvethree