# Referência de renderização e segurança HTTP

Contratos completos de SSR, adaptadores do servidor, serialização e cabeçalhos.

<span id="servidor-y-navegador-tienen-responsabilidades-distintas"></span>

<span class="section-anchor" id="section-1"></span>

## Servidor e navegador têm responsabilidades diferentes

Importe estas funções de `wu-framework/server`, `wu-framework/server/adapters` ou `wu-framework/server/security`. A renderização recebe módulos de servidor explícitos; não monta componentes do navegador nem baixa automaticamente a entrada de um manifesto.

Cada solicitação deve manter seu próprio estado e nonce. O HTML do renderizador é conteúdo confiável: use `escapeHtml` para dados externos e evite enviar segredos em `renderStateScript`. A [receita de servidor](/pt/docs/framework/server-recipes/) mostra como compor a resposta e sua hidratação.

Os nomes `RenderResult` e `RenderOutput` desta página descrevem o formato dos resultados; consulte as declarações do subcaminho `server` para importar tipos efetivamente exportados.

<span class="section-anchor" id="section-2"></span>

## renderApp

Renderiza uma aplicação com um módulo de servidor e produz o contêiner reconhecido pela hidratação do WU.

`renderApp(appName, options): Promise<RenderResult>`

- **Parâmetros:** Nome não vazio; options.module obrigatório, props, styles, containerId, className, shadowMode e declarative; nonce opcional.
- **Retorno:** Objeto com html, inner, containerAttrs, state, appName e containerId.
- **Erros:** Propaga erros de entrada ou do renderizador; trate a rejeição antes de emitir a resposta HTTP.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderApp, renderHtml, escapeHtml } from 'wu-framework/server';
const card = renderHtml(({ title }) => `<h2>${escapeHtml(title)}</h2>`);
const result = await renderApp('card', { module: card, props: { title: 'Resumen' } });
console.log(result.html);
```

O módulo deve produzir HTML confiável. O helper escapa atributos e estado, mas não sanitiza o HTML retornado por render. Não importa automaticamente uma URL de navegador.

Referência: `src/server/wu-server-render.js`.

<span class="section-anchor" id="section-3"></span>

## renderApps

Renderiza uma lista em paralelo e reúne HTML, estado e erros por aplicação.

`renderApps(apps, options?): Promise<RenderAppsResult>`

- **Parâmetros:** Lista de {name, module, ...opciones}; failFast false por padrão; nonce compartilhado opcional.
- **Retorno:** {html, byApp, state, errors}; com failFast false, mantém resultados parciais.
- **Erros:** Por padrão, registra erros por entrada; failFast:true rejeita a operação. Não cancela renderizadores que já estão em execução.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderApps, renderHtml } from 'wu-framework/server';
const result = await renderApps([
  { name: 'summary', module: renderHtml(() => '<p>Resumen</p>') },
  { name: 'activity', module: renderHtml(() => '<p>Actividad</p>') },
]);
console.log(result.errors);
```

Referência: `src/server/wu-server-render.js`.

<span class="section-anchor" id="section-4"></span>

## renderStateScript

Serializa o estado em um script que o cliente pode recuperar durante a hidratação.

`renderStateScript(state, options?): string`

- **Parâmetros:** state serializável; varName identificador JavaScript, merge boolean, nonce opcional.
- **Retorno:** Tag script completa.
- **Erros:** Rejeita varName inválido, nonce inválido ou valores que JSON.stringify não possa serializar.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderStateScript } from 'wu-framework/server';
const script = renderStateScript({ card: { title: 'Resumen' } }, { merge: true });
```

Não inclua segredos: esse estado é visível no HTML da resposta.

Referência: `src/server/wu-server-render.js`.

<span class="section-anchor" id="section-5"></span>

## declarativeShadowDomPolyfill

Gera um script de compatibilidade para templates com shadowrootmode quando não há suporte nativo.

`declarativeShadowDomPolyfill(options?): string`

- **Parâmetros:** options.nonce opcional.
- **Retorno:** HTML de um script; não o executa ao chamar o helper.
- **Erros:** Um nonce inválido falha na construção do atributo.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { declarativeShadowDomPolyfill } from 'wu-framework/server';
const script = declarativeShadowDomPolyfill({ nonce });
```

Emita o script depois do conteúdo que deve converter; ele não observa templates futuros.

Referência: `src/server/wu-server-render.js`.

<span class="section-anchor" id="section-6"></span>

## escapeHtml

Escapa ampersand, sinais de tag e aspas para texto ou atributos HTML.

`escapeHtml(value): string`

