استدعاء solvethree من واجهة خلفية تستخدم FastAPI

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

أعِد المهمة بعد إنشائها، لا بعد اكتمال الحل كله. يسترجع المستدعي حالتها حتى تصبح ready أو failed، ثم يرسل الرمز إلى الجهة المستهدفة إذا نجح الحل.

في هذه الصفحة

اضبط الخادم والهدف

استخدم Python 3.10 أو إصدارًا أحدث. ثبّت FastAPI باستخدام python -m pip install "fastapi[standard]"، ثم ثبّت SDK الرسمي باستخدام python -m pip install https://solvethree.com/downloads/solvethree_sdk-0.1.0-py3-none-any.whl.

اضبط متغيرات البيئة التالية في عملية الخادم قبل تشغيل التطبيق:

  • SOLVETHREE_API_KEY: مفتاح API لمساحة عملك. احتفظ به على الخادم؛ يستخدمه SDK للمصادقة لدى solvethree.
  • INTEGRATION_KEY: سر منفصل يرسله المستدعون في الترويسة X-Integration-Key للمصادقة لدى مسارات FastAPI لديك.
  • CAPTCHA_SITE: اسم المضيف المستهدف، وليس عنوان URL كاملًا.
  • SOLVETHREE_PROXY: عنوان URL لوكيل HTTP أو HTTPS المستخدم لهذه المهمة، دون مسار أو استعلام أو جزء fragment.

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

إضافة مسارات FastAPI وتشغيلها

احفظ هذا المثال باسم main.py. يتطلب كلا المسارين X-Integration-Key. يبني مسار الإنشاء مهمته بالكامل من إعدادات الخادم؛ ولا يقدّم المستدعون الموقع أو الإجراء أو الوكيل في متن الطلب.

FastAPI · تشغيل SDK المتزامن ضمن تجمّع خيوط تنفيذ
# pip install "fastapi[standard]" and the official solvethree SDK wheel.
import hmac
import os
from fastapi import FastAPI, HTTPException, Request
from fastapi.concurrency import run_in_threadpool
from solvethree import Solvethree, SolvethreeError

app = FastAPI()

def authorize(request):
    if not hmac.compare_digest(request.headers.get("x-integration-key", ""), os.environ["INTEGRATION_KEY"]):
        raise HTTPException(status_code=401, detail="Unauthorized")

@app.post("/captcha/tasks")
async def create(request: Request):
    authorize(request)
    task = {"site": os.environ["CAPTCHA_SITE"], "action": "login", "proxy": os.environ["SOLVETHREE_PROXY"]}
    if request.headers.get("x-request-id"):
        task["requestId"] = request.headers["x-request-id"]
    def submit():
        return Solvethree(os.environ["SOLVETHREE_API_KEY"]).create_task(task, wait_ms=0, timeout=20)
    try:
        return await run_in_threadpool(submit)
    except ValueError:
        raise HTTPException(status_code=400, detail="Invalid task input")
    except SolvethreeError as error:
        raise HTTPException(status_code=502, detail={"requestId": error.request_id, "taskId": error.task_id})

@app.get("/captcha/tasks/{task_id}")
async def retrieve(task_id: str, request: Request):
    authorize(request)
    def fetch():
        return Solvethree(os.environ["SOLVETHREE_API_KEY"]).get_task(task_id, wait_ms=15000, timeout=25)
    try:
        return await run_in_threadpool(fetch)
    except ValueError:
        raise HTTPException(status_code=400, detail="Invalid task ID")
    except SolvethreeError as error:
        raise HTTPException(status_code=502, detail={"requestId": error.request_id, "taskId": error.task_id})

تستخدم المهمة reCAPTCHA Enterprise v3 افتراضيًا. وترسل site وaction وproxy واحدًا، دون حقل type أو url.

إن SDK الخاص بـ Python متزامن. واستدعاؤه مباشرة داخل async def سيحجب حلقة الأحداث، لذا يستخدم كلا المعالجين run_in_threadpool. يستخدم الإنشاء wait_ms=0 مع مهلة طلب SDK تبلغ 20 ثانية؛ ويسمح الاسترجاع بانتظار 15 ثانية مع مهلة طلب SDK تبلغ 25 ثانية. لا ينتظر أي من المعالجين اكتمال الحل كله باستخدام client.solve.

