Chame o solvethree a partir de um backend FastAPI

Por solvethree4 min de leitura

Retorne a tarefa após a criação, não após toda a resolução. O cliente consulta seu status até que seja ready ou failed e então envia o token ao destino se a resolução tiver sido bem-sucedida.

Nesta página

Configure o servidor e o alvo

Use Python 3.10 ou posterior. Instale o FastAPI com python -m pip install "fastapi[standard]" e depois instale o SDK oficial com python -m pip install https://solvethree.com/downloads/solvethree_sdk-0.1.0-py3-none-any.whl.

Defina estas variáveis de ambiente no processo do servidor antes de iniciar a aplicação:

  • SOLVETHREE_API_KEY: a chave de API do seu workspace. Mantenha-a no servidor; o SDK a usa para se autenticar no solvethree.
  • INTEGRATION_KEY: um segredo separado que os clientes enviam no cabeçalho X-Integration-Key para se autenticar nas suas rotas do FastAPI.
  • CAPTCHA_SITE: o hostname de destino, não uma URL completa.
  • SOLVETHREE_PROXY: a URL do proxy HTTP ou HTTPS usado para esta tarefa, sem caminho, query ou fragmento.

Crie um perfil ativo para o destino no seu workspace antes de chamar a rota. O exemplo fixa a ação em login, então o perfil e a requisição pretendida ao destino devem corresponder a esse uso. Fornecer um hostname não cria um perfil; consulte a configuração de perfil de site.

Adicione e execute as rotas do FastAPI

Salve este exemplo como main.py. Ambas as rotas exigem X-Integration-Key. A rota de criação monta a tarefa inteiramente a partir da configuração do servidor; os clientes não fornecem o site, a ação ou o proxy no corpo da requisição.

FastAPI · executar o SDK síncrono em um pool de threads
# 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})

A tarefa usa reCAPTCHA Enterprise v3 por padrão. Ela envia site, action e um proxy, sem um campo type ou url.

O SDK Python é síncrono. Chamá-lo diretamente dentro de async def bloquearia o loop de eventos, por isso ambos os handlers usam run_in_threadpool. A criação usa wait_ms=0 com um tempo limite de requisição do SDK de 20 segundos; a consulta permite uma espera de 15 segundos com um tempo limite de requisição do SDK de 25 segundos. Nenhum dos handlers espera toda a resolução usando client.solve.

Para desenvolvimento local, execute fastapi dev main.py no diretório que contém o arquivo. As rotas são POST http://127.0.0.1:8000/captcha/tasks e GET http://127.0.0.1:8000/captcha/tasks/{task_id}. O FastAPI descobre o objeto app; não há um URLconf separado para registrar.

Crie uma tarefa, consulte-a e recupere requisições interrompidas

  1. 1.

    Crie uma única vez com um ID de requisição estável

    Envie POST /captcha/tasks com X-Integration-Key e um X-Request-ID que você mantenha para esta tarefa lógica. O ID de requisição deve conter 1–64 letras ASCII, números, sublinhados ou hífens. A rota o repassa ao solvethree como requestId. Salve o ID da tarefa retornado.

  2. 2.

    Verifique o status HTTP antes de ler o status da tarefa

    O wrapper retorna 401 para falhas de autenticação, 400 para falhas de entrada do tipo ValueError e 502 para exceções SolvethreeError capturadas. O detalhe da resposta 502 contém requestId e taskId do erro do SDK. Trate esse erro HTTP antes de interpretar a resposta como uma tarefa.

  3. 3.

    Consulte a tarefa existente

    Chame GET /captcha/tasks/{task_id} com X-Integration-Key. Verifique status após cada resposta HTTP bem-sucedida. Uma consulta pode retornar uma tarefa em estado não terminal mesmo após o fim da espera; consulte a mesma tarefa novamente em vez de criar outra.

  4. 4.

    Recupere uma criação de resultado incerto

    Se a criação exceder o tempo limite e você tiver um ID de tarefa, consulte-a. Caso contrário, repita o POST com seu X-Request-ID original e os parâmetros da tarefa no servidor inalterados. Reutilizar esse ID com a mesma tarefa retorna a tarefa existente; parâmetros alterados geram conflito. Guarde o ID original separadamente em vez de substituí-lo pelo requestId de uma resposta de erro.

O que fazer após uma resposta HTTP bem-sucedida
O que fazer após uma resposta HTTP bem-sucedida
Status da tarefaAção do cliente
pending ou solvingContinue consultando a mesma tarefa. Ainda não há uma solução utilizável.
readyLeia solution e prepare a requisição ao destino.
failedPare as consultas periódicas. Verifique errorCode e error antes de decidir se faz sentido criar uma nova tarefa; resoluções que falham são reembolsadas.

Envie o token com o proxy original e a identidade retornada

Estas rotas retornam dados da tarefa; elas não enviam nada ao site de destino. Quando status for ready, o componente que faz a requisição ao destino deve usar solution.token, não o ID da tarefa.

Faça o envio pelo mesmo proxy usado para criar essa tarefa, com a identidade de navegador retornada em solution.userAgent e solution.secChUa. Guarde a configuração original da tarefa em vez de presumir que o ambiente atual ainda contém o mesmo proxy. O helper successful_proxy(original_task, ready_result) do SDK seleciona o proxy dessa tarefa original.

Mantenha o envio vinculado ao destino e à ação pretendidos. Uma tarefa ready significa que o solvethree gerou uma solução; somente a resposta do destino informa se a requisição da aplicação foi aceita.

Execute sua primeira tarefa.

Comece com $5 em créditos no espaço de trabalho.

Criar um espaço de trabalho
Chame o solvethree a partir de um backend FastAPI · solvethree