惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
G
GRAHAM CLULEY
Spread Privacy
Spread Privacy
Last Week in AI
Last Week in AI
腾讯CDC
P
Privacy & Cybersecurity Law Blog
WordPress大学
WordPress大学
C
Cybersecurity and Infrastructure Security Agency CISA
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 司徒正美
爱范儿
爱范儿
雷峰网
雷峰网
The Hacker News
The Hacker News
S
SegmentFault 最新的问题
Cisco Talos Blog
Cisco Talos Blog
博客园 - 聂微东
T
Tor Project blog
I
Intezer
大猫的无限游戏
大猫的无限游戏
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Schneier on Security
Schneier on Security
T
Tenable Blog
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
AI
AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
Help Net Security
Help Net Security
O
OpenAI News
博客园 - 【当耐特】
博客园 - Franky
AWS News Blog
AWS News Blog
罗磊的独立博客
J
Java Code Geeks
Know Your Adversary
Know Your Adversary
A
Arctic Wolf
小众软件
小众软件
量子位
SecWiki News
SecWiki News
S
Security Affairs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog
N
News and Events Feed by Topic
Apple Machine Learning Research
Apple Machine Learning Research
H
Heimdal Security Blog
Google DeepMind News
Google DeepMind News
IT之家
IT之家

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Cómo probar la API de Rust
Roobia · 2026-05-13 · via DEV Community

Rust te da un servidor HTTP rápido y con seguridad de tipos en pocas cientos de líneas. Lo que no te da por defecto es un ciclo de feedback rápido para validar la API como la consumen otros clientes: estado HTTP, JSON serializado, headers, autenticación, errores y contratos compartidos.

Prueba Apidog hoy

En esta guía vas a montar un flujo de pruebas de API para Rust con Apidog: conectar un servidor Axum o Actix, crear requests reutilizables, validar JSON de Serde, manejar JWT, simular endpoints para frontend y ejecutar escenarios en CI.

Si vienes de Postman o curl, Apidog también te permite trabajar diseño-primero: generar OpenAPI desde solicitudes guardadas, publicar mocks y compartir entornos de equipo. La migración desde Postman queda para otra lectura; aquí nos enfocamos en Rust.

TL;DR

  • Ejecuta tu servidor Rust localmente con cargo run.
  • Configura http://localhost:3000 como baseUrl en Apidog.
  • Guarda secretos como variables de entorno.
  • Crea una primera request GET /healthz para validar conectividad.
  • Para JSON, prueba tus structs de Serde con cuerpos reales y scripts de aserción.
  • Para JWT, genera el token una vez en un script pre-request y reutilízalo como {{token}}.
  • Usa mocks de Apidog para que frontend avance antes de que el handler esté listo.
  • Guarda todo como un Escenario de Prueba y ejecútalo en CI con apidog-cli.

Por qué probar una API de Rust fuera de la cadena de herramientas de Rust

cargo test es necesario, pero no sustituye una prueba real sobre HTTP. Para validar códigos de estado, headers, errores de serialización y contratos JSON, normalmente terminas escribiendo pruebas de integración específicas por endpoint.

Apidog añade una capa de contrato sobre el servidor en ejecución:

  • La request vive una vez.
  • Las aserciones viven junto a la request.
  • El frontend puede abrir el mismo proyecto.
  • Los mocks salen del mismo contrato.
  • CI puede ejecutar las mismas pruebas contra el binario real.

Tres motivos prácticos para añadirlo al flujo de Rust:

  1. Las verificaciones de contrato se desacoplan de la compilación.

    Apidog prueba un servidor en ejecución. No necesitas esperar a rustc para comprobar si /users sigue devolviendo 200.

  2. Los mocks son compartibles.

    El frontend recibe una URL estable con JSON válido, incluso si el handler todavía no existe.

  3. OpenAPI sale de las requests guardadas.

    Puedes exportar OpenAPI 3.1 sin anotar cada ruta con utoipa, aide u otra librería.

Paso 1: Añade tu servidor Rust como entorno de Apidog

Arranca una API mínima con Axum:

use axum::{routing::get, Router};
use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/healthz", get(|| async { "ok" }));

    let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();

    axum::serve(listener, app).await.unwrap();
}

