feat(infra): auto-commit con 88 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
---
|
||||
name: hoppscotch_run_request
|
||||
kind: function
|
||||
lang: py
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "def hoppscotch_run_request(method: str, url: str, *, title: str | None = None, headers: dict | None = None, body: str | None = None, body_type: str | None = None, variables: dict | None = None, access_token: str, backend_url: str = \"http://localhost:3170\", record_history: bool = True, timeout_s: float = 30.0, verify_tls: bool = True) -> dict"
|
||||
description: "Ejecuta una peticion HTTP real (resolviendo placeholders <<var>>/{{var}} con un dict de variables) y la registra en el UserHistory de un Hoppscotch self-hosted via la mutation GraphQL createUserHistory, para que el humano la vea aparecer en vivo en la pestana History de su GUI (subscription userHistoryCreated). La request se ejecuta con las variables resueltas, pero en el History se guarda SIN resolver (con los literales <<var>>) igual que en el editor. resMetadata minimo: statusCode + duration. El access_token va como cookie, no como header Authorization."
|
||||
tags: [hoppscotch, flow-replay, http]
|
||||
uses_functions: [build_hoppscotch_collection_py_infra]
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [json, re, requests]
|
||||
params:
|
||||
- name: method
|
||||
desc: "metodo HTTP de la peticion (GET, POST, ...)."
|
||||
- name: url
|
||||
desc: "endpoint de la peticion. Puede contener placeholders <<var>> o {{var}} que se resuelven con `variables` antes de ejecutar."
|
||||
- name: title
|
||||
desc: "nombre visible de la request en el History. None = derivar de method + path via build_hoppscotch_collection."
|
||||
- name: headers
|
||||
desc: "dict name->value de cabeceras. Sus values tambien admiten placeholders <<var>>/{{var}}."
|
||||
- name: body
|
||||
desc: "cuerpo de la peticion como texto ya serializado. Admite placeholders. None = sin cuerpo."
|
||||
- name: body_type
|
||||
desc: "tipo de cuerpo para el HoppRESTRequest del History: 'json' | 'form' | 'raw' | None."
|
||||
- name: variables
|
||||
desc: "dict name->value para resolver los placeholders al EJECUTAR. Una variable que falte deja el literal intacto. None = no se resuelve nada."
|
||||
- name: access_token
|
||||
desc: "JWT de sesion (de hoppscotch_login). Viaja en la cookie access_token, NO en el header Authorization. Necesario para registrar en el History."
|
||||
- name: backend_url
|
||||
desc: "base del backend Hoppscotch self-host sin barra final. La mutation cuelga de {backend_url}/graphql. Default http://localhost:3170."
|
||||
- name: record_history
|
||||
desc: "si True y hay access_token, registra la request ejecutada en el UserHistory via createUserHistory. Default True."
|
||||
- name: timeout_s
|
||||
desc: "timeout en segundos de la peticion HTTP ejecutada (y del POST de History). Default 30.0."
|
||||
- name: verify_tls
|
||||
desc: "verificacion del certificado TLS de la peticion ejecutada. Default True."
|
||||
output: "dict. En exito de la ejecucion HTTP: {status: 'ok', status_code: int, duration_ms: int, response_body: str (truncado a 5000 chars), response_headers: dict, recorded: bool, history_id: str|None}. Si la ejecucion fue ok pero el registro de History fallo, status sigue 'ok', recorded False y se anade history_error. Si la ejecucion HTTP falla (RequestException): {status: 'error', error: str, recorded: False}. Nunca lanza por errores de red esperables."
|
||||
tested: true
|
||||
tests:
|
||||
- "test_ejecuta_resolviendo_variables_angle"
|
||||
- "test_ejecuta_resolviendo_variables_brace"
|
||||
- "test_record_history_registra_request_sin_resolver"
|
||||
- "test_record_history_false_no_llama_create_user_history"
|
||||
- "test_request_exception_status_error"
|
||||
- "test_variable_faltante_conserva_literal"
|
||||
test_file_path: "python/functions/infra/hoppscotch_run_request_test.py"
|
||||
file_path: "python/functions/infra/hoppscotch_run_request.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
import sys
|
||||
sys.path.insert(0, "python/functions")
|
||||
from infra.hoppscotch_login import hoppscotch_login
|
||||
from infra.hoppscotch_run_request import hoppscotch_run_request
|
||||
|
||||
# 1) Obtener un JWT de sesion (headless, lee el correo de Mailpit).
|
||||
login = hoppscotch_login("admin@example.com")
|
||||
assert login["status"] == "ok", login["error"]
|
||||
token = login["access_token"]
|
||||
|
||||
# 2) Ejecutar una request con una variable y dejar rastro en el History de la GUI.
|
||||
result = hoppscotch_run_request(
|
||||
"GET",
|
||||
"<<baseURL>>/api/status",
|
||||
title="Status",
|
||||
variables={"baseURL": "https://registry.organic-machine.com"},
|
||||
access_token=token,
|
||||
)
|
||||
print(result["status_code"], result["recorded"], result["history_id"])
|
||||
# 200 True hist-...
|
||||
# -> aparece en vivo en la pestana History del Hoppscotch self-host.
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando el agente ejecuta una consulta HTTP y quiere que el humano la vea en el
|
||||
History de su GUI Hoppscotch self-hosted, en vivo. La entry aparece via la
|
||||
subscription `userHistoryCreated` sin que el humano refresque. Util para hacer
|
||||
auditable/observable lo que el agente prueba: cada `hoppscotch_run_request` deja
|
||||
en la pestana History la request (con sus variables sin resolver) y su statusCode
|
||||
+ duracion. Encadena con `hoppscotch_login` para obtener el `access_token`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **El access_token va como cookie, no como header Authorization.** La mutation
|
||||
`createUserHistory` lee el JWT de la cookie `access_token`. Se manda con
|
||||
`cookies={"access_token": ...}`. Si expira (~24h), re-loguea con
|
||||
`hoppscotch_login`.
|
||||
- **reqData lleva la request SIN resolver.** Lo que se guarda en el History es el
|
||||
HoppRESTRequest con los placeholders `<<var>>`/`{{var}}` literales, igual que en
|
||||
el editor de la GUI, para que el humano vea la plantilla con sus variables y no
|
||||
los valores expandidos. La peticion SI se ejecuta con las variables resueltas.
|
||||
- **Soporta `<<>>` y `{{}}`.** Hoppscotch usa `<<var>>`; muchas plantillas traen
|
||||
`{{var}}`. Ambas sintaxis se resuelven al ejecutar. Una variable que falte en
|
||||
`variables` deja el literal intacto (no rompe).
|
||||
- **resMetadata minimo: statusCode + duration.** Se envia
|
||||
`{"statusCode": ..., "duration": ...}`. Si una version del backend exigiera mas
|
||||
campos, el registro fallaria con `history_error` (la ejecucion HTTP sigue siendo
|
||||
ok). Ajustar el shape si el self-host lo pide.
|
||||
- **El body de respuesta se trunca a 5000 chars** en `response_body` del output,
|
||||
para no devolver payloads enormes. Los `response_headers` van completos.
|
||||
- **duration_ms viene de `resp.elapsed`,** no de `time.time()`: es la latencia que
|
||||
midio `requests` para la peticion ejecutada.
|
||||
- **Degradacion suave del History:** si la ejecucion HTTP fue ok pero el POST de la
|
||||
mutation falla (transporte, no-JSON, errores GraphQL, sin id), `status` sigue
|
||||
"ok", `recorded` es False y se anade `history_error` con el detalle.
|
||||
|
||||
## Capability growth log
|
||||
|
||||
v1.0.0 — version inicial. Ejecucion + registro en UserHistory del self-host;
|
||||
resolucion de placeholders `<<>>`/`{{}}`.
|
||||
Reference in New Issue
Block a user