mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-22 18:43:45 +00:00
e621eacb9b
Wires internal/urlimport into the API: Fetcher → Detect → converters.
Side-effect-free; the editor's "Insert from URL" modal owns any item
mutation (TASK-1474).
Endpoint:
- POST /api/v1/import/url, body {"url"}, response {markdown,
detected_type, title?, source_url, fetched_at, content_type}.
- Status mapping: 400 invalid URL / SSRF / malformed body; 502 upstream
failure (incl. size cap); 504 fetch timeout; 422 conversion failure.
- Swagger 2.0 fallback: detected as "openapi" by the sniffer but
rejected by ConvertOpenAPI → falls through to ConvertGeneric and
re-classifies the response as "generic" so the UI shows the right
affordance.
- 30s wall-clock budget on the whole pipeline via context.WithTimeout
(Fetcher's own timeout is the HTTP-level cap).
Package-level Fetcher is memoized via the existing sync.Once-cached
safe transport (shared keep-alive pool, no per-request leak). The
handler skips the pre-flight ValidateURL when the package fetcher
has AllowLocal=true so tests can swap in a loopback-friendly fetcher
without bypassing the production guard.
Integration tests (handlers_import_test.go):
- HTML happy path (httptest upstream, asserts detected_type/title/
source_url/fetched_at/content_type all wired up).
- OpenAPI 3.x happy path (inline YAML upstream, asserts ConvertOpenAPI
was invoked and detected_type=openapi).
- Swagger 2.0 fallback (asserts detected_type re-classified to
generic, markdown non-empty).
- SSRF rejection (default fetcher, loopback URL → 400 mentioning
"private"/"reserved").
- file:// scheme rejected (400).
- Missing/malformed body rejected (400).
- Upstream 5xx surfaces as 502.
- Size cap exceeded surfaces as 502.
- No-side-effects check: item count unchanged before/after import.
Parent: PLAN-1467.