Enter fullscreen mode Exit fullscreen mode

En Apidog:

  1. Crea un proyecto nuevo.
  2. Abre Gestión de Entornos.
  3. Añade un entorno llamado Rust Local.
Variable Valor
baseUrl http://localhost:3000
token déjalo vacío por ahora
apiVersion v1

Añade también un entorno Rust Staging con la URL desplegada. Así puedes cambiar de local a staging desde el selector de entorno sin editar requests.

Paso 2: Crea la primera request

Dentro del proyecto, crea una carpeta llamada Rust API.

Añade una request:

  • Método: GET
  • URL: {{baseUrl}}/healthz

Envía la solicitud. Si el servidor está corriendo, deberías recibir:

200 OK
ok

Enter fullscreen mode Exit fullscreen mode

Guárdala como health-check.

Si recibes connection refused, revisa:

  • Que el proceso siga ejecutándose.
  • Que el puerto sea 3000.
  • Que el servidor escuche en 0.0.0.0:3000.

Para desarrollo local con herramientas externas o Docker, 0.0.0.0 suele evitar problemas de resolución entre interfaces. Si usas 127.0.0.1, algunas llamadas desde contenedores o procesos externos pueden no llegar al servidor esperado.

Paso 3: Prueba requests y respuestas JSON con Serde

Una API Rust típica recibe JSON, deserializa con Serde y devuelve JSON serializado.

Añade un endpoint POST /users:

use axum::{extract::Json, routing::post, Router};
use serde::{Deserialize, Serialize};

#[derive(Deserialize)]
struct CreateUser {
    name: String,
    email: String,
}

#[derive(Serialize)]
struct User {
    id: u64,
    name: String,
    email: String,
}

async fn create_user(Json(payload): Json<CreateUser>) -> Json<User> {
    Json(User {
        id: 1,
        name: payload.name,
        email: payload.email,
    })
}

let app = Router::new().route("/users", post(create_user));

Enter fullscreen mode Exit fullscreen mode

En Apidog, crea una request:

  • Método: POST
  • URL: {{baseUrl}}/users
  • Body: JSON
{
  "name": "Ada Lovelace",
  "email": "ada@example.com"
}

Enter fullscreen mode Exit fullscreen mode

Envía la request y guárdala como create-user.

Ahora añade aserciones en la pestaña Pruebas:

pm.test("Status is 200", () => {
  pm.expect(pm.response.code).to.eql(200);
});

pm.test("Body has id, name, email", () => {
  const body = pm.response.json();

  pm.expect(body).to.have.property("id");
  pm.expect(body.name).to.eql("Ada Lovelace");
  pm.expect(body.email).to.match(/^[^@]+@[^@]+$/);
});

Enter fullscreen mode Exit fullscreen mode

Con esto conviertes la forma pública del JSON en un contrato ejecutable. Si más adelante cambias atributos de Serde, nombres de campos o tipos, la prueba falla antes de que el cambio llegue a producción.

Paso 4: Cubre rechazos de Serde

No pruebes solo el caso feliz. En Rust, gran parte del contrato real aparece cuando Serde rechaza una entrada.

Crea estas requests:

Request Body Esperado
create-user-missing-email { "name": "Ada" } 422, el cuerpo menciona missing field email
create-user-extra-field { "name": "Ada", "email": "a@b.c", "admin": true } 200 si no usas #[serde(deny_unknown_fields)]; 422 si lo usas
create-user-wrong-type { "name": 1, "email": "a@b.c" } 422, menciona invalid type: integer

Ejemplo de aserción:

pm.test("Status is 422", () => {
  pm.expect(pm.response.code).to.eql(422);
});

pm.test("Error mentions missing email", () => {
  pm.expect(pm.response.text()).to.include("missing field");
});

Enter fullscreen mode Exit fullscreen mode

Esto documenta tu política real de validación. Si activas deny_unknown_fields más adelante, la prueba correspondiente se pondrá en rojo y te avisará de que cambiaste el contrato público.

Paso 5: Prueba rutas protegidas con JWT

Muchas APIs Rust usan middleware o extractores para proteger handlers. Un patrón común con Axum es validar un JWT desde cookies o headers.

Ejemplo simplificado:

