Next.js Route Handler에서 솔버 호출하기
서버 측 POST 핸들러로 작업을 한 번 생성한 다음, GET으로 해당 ID의 작업을 조회하세요. solvethree 키는 서버에 보관하세요. 브라우저에서 솔버를 직접 호출하거나 대기가 끝날 때마다 새 작업을 생성하면 안 됩니다.
이 페이지의 내용
서버 및 사이트 프로필 설정
- Node.js 22+와 공식 JavaScript SDK를 사용하세요. 문서의 패키지 URL 설치 방법을 따르세요. npm 레지스트리에 패키지가 있다고 가정하지 마세요.
- 서버 환경에 SOLVETHREE_API_KEY, CAPTCHA_SITE, SOLVETHREE_PROXY, INTEGRATION_KEY를 설정하세요. 두 비밀 키 모두 NEXT_PUBLIC_ 접두사를 붙이지 마세요.
- 라우트를 호출하기 전에 워크스페이스에서 대상 호스트 이름의 프로필을 활성화하세요. CAPTCHA_SITE를 설정해도 프로필이 생성되지는 않습니다. 사이트 프로필 설정을 참고하세요.
- 예제의 login 액션을 연동에 필요한 액션으로 바꾸세요. 요청은 프록시 하나를 사용하며 기본값은 reCAPTCHA Enterprise v3입니다. type 또는 url 필드는 필요하지 않습니다.
생성 및 조회 핸들러 추가
예제를 app/api/captcha/route.js에 넣으세요. 이 예제는 App Router HTTP 핸들러를 내보내고 SDK를 위해 Node.js 런타임을 명시적으로 선택합니다. 정적으로 생성되는 리소스가 아니라 요청 시 실행되는 서버 라우트로 유지하세요.
import { Solvethree, SolvethreeError } from '@solvethree/sdk';
export const runtime = 'nodejs';
const client = new Solvethree({ apiKey: process.env.SOLVETHREE_API_KEY });
function authorized(request) {
const key = process.env.INTEGRATION_KEY;
return Boolean(key) && request.headers.get('x-integration-key') === key;
}
function failure(error) {
return error instanceof SolvethreeError
? Response.json({ requestId: error.requestId, taskId: error.taskId }, { status: 502 })
: Response.json({ error: 'Invalid task input or ID' }, { status: 400 });
}
export async function POST(request) {
if (!authorized(request)) return new Response('Unauthorized', { status: 401 });
try {
return Response.json(await client.createTask({
site: process.env.CAPTCHA_SITE, action: 'login', proxy: process.env.SOLVETHREE_PROXY,
requestId: request.headers.get('x-request-id') ?? undefined,
}, { waitMs: 0, signal: AbortSignal.timeout(20000) }));
} catch (error) { return failure(error); }
}
export async function GET(request) {
if (!authorized(request)) return new Response('Unauthorized', { status: 401 });
const id = new URL(request.url).searchParams.get('id');
if (!id) return Response.json({ error: 'Provide id' }, { status: 400 });
try {
return Response.json(await client.getTask(id, { waitMs: 15000, signal: AbortSignal.timeout(25000) }));
} catch (error) { return failure(error); }
}POST는 waitMs: 0으로 createTask를 호출하므로 솔루션을 기다리지 않고 작업 응답을 반환합니다. 반환된 작업 ID를 저장하세요. GET은 기존 ID를 받아 getTask를 호출하며, 작업을 생성하지 않습니다.
GET은 최대 15초 대기를 요청하며, 별도로 요청을 25초 후 중단합니다. POST 요청은 20초 후 중단됩니다. 이 제한은 각 요청에 적용되며 작업 수명을 제한하지 않습니다.
각 작업을 반환하기 전에 접근 권한 확인
브라우저 접근에는 INTEGRATION_KEY를 배포하는 대신 애플리케이션의 실제 서버 측 인증을 사용하세요. 인증만으로는 충분하지 않습니다. 인증된 사용자가 임의의 작업 ID를 제공할 수 있다면 다른 사용자의 결과도 요청할 수 있습니다.
- 1.
생성 작업을 호출자와 연결
인증된 POST 요청으로 작업을 생성한 후에는 반환하기 전에 해당 ID를 인증된 사용자 또는 테넌트와 연결해 저장하세요. 복구 시에도 소유권 기록이 유지되도록 논리적 requestId도 같은 소유자와 연결하세요.
- 2.
조회 전 소유권 확인
GET에서는 호출자를 인증하고, getTask를 호출하기 전에 전달된 ID를 소유권 기록과 대조하세요. 호출자가 소유하지 않은 ID는 거부하고, 검사가 성공한 경우에만 결과를 반환하세요.
애플리케이션에서 호출자에게 선택 권한을 명시적으로 부여하지 않는 한 사이트, 액션, 프록시는 서버에서 제어하세요. 이 예제의 고정된 환경 값은 클라이언트가 해당 입력을 변경하지 못하게 합니다.
같은 작업 폴링 및 처리 여부가 불확실한 요청 복구
- 1.
종료되지 않은 작업은 계속 폴링
pending 또는 solving 상태이면 애플리케이션의 전체 대기 기한 내에서 같은 ID를 다시 조회하세요. GET 대기가 끝났다는 이유로 새 작업을 생성하지 마세요.
- 2.
ready 또는 failed에서 중단
사용 가능한 솔루션은 ready에만 포함됩니다. failed이면 폴링을 중단하고 errorCode와 error를 확인하세요. 풀이에 실패하면 환불됩니다. 응답을 작업으로 해석하기 전에 성공이 아닌 HTTP 응답부터 처리하세요. 라우트의 catch 핸들러가 반환된 작업 상태 확인을 대신하지는 않습니다.
- 3.
연결 시간 초과 후 생성 요청 복구
POST 전에 x-request-id를 정하고 보관하세요. 작업 ID를 받았다면 해당 작업을 조회하세요. 생성 응답이 유실되었다면 같은 요청 ID와 변경하지 않은 작업 입력으로 POST를 다시 보내 기존 작업을 복구하세요. 요청 ID에는 1–64자의 ASCII 영문자, 숫자, 밑줄 또는 하이픈을 사용할 수 있습니다. 같은 ID를 다른 입력에 재사용하면 충돌이 발생합니다.
작업이 ready라는 것은 solvethree가 솔루션을 생성했다는 뜻이지, 대상이 이를 수락했다는 뜻은 아닙니다. SDK는 솔루션을 대신 제출하지 않습니다. 제출할 때는 반환된 userAgent와 secChUa를 풀이에 성공한 프록시와 함께 사용하세요. 프록시가 하나인 이 예제에서는 설정된 프록시가 이에 해당합니다. 관련 없는 브라우저 식별 정보나 IP로 바꾸지 마세요.
요청 오류나 최종 실패가 발생하면 다른 풀이에 비용을 지불하기 전에 API 오류 참조를 확인하세요. 잘못된 입력을 그대로 재시도해도 해결되지 않습니다.
출처 및 API 레퍼런스
첫 작업을 실행하세요.
워크스페이스 크레딧 $5로 시작하세요.