للتطوير المحلي، شغّل fastapi dev main.py من المجلد الذي يحتوي على الملف. المساران هما POST http://127.0.0.1:8000/captcha/tasks وGET http://127.0.0.1:8000/captcha/tasks/{task_id}. يكتشف FastAPI الكائن app؛ ولا يوجد URLconf منفصل لتسجيله.

إنشاء مهمة واسترجاعها واستعادة الطلبات المنقطعة

  1. 1.

    أنشئ مرة واحدة بمعرّف طلب ثابت

    أرسل POST /captcha/tasks مع X-Integration-Key وقيمة X-Request-ID تحتفظ بها لهذه المهمة المنطقية. يجب أن يحتوي معرّف الطلب على 1–64 حرفًا من حروف ASCII أو الأرقام أو الشرطات السفلية أو الشرطات. يمرّره المسار إلى solvethree باسم requestId. احفظ معرّف المهمة المُعاد.

  2. 2.

    تحقّق من حالة HTTP قبل قراءة حالة المهمة

    يعيد الغلاف 401 عند فشل المصادقة، و400 عند أخطاء المدخلات من نوع ValueError، و502 عند التقاط استثناءات SolvethreeError. تتضمن تفاصيل استجابة 502 قيمتي requestId وtaskId من خطأ SDK. عالج خطأ HTTP هذا قبل التعامل مع الاستجابة على أنها مهمة.

  3. 3.

    استرجاع المهمة الحالية

    استدعِ GET /captcha/tasks/{task_id} مع X-Integration-Key. افحص status بعد كل استجابة HTTP ناجحة. قد يعيد الاسترجاع مهمة لم تصل إلى حالة نهائية حتى بعد انتهاء انتظاره؛ استرجع المهمة نفسها مجددًا بدلًا من إنشاء أخرى.

  4. 4.

    استعادة طلب إنشاء غير مؤكّد النتيجة

    إذا انتهت مهلة الإنشاء وكان لديك معرّف مهمة، فاسترجعها. وإلا، فكرّر POST باستخدام X-Request-ID الأصلي ومدخلات المهمة نفسها على الخادم دون تغيير. تؤدي إعادة استخدام ذلك المعرّف مع المهمة نفسها إلى إعادة المهمة الحالية؛ أما تغيير المدخلات فيؤدي إلى تعارض. احتفظ بالمعرّف الأصلي منفصلًا بدلًا من استبداله بقيمة requestId الواردة في استجابة خطأ.

ما يجب فعله بعد استجابة HTTP ناجحة
ما يجب فعله بعد استجابة HTTP ناجحة
حالة المهمةإجراء المستدعي
قيد الانتظار أو جارٍ الحلواصل استرجاع المهمة نفسها. لا يوجد حل قابل للاستخدام بعد.
readyاقرأ solution وجهّز الطلب إلى الجهة المستهدفة.
فاشلةأوقف الاستقصاء. افحص errorCode وerror قبل أن تقرّر ما إذا كان إنشاء مهمة جديدة مناسبًا؛ تُردّ تكلفة محاولات الحل الفاشلة.

أرسل الرمز باستخدام الوكيل الأصلي والهوية المُعادة

تعيد هذه المسارات بيانات المهمة؛ ولا ترسل شيئًا إلى الموقع المستهدف. بمجرد أن تصبح status هي ready، يجب أن يستخدم المكوّن الذي يرسل الطلب إلى الجهة المستهدفة solution.token، لا معرّف المهمة.

أرسل عبر الوكيل نفسه المستخدم لإنشاء تلك المهمة، مع هوية المتصفح المُعادة في solution.userAgent وsolution.secChUa. احتفظ بإعدادات المهمة الأصلية بدلًا من افتراض أن البيئة الحالية لا تزال تحتوي على الوكيل نفسه. تختار الدالة المساعدة successful_proxy(original_task, ready_result) في SDK الوكيل من تلك المهمة الأصلية.

أبقِ الإرسال مرتبطًا بالجهة المستهدفة والإجراء المقصودين. تعني المهمة بحالة ready أن solvethree ولّد حلًا؛ ولا تُبيّن إلا استجابة الجهة المستهدفة ما إذا كان طلب التطبيق قد قُبل.

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

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

إنشاء مساحة عمل
استدعاء solvethree من واجهة خلفية تستخدم FastAPI · solvethree