Ruby로 reCAPTCHA Enterprise 해결하기
Ruby의 Net::HTTP로 reCAPTCHA Enterprise 작업을 생성하고, 준비되거나 실패할 때까지 폴링하세요. 아래 예제는 solvethree의 REST API를 직접 호출하므로 Ruby SDK가 필요하지 않습니다.
이 페이지의 내용
사이트 및 환경 구성
- 1.
사이트 프로필 활성화
solvethree 콘솔에서 대상 호스트 이름을 설정하고 워크스페이스에서 해당 프로필이 활성 상태인지 확인하세요. 호스트 이름과 액션을 전송해도 프로필이 생성되지는 않습니다. 사이트 프로필 설정을 참고하세요.
- 2.
환경 변수 설정
SOLVETHREE_API_KEY를 워크스페이스 API 키로 설정하고,SOLVETHREE_PROXY를 대상에 토큰을 제출할 때도 사용할 HTTP 또는 HTTPS 프록시 URL로 설정하세요. 키는 서버에 보관하세요. - 3.
예제 입력값 변경
accounts.example.com을 전체 URL이 아닌 대상 호스트 이름으로 바꾸고,login을 대상에서 요구하는 액션으로 바꾸세요. 이 요청은proxy하나를 사용하므로proxyCandidates를 추가하지 마세요.type과url은 생략하세요.recaptchaType을 생략하면 기본값인enterprise-v3가 선택됩니다.
예제를 solve.rb로 저장하고 해당 변수를 설정한 다음 Ruby로 실행하세요. 예제는 net/http, json, securerandom을 로드하며, JSON으로 요청 본문과 API 응답을 처리합니다.
한 번 생성한 뒤 작업 ID로 폴링
require 'net/http'
require 'json'
require 'securerandom'
api = 'https://api.solvethree.com/v1'
input = {site: 'accounts.example.com', action: 'login', proxy: ENV.fetch('SOLVETHREE_PROXY'), requestId: SecureRandom.uuid}
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 180
call = lambda do |method, path, body = nil|
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
raise 'Local deadline reached' if remaining <= 0
uri = URI(api + path)
request = method == :post ? Net::HTTP::Post.new(uri) : Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer ' + ENV.fetch('SOLVETHREE_API_KEY')
request['Accept'] = 'application/json'
if body
request['Content-Type'] = 'application/json'
request.body = JSON.generate(body)
end
# Net::HTTP's own proxy configuration is separate from input[:proxy].
http = Net::HTTP.new(uri.hostname, uri.port, nil)
http.use_ssl = uri.scheme == 'https'
http.open_timeout = [10, remaining].min
http.read_timeout = [25, remaining].min
http.write_timeout = [25, remaining].min
http.max_retries = 0
response = http.request(request)
raise "API HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
JSON.parse(response.body)
end
task_id = nil
begin
result = call.call(:post, '/tasks?waitMs=0', input)
task_id = result.fetch('id')
while %w[pending solving].include?(result.fetch('status'))
result = call.call(:get, '/tasks/' + URI.encode_www_form_component(task_id) + '?waitMs=15000')
sleep(1) if %w[pending solving].include?(result.fetch('status'))
end
raise "Task failed: #{result['errorCode']}" unless result['status'] == 'ready'
puts "Ready task: #{task_id}"
# Submit result['solution']['token'] with its userAgent/secChUa and original proxy.
rescue StandardError => error
warn "Recovery requestId=#{input[:requestId]} taskId=#{task_id || 'unknown'}"
raise error
end스크립트는 생성 요청을 한 번 보내고, 반환된 작업 ID를 저장한 뒤 상태가 pending 또는 solving인 동안 해당 작업을 조회합니다. 사용 가능한 솔루션은 ready 상태에서만 제공됩니다. 모든 응답은 HTTP 상태가 성공인 경우에만 본문을 성공 페이로드로 파싱해야 합니다.
HTTPS는 명시적으로 활성화됩니다. 자동 재시도는 비활성화되며, 리디렉션은 따라가지 않고 HTTP 상태 검사에서 거부됩니다. 작업 본문의 프록시는 풀이용이며, Ruby에서 solvethree API로 연결할 때의 프록시를 설정하지는 않습니다.
공유 단조 시계 기반 기한을 통해 폴링에 180초의 로컬 시간 한도를 적용합니다. 연결, 읽기, 쓰기 시간 제한은 각 요청이 시작될 때 남은 시간을 기준으로 상한이 정해집니다. 이 시간 한도는 폴링 제한이며, 진행 중인 요청을 반드시 취소하는 타이머는 아닙니다. 개별 시간 제한 설정은 Ruby Net::HTTP 문서에 설명되어 있습니다.
브라우저 식별 정보와 함께 토큰 제출
예제는 토큰이 아닌 준비된 작업의 ID를 출력합니다. 준비된 결과에서 solution.token을 읽어 대상 요청에서 요구하는 토큰 필드에 넣으세요. 대신 작업 ID를 보내지 마세요.
반환된 solution.userAgent를 User-Agent 헤더에, solution.secChUa를 Sec-CH-UA에 사용하세요. 이 작업에 제공한 것과 동일한 프록시를 통해 의도한 대상에 제출하세요. 반환된 식별 정보를 무관한 브라우저의 헤더로 대체하지 마세요.
작업이 준비되었다는 것은 solvethree가 솔루션을 생성했다는 뜻입니다. 대상이 애플리케이션 요청을 수락했는지는 대상의 응답을 별도로 확인해 판단하세요.
중복 작업을 생성하지 않고 실패 처리
- 스크립트에서 API HTTP 오류가 발생합니다.
성공이 아닌 HTTP 응답을 확인하세요. 이는 요청 수준의 오류이며, 작업의 최종 결과가 아닙니다.
다음을 시도해 보세요: 재시도하기 전에 해당 응답을 진단하세요. 잘못된 입력값을 수정하지 않은 채 반복해서 제출하지 마세요.
- 작업이
failed상태가 됩니다. 결과에서
errorCode와error를 모두 확인하세요. 예제에서 발생시키는 오류 메시지에는errorCode만 포함됩니다.다음을 시도해 보세요: 해당 작업의 폴링을 중단하고 보고된 원인을 해결하세요. 실패한 풀이는 환불되며, 실패가 반드시 크레딧 부족을 의미하지는 않습니다.
- 작업 ID를 받기 전에 생성 요청의 시간이 초과됩니다.
표준 오류에 기록된 복구용
requestId를 보관하세요. 시간 초과만으로 생성 실패가 입증되지는 않습니다.다음을 시도해 보세요: 동일한 요청 ID로 동일한 작업 요청을 제출해 복구하세요. 스크립트를 단순히 다시 실행하지 마세요. 새로 실행하면 새 ID가 생성되어 다른 작업이 만들어질 수 있습니다.
- 폴링이 로컬 기한에 도달하거나 연결이 끊깁니다.
로그에 기록된 작업 ID와 요청 ID를 보관하세요.
다음을 시도해 보세요: 다른 작업을 생성하기 전에 알고 있는 작업 ID로 조회하세요. 로컬 예외는 작업의 종료 상태가 아닙니다.
프로세스 재시작 후에도 복구하려면 POST를 보내기 전에 요청 ID와 원래 작업 입력값을 보관하고, 작업 ID가 반환되면 이를 보관하세요. 동일한 입력값으로 요청 ID를 재사용하면 기존 작업이 반환되며, 같은 ID를 유지하면서 입력값을 변경하면 충돌이 발생합니다. 다음 진단 단계는 API 오류 처리를 참고하세요.
첫 작업을 실행하세요.
워크스페이스 크레딧 $5로 시작하세요.