use axum::{
    extract::Json,
    http::StatusCode,
};
use axum_extra::extract::cookie::PrivateCookieJar;
use jsonwebtoken::{decode, DecodingKey, Validation};

async fn me(jar: PrivateCookieJar) -> Result<Json<User>, StatusCode> {
    let token = jar
        .get("token")
        .ok_or(StatusCode::UNAUTHORIZED)?;

    let claims = decode::<Claims>(
        token.value(),
        &DecodingKey::from_secret(b"secret"),
        &Validation::default(),
    )
    .map_err(|_| StatusCode::UNAUTHORIZED)?;

    Ok(Json(User {
        id: claims.claims.sub,
        name: "Ada".into(),
        email: "ada@example.com".into(),
    }))
}

Enter fullscreen mode Exit fullscreen mode

En Apidog, evita generar JWT manualmente en cada request. Añade un Script Pre-Solicitud a nivel de carpeta:

const jwt = require("jsonwebtoken");

const token = jwt.sign(
  {
    sub: 1,
    exp: Math.floor(Date.now() / 1000) + 3600,
  },
  "secret"
);

pm.environment.set("token", token);

Enter fullscreen mode Exit fullscreen mode

Luego configura la carpeta:

  • Auth: Bearer Token
  • Token: {{token}}

Ahora todas las requests dentro de la carpeta heredan el JWT.

Para más detalle, consulta cómo probar autenticación JWT en APIs.

Paso 6: Prueba streaming y Server-Sent Events

Rust tiene buen soporte para streaming. En Axum, una respuesta Sse envuelve un futures::Stream y emite text/event-stream.

El formato típico es:

data: { ... }

data: { ... }

event: done
data: {}

Enter fullscreen mode Exit fullscreen mode

En Apidog, la request se crea como cualquier GET. Cuando el Content-Type es text/event-stream, el panel de respuesta cambia a modo streaming y muestra los eventos a medida que llegan.

Valida al menos:

  • Que el primer fragmento llegue dentro del SLA esperado.
  • Que se emita un evento final, por ejemplo event: done.
  • Que el stream no quede abierto para siempre.
  • Que el timeout de la request sea estricto.

Si usas WebSockets en lugar de SSE, Apidog tiene un tipo de request específico para WebSocket. El flujo es equivalente: crear conexión, guardar mensajes esperados y afirmar respuestas.

Paso 7: Simula la API para desarrollo frontend en paralelo

El frontend no debería bloquearse porque el handler Rust todavía no compila o aún no existe.

Con Apidog puedes publicar un mock basado en la misma request create-user.

Pasos:

  1. Haz clic derecho en create-user.
  2. Elige Smart Mock.
  3. Actívalo.

Apidog servirá una respuesta sintética en una URL similar a:

https://mock.apidog.com/m1/<projectId>/users

Enter fullscreen mode Exit fullscreen mode

El mock acepta el mismo body que tu API real. El frontend puede hacer POST contra esa URL mientras tú terminas el handler.

Para mocks dinámicos, usa Advanced Mock:

return {
  id: Math.floor(Math.random() * 10000),
  name: body.name,
  email: body.email,
  createdAt: new Date().toISOString()
};

Enter fullscreen mode Exit fullscreen mode

Cuando el handler Rust esté listo, el frontend cambia la URL base de nuevo a:

http://localhost:3000

Enter fullscreen mode Exit fullscreen mode

El contrato no cambia.

Este patrón también aplica a otros runtimes. El equipo cubre flujos similares en cómo construir y probar una API de Spring Boot y en el flujo general de pruebas de API.

Paso 8: Guarda las requests como escenario de prueba de CI

Un Escenario de Prueba de Apidog encadena requests, comparte variables y se puede ejecutar sin interfaz gráfica.

Crea un escenario con este orden:

  1. health-check

    • Espera 200.
  2. create-user

    • Espera 200.
    • Captura body.id en una variable.
  3. create-user-missing-email

    • Espera 422.
  4. me

    • Usa el pre-request JWT.
    • Espera 200.
    • Valida que el id devuelto coincide con el capturado.
  5. Request SSE

    • Valida que el stream completa en menos de 5 segundos.

