net/http 서버에서 Go SDK 사용하기

작성: solvethree읽는 데 3분

공유 solvethree 클라이언트를 하나 생성하고, 인증된 POST 요청에서 작업 ID를 반환한 다음, 별도의 GET 요청으로 상태를 조회하세요. 생성 핸들러 안에서 Solve를 호출하지 마세요. 이 연동 방식에서는 원래 요청을 열린 상태로 유지하지 않고도 호출자가 결과를 기다릴 수 있습니다.

이 페이지의 내용

서버 및 대상 설정

  1. 1.

    Go SDK 설치

    Go 1.22 이상을 사용하세요. 초기화된 Go 모듈에서 go get solvethree.com/[email protected]으로 공식 SDK를 설치하세요. 아래 예제를 main.go로 저장하세요.

  2. 2.

    서버 환경 설정

    SOLVETHREE_API_KEY를 워크스페이스 API 키로, INTEGRATION_KEY를 이 내부 서버의 호출자용 별도 비밀 키로 설정하세요. CAPTCHA_SITE는 대상 호스트 이름으로, SOLVETHREE_PROXY는 풀이에 사용하는 HTTP 또는 HTTPS 프록시 URL로 설정하세요. 두 키 모두 신뢰할 수 있는 서버에 보관하세요.

  3. 3.

    설정한 대상 준비

    워크스페이스에서 사용할 수 있는 활성 프로필이 사이트에 있는지 확인하세요. 사이트 프로필 설정을 참고하세요. 이 예제는 액션을 login으로 고정합니다. 서버를 실행하기 전에 대상이 요구하는 액션으로 변경하세요. 호스트 이름과 액션을 지정하는 것만으로는 프로필이 생성되지 않습니다.

Go net/http · 작업 생성 및 조회
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 보관

X-Integration-Key 헤더와 함께 POST /captcha/tasks를 전송하세요. ID를 받기 전에 연결이 끊겨도 작업을 복구할 수 있도록 호출자가 생성한 X-Request-ID도 전송하세요. ASCII 영문자, 숫자, 밑줄 또는 하이픈을 사용해 1–64자로 지정하세요.

핸들러는 설정된 작업을 검증한 다음 대기 값을 0으로 지정해 CreateTask를 호출합니다. 풀이가 끝날 때까지 기다리지 않고 작업 생성을 요청합니다. 20초 컨텍스트는 이 HTTP 요청의 대기 시간을 제한하며, 풀이 시간 제한이 아닙니다.

성공하면 핸들러는 SDK 작업 결과를 반환합니다. 작업 ID를 저장하고 이후 확인에는 GET 경로를 사용하세요. POST가 성공했다고 해서 사용 가능한 토큰이 생긴 것으로 해석하지 마세요.

두 경로 모두 연동 키가 필요합니다. 이는 사용자별 권한 부여가 아닌 신뢰할 수 있는 내부 인터페이스입니다. 해당 키를 가진 호출자는 설정된 워크스페이스를 통해 접근 권한을 공유합니다.

완료될 때까지 GET으로 기존 작업 조회

동일한 연동 키 헤더와 함께 GET /captcha/tasks/{id}를 전송하세요. 핸들러는 GetTask만 호출하며 대체 작업을 생성하지 않습니다. 25초 요청 컨텍스트 안에서 최대 15초의 대기를 요청합니다.

  • pending 또는 solving: 동일한 작업 ID를 유지하고 다시 조회하세요.
  • ready: 풀이 결과를 읽으세요. 사용 가능한 결과가 있는 유일한 상태입니다.
  • failed: 폴링을 중단하고 errorCode와 error를 확인하세요. 다른 작업을 생성할지 결정하기 전에 원인을 해결하세요.

성공한 작업 결과를 디코딩하기 전에 HTTP 응답 상태를 확인하세요. 이 서버에서는 인증되지 않은 요청은 401, 잘못된 작업 입력은 400, SDK 요청 오류는 502를 반환합니다. 반환된 작업의 상태가 failed인 경우는 HTTP 요청 실패와는 다른 결과입니다.

다른 풀이를 생성하지 않고 시간 초과 복구

시간 초과가 발생했다고 해서 생성에 실패한 것은 아닙니다. 요청 컨텍스트를 취소하면 로컬 대기만 중단되며 원격 작업은 중단되지 않습니다. SDK는 생성 POST를 자동으로 재시도하지 않습니다.

  1. 1.

    작업 ID가 있으면 해당 작업 조회

    해당 ID로 GET 경로를 사용하세요. SDK 오류가 발생하면, SDK가 해당 값을 제공하는 경우 예제의 JSON 오류 응답에 taskId와 requestId가 포함됩니다.

  2. 2.

    요청 ID만 있으면 원래 생성 요청 재전송

    동일한 X-Request-ID와 변경되지 않은 작업 입력으로 POST를 다시 전송하세요. 즉, 설정된 호스트 이름, 액션, 프록시를 그대로 유지해야 합니다. 동일한 요청 ID와 작업 요청을 사용하면 기존 작업이 복구되며, 해당 ID에 다른 입력을 사용하면 충돌이 발생합니다.

  3. 3.

    첫 요청 전에 ID 보관

    요청 ID를 지정하지 않으면 SDK가 생성하지만, 연결이 끊긴 호출자는 이를 받지 못할 수 있습니다. POST 전에 X-Request-ID를 정하고 보관하면 복구 시 오류 응답에 의존하지 않아도 됩니다.

ready 결과를 동일한 프록시로 사용

이 서버는 결과를 반환하며, SDK가 결과를 대상에 제출하지는 않습니다. 제출 코드는 토큰, 반환된 userAgent 및 secChUa 브라우저 식별 정보, 풀이에 성공한 프록시를 사용해야 합니다. 이 단일 프록시 예제에서는 풀이 후 IP를 바꾸지 말고 설정된 프록시를 계속 사용하세요.

ready 작업은 풀이 결과가 생성되었다는 뜻이지, 대상이 애플리케이션 요청을 수락했다는 뜻은 아닙니다. 제출에 실패하면 다른 풀이 비용을 지불하기 전에 전송한 토큰, 식별 정보, 프록시, 대상 요청을 점검하세요.

첫 작업을 실행하세요.

워크스페이스 크레딧 $5로 시작하세요.

워크스페이스 만들기
net/http 서버에서 Go SDK 사용하기 · solvethree