Las APIs devuelven JSON; las páginas devuelven HTML. El motor de
plantillas de nyx-serve renderiza HTML con un default de seguridad que
importa: {{value}} se escapa como HTML.
Tienes que optar por salir con {{{raw}}} — lo
peligroso es la excepción, no el default que te olvidas.
import "nyx-serve/src/template" fn page_notes(req: Request) -> Response { var item1: Map = map_new() item1.insert("title", "Buy coffee") var item2: Map = map_new() item2.insert("title", "<script>alert(1)</script>") var items: Array = [item1, item2] var ctx: Map = map_new() ctx.insert("heading", "My notes") ctx.insert("has_items", "1") ctx.insert("items", items) let tmpl: String = "<h1>{{heading}}</h1> {{#if has_items}} <ul>{{#each items}}<li>{{title}}</li>{{/each}}</ul> {{else}}<p>No notes yet.</p>{{/if}}" return response_html(200, tpl_render(tmpl, ctx)) }
Ese segundo ítem — un tag <script> — se renderiza
como texto escapado, no como un tag vivo. Lo que ofrece la plantilla:
{{key}} escapado, {{{key}}} crudo{{#if key}}…{{else}}…{{/if}}{{#each key}}…{{/each}} sobre un Array<Map>, anidable{{> name}} partials, registered with tpl_partial(name, template)
Serví un directorio bajo un prefijo de URL. La variante
_cached agrega Cache-Control y
Last-Modified para que navegadores y CDNs se salteen las
re-descargas.
import "nyx-serve/src/files" // in main(): app_static_cached(app, "/assets/", "public/", 3600)
Un request a /assets/style.css ahora sirve public/style.css con una hora de cache.
Los campos de form clásicos llegan ya parseados en req.form
(lo viste en el paso 3). Las subidas de archivos usan
multipart_parse, que es binary-safe — un PNG con bytes NUL
llega intacto:
import "nyx-serve/src/multipart" fn upload(req: Request) -> Response { let ctype: String = http_find_header(req.headers_flat, "Content-Type") let parts: Array = multipart_parse(req.body, ctype) let p: Array = parts[0] let filename: String = part_filename(p) let data: String = part_value(p) return response_text(200, filename + ": " + int_to_string(data.length()) + " bytes") }
part_name,
part_filename, part_ctype,
part_value. El layout de 4 slots detrás es interno.