Exporta el escenario como JSON y guárdalo en el repositorio:

tests/apidog/contract.json

Enter fullscreen mode Exit fullscreen mode

Ejemplo de ejecución en CI:

- name: Run API contract tests
  run: |
    cargo build --release
    ./target/release/myserver &
    sleep 2
    apidog-cli run tests/apidog/contract.json --env "Rust Local"

Enter fullscreen mode Exit fullscreen mode

Con esto, cada PR que modifique un handler se prueba contra un binario Rust real. Si cambia un nombre de campo de Serde, un código de estado o una regla de JWT, CI lo detecta antes del merge.

Paso 9: Genera OpenAPI desde las requests guardadas

Cuando el conjunto de requests sea estable:

  1. Abre el menú de exportación de Apidog.
  2. Elige OpenAPI 3.1.
  3. Exporta el documento.

Obtendrás una especificación basada en las requests reales y sus ejemplos.

Puedes usarla para generar clientes tipados en:

  • TypeScript
  • Swift
  • Kotlin
  • Python
  • otros lenguajes compatibles con OpenAPI

Si quieres versionarla dentro del repositorio Rust, ejecútalo desde CI con apidog-cli export y escribe el resultado en:

openapi.json

Enter fullscreen mode Exit fullscreen mode

Así el contrato queda junto al código, pero sigue validándose desde fuera de cargo.

Preguntas frecuentes

¿Funciona Apidog con Axum y Actix-web?

Sí. Apidog habla HTTP, no Rust. Funciona con Axum, Actix-web, Rocket, Warp, Poem, Loco o cualquier servidor que responda requests HTTP.

La consideración práctica para desarrollo local es enlazar a 0.0.0.0 si necesitas que herramientas externas o contenedores lleguen al proceso.

¿Cómo pruebo handlers que hacen panic?

Ejecuta el servidor con CatchPanicLayer de tower-http delante del router. Así un panic puede convertirse en 500 con una respuesta controlada.

Luego crea una request en Apidog que active esa ruta y afirma:

pm.test("Status is 500", () => {
  pm.expect(pm.response.code).to.eql(500);
});

Enter fullscreen mode Exit fullscreen mode

Si no capturas el panic, la conexión puede cerrarse y Apidog mostrará un error de red. Eso también describe un comportamiento observable del contrato.

¿Puedo ejecutar Apidog contra un binario Rust en Docker?

Sí. Apunta baseUrl al puerto expuesto del contenedor.

Si usas Docker Compose, asegúrate de que el runner de Apidog esté en la misma red o usa el puerto publicado en el host.

¿Qué pasa con gRPC?

Apidog incluye requests gRPC. Puedes importar tus archivos .proto, elegir servicio y método, rellenar el payload y enviar la llamada.

Los conceptos de entorno, autenticación y escenarios de prueba se mantienen igual.

¿El escenario de prueba reemplaza a cargo test?

No.

Usa ambos:

  • cargo test para lógica interna, unidades y comportamiento de dominio.
  • Apidog para validar la superficie HTTP real: JSON, headers, auth, códigos de estado, CORS, errores y contratos.

Detectan problemas distintos.

¿Apidog es gratuito para proyectos Rust open source?

Sí. El cliente de Apidog es gratuito para individuos y equipos pequeños. Los escenarios de prueba, mocks y exportación OpenAPI forman parte del nivel gratuito.

Si mantienes una API pública de Rust, puedes incluir el proyecto o los escenarios en tu repositorio para que otros desarrolladores ejecuten el mismo contrato.

Conclusión

Una API Rust necesita más que compilación correcta. Necesita un contrato HTTP ejecutable.

Con Apidog puedes crear requests reales, añadir aserciones, generar mocks para frontend, exportar OpenAPI y correr el mismo flujo en CI contra el binario Rust en vivo.

Empieza con GET /healthz, añade tus endpoints JSON, cubre errores de Serde, configura JWT y exporta un escenario de prueba. El resultado es un ciclo de feedback más rápido, desacoplado de cargo, y un contrato compartido por backend, frontend y CI.

Descarga Apidog y apúntalo a tu servidor Rust. La configuración inicial lleva pocos minutos y te deja una suite de contrato reutilizable para cada cambio futuro.