A Tiny Nim Microservice, Three Real Bugs, and What They Taught Me About My Own Mummy Fork
Description and use
A small Nim microservice using the Mummy fork implements POST /api/contact with validation, rate limiting, CORS, and email sending via Resend. Three bugs (identical HttpHeaders types, gcsafe misuse, missing OPTIONS route) are fixed, making the service ready for deployment on Render.
Problem
Implement a simple POST /api/contact endpoint that validates input, enforces rate limits, handles CORS, and sends an email, while dealing with deployment constraints and framework quirks.
Outcome
The microservice now validates input, enforces rate limits, handles CORS preflight, logs requests, serves OpenAPI docs, and reliably sends emails via Resend, with all three discovered bugs fixed and deployment constraints addressed.
Workflow
- Define ContactBody type and validation logic
- Add explicit field checks (non-empty, 2000-char limit, email format)
- Configure Mummy middleware: logging, CORS, rate limiter, error handler
- Serve OpenAPI docs at /docs and /openapi.json
- Implement email sending via std/smtp, then switch to Resend API
- Deploy to Render free tier, discover SMTP port block
- Add OPTIONS /api/contact route to enable CORS preflight
- Resolve type mismatch by importing std/httpcore except HttpHeaders
- Wrap global read in cast(gcsafe) to satisfy compiler
- Test edge cases: disallowed origin, malformed email, 2000-char boundary, rapid submissions, health checks
Evidence
Two HttpHeaders types that look identical and aren't.
gcsafe doesn't care that your global never actually changes.
An unregistered route means your middleware never runs — including for the request that most needs it.
- Record date: 2026-09-20T04:00:35.227Z