- **Parâmetros:** Qualquer valor; null e undefined são convertidos em string vazia.
- **Retorno:** String escapada.
- **Erros:** A coerção para string pode propagar um erro do próprio valor.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { escapeHtml } from 'wu-framework/server';
escapeHtml('<etiqueta>'); // '&lt;etiqueta&gt;'
```

Não valida URLs nem transforma HTML arbitrário em conteúdo seguro.

Referência: `src/server/wu-server-render.js`.

<span class="section-anchor" id="section-7"></span>

## serializeState

Codifica JSON e impede o fechamento do script por caracteres de tag.

`serializeState(value): string`

- **Parâmetros:** Valor compatível com JSON; null/undefined na raiz são representados como null.
- **Retorno:** JSON com <, > e separadores Unicode escapados.
- **Erros:** Referências cíclicas, BigInt ou serializações não aceitas podem lançar erro.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { serializeState } from 'wu-framework/server';
serializeState({ title: '</script>' });
```

Referência: `src/server/wu-server-render.js`.

<span class="section-anchor" id="section-8"></span>

## SSR_MARKER_ATTR / SSR_ROOT_ATTR

Expõe os nomes dos atributos que coordenam renderizador e hidratação.

`SSR_MARKER_ATTR: 'data-wu-ssr'; SSR_ROOT_ATTR: 'data-wu-root'`

- **Parâmetros:** Constantes exportadas de wu-framework/server.
- **Retorno:** Duas strings.
- **Erros:** A leitura das constantes não valida o conteúdo do contêiner.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { SSR_MARKER_ATTR, SSR_ROOT_ATTR } from 'wu-framework/server';
console.log(SSR_MARKER_ATTR, SSR_ROOT_ATTR);
```

Referência: `src/server/wu-server-render.js`.

<span class="section-anchor" id="section-9"></span>

## createNonce

Gera um nonce de 128 bits com crypto.getRandomValues.

`createNonce(): string`

- **Parâmetros:** Sem parâmetros.
- **Retorno:** String base64url sem padding.
- **Erros:** Precisa de Web Crypto; lança erro se não estiver disponível.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { createNonce } from 'wu-framework/server';
const nonce = createNonce();
```

Referência: `src/server/wu-security-headers.js`.

<span class="section-anchor" id="section-10"></span>

## buildCsp

Compõe uma política CSP para scripts, estilos, imagens, conexões e frames.

`buildCsp(options?): string`

- **Parâmetros:** nonce; listas scriptSrc/styleSrc/connectSrc/imgSrc/frameSrc; unsafeInlineStyle; https true por padrão.
- **Retorno:** Valor completo de Content-Security-Policy.
- **Erros:** Rejeita um nonce inválido; as listas de origens devem vir de configuração confiável.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { buildCsp } from 'wu-framework/server';
const policy = buildCsp({ nonce, connectSrc: ['https://api.example.com'] });
```

Sem nonce e sem styleSrc, a política inclui unsafe-inline para estilos; connect-src também incorpora scriptSrc. https:false omite upgrade-insecure-requests.

Referência: `src/server/wu-security-headers.js`.

<span class="section-anchor" id="section-11"></span>

## securityHeaders

Constrói cabeçalhos CSP, HSTS, X-Frame-Options, MIME, referrer, permissions e CORS opcional.

`securityHeaders(options?): Record<string, string>`

- **Parâmetros:** Opções CSP mais hsts, frameOptions, referrerPolicy, permissionsPolicy, nosniff, corsOrigin e csp.
- **Retorno:** Mapa de cabeçalhos; não modifica uma resposta.
- **Erros:** Propaga a validação de CSP quando a política é gerada.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { securityHeaders } from 'wu-framework/server';
const headers = securityHeaders({ nonce, hsts: false, corsOrigin: 'https://shell.example.com' });
```

HSTS está ativo por padrão; desative-o explicitamente para uma resposta HTTP de desenvolvimento. csp:false omite CSP.

Referência: `src/server/wu-security-headers.js`.

<span class="section-anchor" id="section-12"></span>

## applySecurityHeaders

Aplica os cabeçalhos a uma resposta Node compatível com setHeader.

`applySecurityHeaders(res, options?): response`

- **Parâmetros:** res com setHeader; getHeader permite combinar um Vary existente.
- **Retorno:** A mesma resposta.
- **Erros:** Lança erro se res não tiver setHeader ou se a política for inválida.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { applySecurityHeaders } from 'wu-framework/server';
applySecurityHeaders(res, { nonce });
```

Referência: `src/server/wu-security-headers.js`.

<span class="section-anchor" id="section-13"></span>

## wuSecurityMiddleware

Cria middleware de Express ou Connect com nonce por solicitação.

`wuSecurityMiddleware(options?): middleware`

- **Parâmetros:** Opções de cabeçalhos; `nonce` deve ser uma função por requisição. Omiti-la gera um nonce novo automaticamente; uma string fixa é rejeitada ao construir o wrapper.
- **Retorno:** Função (req,res,next) que escreve req.wuNonce e res.locals.nonce se locals existir.
- **Erros:** Erros de geração do nonce ou dos cabeçalhos são propagados ao executar o middleware.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { wuSecurityMiddleware } from 'wu-framework/server';
app.use(wuSecurityMiddleware());
```

