Las claves API hardcoded y los timeouts fijos funcionan para prototipos. Producción necesita configuración específica por entorno, gestión de secretos y la capacidad de cambiar la configuración sin redeploy.
Jerarquía de configuración
Priority (highest → lowest):
1. Environment variables ← deployment-specific overrides
2. Config file (YAML/JSON) ← version-controlled defaults
3. Application defaults ← fallback values in code
Referencia de configuración completa
| Parámetro | Variable ambiental | Predeterminado | Descripción |
|---|---|---|---|
| Clave API | CAPTCHAAI_API_KEY |
— | Requerido. Su clave API CaptchaAI |
| Enviar URL | CAPTCHAAI_SUBMIT_URL |
https://ocr.captchaai.com/in.php |
Endpoint de envío de tarea |
| URL de sondeo | CAPTCHAAI_POLL_URL |
https://ocr.captchaai.com/res.php |
Endpoint de sondeo de resultados |
| Intervalo de consulta | CAPTCHAAI_POLL_INTERVAL |
5 |
Segundos entre intentos de sondeo |
| Intentos de consulta máximos | CAPTCHAAI_MAX_POLLS |
60 |
Máximo de intentos de sondeo antes del tiempo de espera |
| concurrencia | CAPTCHAAI_CONCURRENCY |
10 |
Tareas CAPTCHA paralelas máximas |
| Tiempo de espera | CAPTCHAAI_TIMEOUT |
300 |
Tiempo de espera total en segundos |
| apoderado | CAPTCHAAI_PROXY |
— | URL proxy para resolver CAPTCHA |
| URL de devolución de llamada | CAPTCHAAI_CALLBACK_URL |
— | URL de webhook para resultados asincrónicos |
| Reintentar | CAPTCHAAI_RETRIES |
3 |
Reintentos en caso de fallos transitorios |
| Nivel de registro | CAPTCHAAI_LOG_LEVEL |
info |
Detalle del registro |
Cargador de configuración
pitón
import os
import yaml
from dataclasses import dataclass, field
from pathlib import Path
@dataclass
class CaptchaAIConfig:
api_key: str = ""
submit_url: str = "https://ocr.captchaai.com/in.php"
poll_url: str = "https://ocr.captchaai.com/res.php"
poll_interval: int = 5
max_polls: int = 60
concurrency: int = 10
timeout: int = 300
proxy: str = ""
callback_url: str = ""
retries: int = 3
log_level: str = "info"
@classmethod
def load(cls, config_path=None):
"""Load config: env vars override file, which overrides defaults."""
config = cls()
# Layer 2: Config file
if config_path and Path(config_path).exists():
with open(config_path) as f:
file_config = yaml.safe_load(f) or {}
for key, value in file_config.items():
if hasattr(config, key):
setattr(config, key, value)
# Layer 1: Environment variables (highest priority)
env_map = {
"CAPTCHAAI_API_KEY": "api_key",
"CAPTCHAAI_SUBMIT_URL": "submit_url",
"CAPTCHAAI_POLL_URL": "poll_url",
"CAPTCHAAI_POLL_INTERVAL": "poll_interval",
"CAPTCHAAI_MAX_POLLS": "max_polls",
"CAPTCHAAI_CONCURRENCY": "concurrency",
"CAPTCHAAI_TIMEOUT": "timeout",
"CAPTCHAAI_PROXY": "proxy",
"CAPTCHAAI_CALLBACK_URL": "callback_url",
"CAPTCHAAI_RETRIES": "retries",
"CAPTCHAAI_LOG_LEVEL": "log_level",
}
for env_key, attr_name in env_map.items():
value = os.environ.get(env_key)
if value is not None:
# Cast to correct type
current = getattr(config, attr_name)
if isinstance(current, int):
value = int(value)
setattr(config, attr_name, value)
config.validate()
return config
def validate(self):
if not self.api_key:
raise ValueError("CAPTCHAAI_API_KEY is required")
if self.poll_interval < 1:
raise ValueError("poll_interval must be >= 1")
if self.concurrency < 1:
raise ValueError("concurrency must be >= 1")
# Usage
config = CaptchaAIConfig.load("config/captchaai.yaml")
print(f"Concurrency: {config.concurrency}, Timeout: {config.timeout}s")
javascript
const fs = require("fs");
const yaml = require("js-yaml");
const path = require("path");
class CaptchaAIConfig {
static defaults = {
apiKey: "",
submitUrl: "https://ocr.captchaai.com/in.php",
pollUrl: "https://ocr.captchaai.com/res.php",
pollInterval: 5,
maxPolls: 60,
concurrency: 10,
timeout: 300,
proxy: "",
callbackUrl: "",
retries: 3,
logLevel: "info",
};
static envMap = {
CAPTCHAAI_API_KEY: "apiKey",
CAPTCHAAI_SUBMIT_URL: "submitUrl",
CAPTCHAAI_POLL_URL: "pollUrl",
CAPTCHAAI_POLL_INTERVAL: { key: "pollInterval", type: "int" },
CAPTCHAAI_MAX_POLLS: { key: "maxPolls", type: "int" },
CAPTCHAAI_CONCURRENCY: { key: "concurrency", type: "int" },
CAPTCHAAI_TIMEOUT: { key: "timeout", type: "int" },
CAPTCHAAI_PROXY: "proxy",
CAPTCHAAI_CALLBACK_URL: "callbackUrl",
CAPTCHAAI_RETRIES: { key: "retries", type: "int" },
CAPTCHAAI_LOG_LEVEL: "logLevel",
};
static load(configPath = null) {
let config = { ...CaptchaAIConfig.defaults };
// Layer 2: Config file
if (configPath && fs.existsSync(configPath)) {
const ext = path.extname(configPath);
const raw = fs.readFileSync(configPath, "utf8");
const fileConfig = ext === ".json" ? JSON.parse(raw) : yaml.load(raw);
config = { ...config, ...fileConfig };
}
// Layer 1: Environment variables
for (const [envKey, mapping] of Object.entries(CaptchaAIConfig.envMap)) {
const value = process.env[envKey];
if (value !== undefined) {
const attrKey = typeof mapping === "string" ? mapping : mapping.key;
const type = typeof mapping === "string" ? "string" : mapping.type;
config[attrKey] = type === "int" ? parseInt(value, 10) : value;
}
}
CaptchaAIConfig.validate(config);
return config;
}
static validate(config) {
if (!config.apiKey) throw new Error("CAPTCHAAI_API_KEY is required");
if (config.pollInterval < 1) throw new Error("pollInterval must be >= 1");
if (config.concurrency < 1) throw new Error("concurrency must be >= 1");
}
}
// Usage
const config = CaptchaAIConfig.load("config/captchaai.yaml");
console.log(`Concurrency: ${config.concurrency}, Timeout: ${config.timeout}s`);
Archivos de configuración por entorno
# config/captchaai.yaml — base
api_key: "" # Always set via env var
concurrency: 5
poll_interval: 5
retries: 3
log_level: info
# config/captchaai.production.yaml
concurrency: 20
poll_interval: 3
timeout: 180
log_level: warning
# config/captchaai.staging.yaml
concurrency: 3
poll_interval: 5
timeout: 300
log_level: debug
Gestión de secretos
Nunca almacene claves API en archivos de configuración o control de fuente.
| Método | Mejor para | Ejemplo |
|---|---|---|
| Variables ambientales | Contenedores, CI/CD | export CAPTCHAAI_API_KEY=abc123 |
| Administrador de secretos de AWS | Infraestructura de AWS | Recuperar al inicio; rotación automática |
| Bóveda de HashiCorp | Multinube, local | Secretos dinámicos con TTL |
| Secretos de Docker | Docker Swarm / Componer | Montado en /run/secrets/ |
Archivo .env (solo para desarrolladores) |
Desarrollo local | biblioteca dotenv; .gitignore eso |
Ejemplo de composición de Docker
services:
captcha-worker:
image: captcha-worker:latest
environment:
- CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
- CAPTCHAAI_CONCURRENCY=15
- CAPTCHAAI_LOG_LEVEL=warning
env_file:
- .env.production
Banderas de características
Alternar capacidades sin volver a implementar:
class FeatureFlags:
def __init__(self):
self.flags = {
"use_callback": os.environ.get("FF_USE_CALLBACK", "false") == "true",
"enable_proxy": os.environ.get("FF_ENABLE_PROXY", "true") == "true",
"max_concurrent": int(os.environ.get("FF_MAX_CONCURRENT", "10")),
}
def is_enabled(self, flag):
return self.flags.get(flag, False)
def get(self, flag, default=None):
return self.flags.get(flag, default)
Solución de problemas
| Problema | causa | Solución |
|---|---|---|
| La clave API no se carga | Falta var env; nombre de variable incorrecto | Marque echo $CAPTCHAAI_API_KEY; verificar la ortografía |
| Archivo de configuración ignorado | Ruta incorrecta o falta biblioteca YAML | Verificar que el archivo exista; instalar pyyaml / js-yaml |
| Prod usando la configuración de desarrollo | Anulación específica del entorno no aplicada | Verifique la precedencia de env var; verificar NODE_ENV / APP_ENV |
| Secretos visibles en los registros | El volcado de configuración incluye la clave API | Enmascarar campos sensibles en la checkout del registro |
Preguntas frecuentes
¿Debo usar YAML o JSON para archivos de configuración?
YAML para archivos editados por humanos (admite comentarios). JSON para configuraciones generadas por máquina o cuando desee un análisis estricto.
¿Con qué frecuencia debo rotar las claves API?
Gire inmediatamente si está comprometido. Programar rotación cada 90 días para cumplimiento. Utilice administradores de secretos que admitan la rotación automática.
¿Puedo cambiar la concurrencia sin reiniciar?
Sí: lea la configuración de las variables de entorno o un servicio de configuración en cada lote de tareas, no solo al inicio. Esto le permite ajustar la concurrencia actualizando la var env y enviando una señal de recarga.
Artículos relacionados
- Configuración de proxy SOCKS5 en CaptchaAI
- Gestión de claves API para equipos de CaptchaAI
Prepara tu configuración de producción
Prepara tu configuración para producción: comienza con una clave API CaptchaAI y parte de las plantillas de configuración anteriores.
Guías relacionadas:
- Seguridad de clave API y lista blanca de IP
- Solución en contenedores Docker
- Arquitectura multirregional