Используйте Go SDK в сервере net/http
Создайте один общий клиент solvethree, возвращайте ID задачи из аутентифицированного POST-запроса и получайте ее статус через отдельный GET. Не вызывайте Solve внутри обработчика создания: эта интеграция позволяет вызывающей стороне дождаться результата, не удерживая исходный запрос открытым.
На этой странице
Настройте сервер и целевой сайт
- 1.
Установите SDK для Go
Используйте Go 1.22 или новее. В инициализированном модуле Go установите официальный SDK командой
go get solvethree.com/[email protected]. Сохраните пример ниже какmain.go. - 2.
Настройте окружение сервера
Задайте в
SOLVETHREE_API_KEYAPI-ключ рабочего пространства, а вINTEGRATION_KEY— отдельный секрет для клиентов этого внутреннего сервера. ВCAPTCHA_SITEукажите имя хоста целевого сайта, а вSOLVETHREE_PROXY— URL HTTP- или HTTPS-прокси, используемого для решения. Храните оба ключа на доверенных серверах. - 3.
Подготовьте настроенный целевой сайт
Убедитесь, что у сайта есть активный профиль, доступный вашему рабочему пространству; см. настройку профиля сайта. В примере действие фиксировано и равно
login. Перед запуском сервера замените его на действие, которое ожидает целевой сайт. Указание имени хоста и действия не создает профиль.
package main
import (
"context"
"encoding/json"
"errors"
"log"
"net/http"
"os"
"time"
solvethree "solvethree.com/sdk"
)
func main() {
client, err := solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"), nil)
if err != nil { log.Fatal(err) }
secret := os.Getenv("INTEGRATION_KEY")
if secret == "" { log.Fatal("Set INTEGRATION_KEY") }
authorize := func(w http.ResponseWriter, r *http.Request) bool {
if r.Header.Get("X-Integration-Key") != secret { http.Error(w, "Unauthorized", 401); return false }
return true
}
respond := func(w http.ResponseWriter, result *solvethree.TaskResult, err error) {
w.Header().Set("Content-Type", "application/json")
if err != nil {
var recovery *solvethree.Error
w.WriteHeader(http.StatusBadGateway)
ids := map[string]string{"error": "Solver request failed"}
if errors.As(err, &recovery) { ids["requestId"] = recovery.RequestID; ids["taskId"] = recovery.TaskID }
_ = json.NewEncoder(w).Encode(ids)
return
}
_ = json.NewEncoder(w).Encode(result)
}
mux := http.NewServeMux()
mux.HandleFunc("POST /captcha/tasks", func(w http.ResponseWriter, r *http.Request) {
if !authorize(w,r) { return }
input := solvethree.TaskRequest{Site: os.Getenv("CAPTCHA_SITE"), Action:"login",
Proxy:os.Getenv("SOLVETHREE_PROXY"), RequestID:r.Header.Get("X-Request-ID")}
if err := input.Validate(); err != nil { http.Error(w,"Invalid task input",400);return }
ctx,cancel := context.WithTimeout(r.Context(),20*time.Second);defer cancel()
zero:=0
result,err:=client.CreateTask(ctx,input,&zero)
respond(w,result,err)
})
mux.HandleFunc("GET /captcha/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
if !authorize(w,r) { return }
ctx,cancel:=context.WithTimeout(r.Context(),25*time.Second);defer cancel()
result,err:=client.GetTask(ctx,r.PathValue("id"),15000)
respond(w,result,err)
})
server:=&http.Server{Addr:"127.0.0.1:3000", Handler:mux, ReadHeaderTimeout:5*time.Second}
log.Fatal(server.ListenAndServe())
}Запустите модуль командой go run .. Сервер слушает на 127.0.0.1:3000. Он использует стандартный маршрутизатор Go net/http, поэтому фреймворк не требуется. Клиент SDK создается один раз и безопасен для конкурентного использования.
Задача использует режим reCAPTCHA по умолчанию — enterprise-v3. В ней указываются имя хоста сайта, действие и один прокси, а не type или url. Тело POST-запроса не используется, поэтому вызывающая сторона не может выбирать произвольные целевые сайты или прокси.
Отправьте POST один раз и сохраните ID задачи
Отправьте POST /captcha/tasks с заголовком X-Integration-Key. Также передайте сгенерированный вызывающей стороной X-Request-ID, чтобы восстановить задачу, если соединение прервется до получения ее ID. Используйте 1–64 символа: ASCII-буквы, цифры, подчеркивания или дефисы.
Обработчик проверяет настроенную задачу, затем вызывает CreateTask с нулевым значением ожидания. Он запрашивает создание задачи, не дожидаясь завершения решения. Контекст на 20 секунд ограничивает время ожидания этого HTTP-запроса; это не тайм-аут решения.
При успехе обработчик возвращает результат задачи из SDK. Сохраните ID задачи и используйте GET-маршрут для последующих проверок. Успешный POST не означает, что токен уже пригоден для использования.
Оба маршрута требуют ключ интеграции. Это доверенный внутренний интерфейс, а не авторизация отдельных пользователей: клиенты с этим ключом имеют общий доступ через настроенное рабочее пространство.
Получайте существующую задачу через GET до ее завершения
Отправьте GET /captcha/tasks/{id} с тем же заголовком ключа интеграции. Обработчик вызывает только GetTask; он никогда не создает задачу на замену. Он запрашивает ожидание до 15 секунд в контексте запроса на 25 секунд.
pendingилиsolving: сохраните тот же ID задачи и запросите ее снова.ready: прочитайте решение. Это единственный статус с пригодным для использования результатом.failed: прекратите опрос и изучитеerrorCodeиerror. Устраните причину, прежде чем решать, создавать ли новую задачу.
Проверьте HTTP-статус ответа, прежде чем декодировать успешный результат задачи. В этом сервере неавторизованные запросы возвращают 401, некорректные входные данные задачи — 400, а ошибки запросов SDK — 502. Возвращенная задача со статусом failed — это другой исход, не ошибка HTTP-запроса.
Восстановите задачу после тайм-аута без нового решения
Тайм-аут не доказывает, что создание не удалось. Отмена контекста запроса прекращает локальное ожидание, а не удаленную задачу. SDK никогда автоматически не повторяет POST-запрос создания.
- 1.
Если у вас есть ID задачи, запросите ее
Используйте GET-маршрут с этим ID. При ошибках SDK JSON-ответ с ошибкой в примере содержит
taskIdиrequestId, если SDK предоставляет их. - 2.
Если у вас есть только ID запроса, повторите исходный запрос создания
Отправьте POST повторно с тем же
X-Request-IDи неизменными входными данными задачи. Это означает, что настроенные имя хоста, действие и прокси должны остаться прежними. Тот же ID запроса и тот же запрос задачи восстанавливают существующую задачу; другие входные данные с этим ID приводят к конфликту. - 3.
Сохраните ID до первого запроса
SDK генерирует ID запроса, если он не указан, но при разрыве соединения вызывающая сторона может его не получить. Если выбрать и сохранить
X-Request-IDдо POST, восстановление не будет зависеть от ответа с ошибкой.
Используйте готовый результат с тем же прокси
Этот сервер возвращает результат; SDK не отправляет его целевому сайту. Ваш код отправки должен использовать токен, возвращенные параметры браузера userAgent и secChUa, а также прокси, на котором решение удалось. В этом примере с одним прокси продолжайте использовать настроенный прокси, а не меняйте IP после решения.
Задача со статусом ready означает, что решение сгенерировано, а не что целевой сайт принял запрос вашего приложения. Если отправка не удалась, проверьте исходящие токен, параметры браузера, прокси и запрос к целевому сайту, прежде чем платить за новое решение.
Источники и справочник API
Запустите первую задачу.
Начните с $5 на балансе рабочего пространства.