Referência: `src/server/wu-security-headers.js`.

<span class="section-anchor" id="section-14"></span>

## withSecurityHeaders

Envolve um handler Fetch e adiciona cabeçalhos, mantendo o corpo e o status HTTP.

`withSecurityHeaders(handler, options?): (request) => Promise<Response>`

- **Parâmetros:** handler(request,{nonce}) deve retornar Response.
- **Retorno:** Handler assíncrono com uma nova Response.
- **Erros:** Propaga o erro do handler e exige um resultado compatível com Response.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { withSecurityHeaders } from 'wu-framework/server';
const GET = withSecurityHeaders(async (_request, { nonce }) => {
  return new Response(`<p>Listo</p>`, { headers: { 'Content-Type': 'text/html' } });
});
```

Referência: `src/server/wu-security-headers.js`.

<span class="section-anchor" id="section-15"></span>

## renderReact

Adapta o renderizador do React ao contrato de renderApp.

`renderReact(ComponentOrFn, options?): { render(props): Promise<RenderOutput> }`

- **Parâmetros:** Component React; styles, strictMode, react e renderToString injetáveis.
- **Retorno:** Módulo de servidor com render que retorna html, styles e state.
- **Erros:** Propaga erros de entrada ou do renderizador; trate a rejeição antes de emitir a resposta HTTP.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderReact, renderApp } from 'wu-framework/server';
import React from 'react';
import { renderToString } from 'react-dom/server';
const module = renderReact(Card, { react: React, renderToString });
const result = await renderApp('card', { module, props: { count: 2 } });
```

Injete a mesma instância do React usada pelo componente para evitar duplicar seu runtime.

Referência: `src/server/adapters.js`.

<span class="section-anchor" id="section-16"></span>

## renderVue

Adapta o renderizador do Vue ao contrato de renderApp.

`renderVue(ComponentOrFn, options?): { render(props): Promise<RenderOutput> }`

- **Parâmetros:** Component Vue; styles, setup(app,props), createSSRApp e renderToString injetáveis.
- **Retorno:** Módulo de servidor com render que retorna html, styles e state.
- **Erros:** Propaga erros de entrada ou do renderizador; trate a rejeição antes de emitir a resposta HTTP.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderVue, renderApp } from 'wu-framework/server';
const module = renderVue(Card, { setup(app) { /* app.use(plugin) */ } });
const result = await renderApp('card', { module, props: { count: 2 } });
```

Precisa de vue e @vue/server-renderer ou de ambas as funções injetadas.

Referência: `src/server/adapters.js`.

<span class="section-anchor" id="section-17"></span>

## renderPreact

Adapta o renderizador do Preact ao contrato de renderApp.

`renderPreact(ComponentOrFn, options?): { render(props): Promise<RenderOutput> }`

- **Parâmetros:** Component Preact; styles, h e renderToString injetáveis.
- **Retorno:** Módulo de servidor com render que retorna html, styles e state.
- **Erros:** Propaga erros de entrada ou do renderizador; trate a rejeição antes de emitir a resposta HTTP.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderPreact, renderApp } from 'wu-framework/server';
const module = renderPreact(Card, { styles: ['h2{color:navy}'] });
const result = await renderApp('card', { module, props: { count: 2 } });
```

Precisa de preact e preact-render-to-string se as funções não forem injetadas.

Referência: `src/server/adapters.js`.

<span class="section-anchor" id="section-18"></span>

## renderSvelte

Adapta o renderizador do Svelte ao contrato de renderApp.

`renderSvelte(ComponentOrFn, options?): { render(props): Promise<RenderOutput> }`

- **Parâmetros:** Componente compilado para servidor e styles opcionais.
- **Retorno:** Módulo de servidor com render que retorna html, styles e state.
- **Erros:** Propaga erros de entrada ou do renderizador; trate a rejeição antes de emitir a resposta HTTP.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderSvelte, renderApp } from 'wu-framework/server';
const module = renderSvelte(Card);
const result = await renderApp('card', { module, props: { count: 2 } });
```

Svelte 4 usa Component.render; Svelte 5 importa svelte/server. O wrapper não adiciona out.head ao documento.

Referência: `src/server/adapters.js`.

<span class="section-anchor" id="section-19"></span>

## renderSolid

Adapta o renderizador do Solid ao contrato de renderApp.

`renderSolid(ComponentOrFn, options?): { render(props): Promise<RenderOutput> }`

- **Parâmetros:** Componente compilado para SSR e styles opcionais.
- **Retorno:** Módulo de servidor com render que retorna html, styles e state.
- **Erros:** Propaga erros de entrada ou do renderizador; trate a rejeição antes de emitir a resposta HTTP.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderSolid, renderApp } from 'wu-framework/server';
const module = renderSolid(Card);
const result = await renderApp('card', { module, props: { count: 2 } });
```

