HTTP servers and MongoDB
zy serve runs a project containing server.zy and database configuration.
Recognized assets in public/ are optional and individually bounded to 1 MiB.
It defaults to the current directory. Select another with --project=directory;
override the bind address with --host=127.0.0.1 and --port=8000.
fn list_projects(request) {
return http.json(200, {"data": mongo.list("projects", 20, 0)})
}
http.route("GET", "/api/v1/projects", list_projects)
HTTP exists in serve mode; MongoDB also exists in migrations and workers.
All namespaces propagate into imported modules. Regular run remains a local script runner. Top-level code executes
at startup and again for every request: use it only for declarations and route
registration. Put database writes inside handlers. Each request gets fresh
interpreter state; no language globals are shared across requests.
| Function | Result |
|---|---|
http.route(method, path, handler[, options]) | Registers a one-parameter Zy function; optional role restrictions |
http.json(status, body) | Response value returned by a handler |
mongo.list(collection, limit, offset) | List of documents, newest first |
mongo.get(collection, id) | Document or null |
mongo.insert(collection, document) | Created document |
mongo.update(collection, id, fields) | Patched document or null |
mongo.delete(collection, id) | Boolean indicating deletion |
mongo.valid_id(id) | Boolean ObjectID validation |
mongo.find(collection, filter, limit, offset) | Bounded filtered documents |
mongo.count(collection, filter) | Matched document count |
mongo.aggregate(collection, stages) | Bounded read-only aggregation |
mongo.transaction(operations) | Atomic batch of 1..25 operations |
mongo.create_index(collection, fields, unique) | Index name |
Methods: GET, POST, PUT, PATCH, DELETE, HEAD. GET automatically supports HEAD.
Paths use Go 1.22 ServeMux patterns such as /api/v1/projects/{id}. Duplicate,
conflicting, and invalid patterns fail startup. The runtime reserves health and
public asset routes. Every path under /api requires bearer authentication.
Handlers receive a map with method, path, params, query, body, and
request_id, trace_id, and user. Path/query values are strings; query uses the first value when a
key repeats. Empty bodies are null; nonempty bodies must be strict JSON with
Content-Type: application/json. Responses are bounded JSON with status 200..599.
Use http.json(204, null) for no content. No custom response headers, streaming,
WebSockets, or outgoing HTTP client API are included in this version.
MongoDB names contain letters, digits, and underscores and start with a letter.
IDs are 24-character hexadecimal strings. Documents expose id instead of _id.
Insert adds UTC created_at and updated_at; update preserves creation time.
Documents reject _id, dollar-prefixed keys, dotted keys, and null key bytes,
including nested objects. MongoDB operations fail with secret-safe Zy I/O errors.
Pagination requires limit 1..100 and offset 0..100000. The runtime uses the
official MongoDB Go driver.
Environment files load from the project directory. Process environment overrides
.env, which overrides atlas-credentials.env. Required settings: MONGODB_URI
and an API_KEY of at least 32 characters. Optional: MONGODB_DATABASE (default
zy_backend), HOST, PORT, CORS_ORIGINS (explicit origins), and
RATE_LIMIT_PER_MINUTE (default 120), AUTH_ENABLED (true),
ENABLE_REGISTRATION (false), and MAX_CONCURRENT_REQUESTS (128). Secrets remain outside language globals
unless explicitly read with env.get; local file configuration is not installed
into the process environment. Optional <username> / <password> placeholders
in the URI are escaped using their corresponding configuration values.
Readiness uses a bounded primary ping; unavailable databases cause startup to fail. Ctrl+C or SIGTERM initiates a 15-second HTTP drain and disconnects MongoDB. Request logs contain IDs, method, path, status, and timing, without headers, bodies, or connection strings. Rate limits are in-memory per direct client IP, with a bounded table of 10000 peers; forwarded IP headers are not trusted. Handler execution gets 10 seconds, database calls 5 seconds, and JSON bodies and responses are capped at 1 MiB.
Restart after code changes. Entry and imported sources are prepared once into an immutable snapshot; each request gets fresh state without reparsing files. Serve behind HTTPS and a process supervisor. See backend services for accounts, sessions, roles, query rules, transactions, migrations, jobs, caching, metrics, tracing, and measured performance.