Resolve solid-js/web no ambiente servidor; não aceita um renderizador injetado como React.

Referência: `src/server/adapters.js`.

<span class="section-anchor" id="section-20"></span>

## renderHtml

Adapta o renderizador de Html ao contrato de renderApp.

`renderHtml(ComponentOrFn, options?): { render(props): Promise<RenderOutput> }`

- **Parâmetros:** Função (props) => string|Promise<string> e styles string/lista/função.
- **Retorno:** Módulo de servidor com render que retorna html, styles e state.
- **Erros:** Propaga erros de entrada ou do renderizador; trate a rejeição antes de emitir a resposta HTTP.
- **Permissões:** Não usa concessões do navegador; a aplicação servidor controla módulos, dados e cabeçalhos.
- **Limpeza:** Não cria listeners nem um runtime cliente persistente.

```js
import { renderHtml, renderApp } from 'wu-framework/server';
const module = renderHtml(({ count }) => `<p>${Number(count)}</p>`);
const result = await renderApp('card', { module, props: { count: 2 } });
```

O HTML retornado não é sanitizado. Escape o conteúdo externo antes de interpolá-lo.

Referência: `src/server/adapters.js`.

<span class="section-anchor" id="section-21"></span>

## createServerRequest

`createServerRequest(options?): WuServerRequest`

Cria um contexto privado por requisição com `signal`, `locals`, `renderApp`, `renderApps`, `stream` e `dispose`. Aceita opções de lote, incluindo `request`, e combina seu sinal com `options.signal`. Não crie esse objeto no escopo global do módulo. `dispose(reason)` aborta, libera listeners e limpa `locals`.

```js
import { createServerRequest, renderStateScript, escapeHtml, withSecurityHeaders } from 'wu-framework/server';

export const GET = withSecurityHeaders(async (request, { nonce }) => {
  const scope = createServerRequest({ request, nonce, timeout: 2000, concurrency: 2 });
  try {
    scope.locals.set('requestId', crypto.randomUUID());
    const rendered = await scope.renderApps([{
      name: 'greeting',
      load: async ({ signal }) => {
        signal.throwIfAborted();
        return { props: { label: 'Hello' }, publicState: { label: 'Hello' } };
      },
      module: { render: props => '<p>' + escapeHtml(props.label) + '</p>' },
    }]);
    return new Response(rendered.html + renderStateScript(rendered.state, { nonce }), {
      headers: { 'Content-Type': 'text/html; charset=utf-8' },
    });
  } finally {
    scope.dispose();
  }
});
```

`load(context)` recebe `{ appName, signal, request, locals }` e retorna `{ props?, publicState? }`. Com loader, apenas `publicState` vira estado de hidratação; nem props privadas nem o `state` retornado pelo renderer são publicados automaticamente. Sem loader, o `state` do renderer é preservado. Isso não impede o próprio renderer de escrever um segredo no HTML.

<span id="cancelación-plazos-y-concurrencia-ssr"></span>

<span class="section-anchor" id="section-22"></span>

## Cancelamento, prazos e concorrência SSR

`renderApp`, `renderApps` e `renderAppsStream` aceitam `signal` e `timeout` por app, incluindo o loader; `timeout: 0` desativa o prazo. Lotes e streams aceitam `concurrency`, ilimitada por padrão. O aborto preserva `signal.reason`; sem motivo fornecido usa `WU_SSR_ABORTED`. Vencer o prazo produz `WU_SSR_TIMEOUT`. Renderers e loaders devem cooperar com `context.signal` para parar seu trabalho.

Sem `failFast`, uma falha de app permite degradação parcial; com `failFast: true`, o lote é abortado. Cancelar o stream propaga o aborto ao trabalho pendente. Ao retornar um stream HTTP, mantenha o contexto até o consumo terminar ou ser cancelado; não chame `dispose()` logo após construir a resposta.

```js
// Reusable wrappers: a function generates a new nonce for each request.
wuSecurityMiddleware({ nonce: () => createNonce() });
withSecurityHeaders(handler, { nonce: () => createNonce() });
// Low-level helpers still accept the nonce of this response.
const nonce = createNonce();
const headers = securityHeaders({ nonce });
```