# O que uma rota devolve

A página padrão, seu próprio HTML, JSON, XML, texto, CSV, arquivos e PDF, e como fazer cada um.

Cada rota é uma tela em branco. Uma rota é uma pasta com um `index.tpl`, e o que esse template produz é a resposta, nada mais. O Nimbly não acrescenta layout, invólucro ou formato próprio.

- Para ter a página padrão, com o head, os assets e a edição na página, termine o template com `[#html#]`.
- Para ter seu próprio documento HTML, escreva-o.
- Para ter JSON, XML, texto simples, CSV, um arquivo ou um PDF, produza isso.

Todos usam os mesmos shortcodes, dados, templates, bibliotecas e permissões. Um site pode misturá-los à vontade: um site público com a shell padrão, uma landing page com documento próprio, um feed JSON, um sitemap e um download só para membros, lado a lado.

| A rota devolve | Como |
|---|---|
| A página padrão | `[#html#]` no final do `index.tpl` |
| Seu próprio documento HTML | Escreva o documento no `index.tpl`; veja [Seu próprio HTML](/pt/docs/guides/html-shell/) |
| JSON | `[#http-header json#]` e o JSON |
| XML, um feed | `[#http-header xml#]` e o XML |
| Texto simples | `[#http-header txt#]` e o texto |
| CSV | `[#http-header csv#]` e as linhas |
| Um arquivo | Uma biblioteca que envia os cabeçalhos e o conteúdo do arquivo |
| Um PDF | O módulo de PDF, a partir de um template HTML |
| Um redirecionamento | `[#redirect url#]` |
| Um código de status | `[#http-header 404#]`, `403` ou `500` |

## O endereço

Uma pasta de rota pode conter um ponto, então o endereço pode ter uma extensão:

```text
ext/uri/projects.json/index.tpl     /projects.json
ext/uri/feed.xml/index.tpl          /feed.xml
ext/uri/export/projects.csv/        /export/projects.csv
```

Uma rota dinâmica funciona do mesmo jeito, por exemplo `ext/uri/api/projects/(slug)/`, que responde JSON para um projeto. Veja [Roteamento](/pt/docs/concepts/routing/).

## O tipo de conteúdo

`[#http-header type#]` no início de um template define o `Content-Type`:

| Tipo | Content-Type |
|---|---|
| `json` | `application/json` |
| `xml` | `application/xml; charset=UTF-8` |
| `txt` | `text/plain; charset=UTF-8` |
| `csv` | `application/csv; charset=UTF-8` |
| `css` | `text/css` |
| `js` | `application/javascript` |

Para qualquer outro tipo, ou para cabeçalhos extras, use uma biblioteca com a função `header()` do PHP, como mostrado abaixo.

## JSON

`ext/uri/projects.json/index.tpl`:

```html
[#http-header json#]
[#data projects filter=published:1 sort=year|numeric|desc#]
[#fmt var=data.projects empty={} type=json#]
```

`[#fmt ... type=json#]` codifica uma variável; `[#get project.title json#]` codifica um único valor, com aspas e escape. As quebras de linha entre os shortcodes não fazem mal: o JSON permite espaços em branco.

Para um formato próprio, escreva-o no template:

```html
[#http-header json#][#data .config.site#]{"site": [#get data.config.site.name json#], "projects": [#data-count projects#]}
```

Quando a resposta precisa de lógica, monte-a numa biblioteca:

```php
<?php
// ext/lib/project-stats.php

function project_stats_sc($params)
{
    load_library('data');
    $projects = data_read('projects') ?: [];
    header('Content-Type: application/json');
    return json_encode([
        'total' => count($projects),
        'per_sector' => array_count_values(array_column($projects, 'sector')),
    ]);
}
```

`ext/uri/stats.json/index.tpl` tem uma linha: `[#project-stats#]`.

## XML e feeds

`ext/uri/feed.xml/index.tpl`:

```html
[#http-header xml#]<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Fieldwork projects</title>
    [#data projects filter=published:1 sort=year|numeric|desc limit=20#]
    [#repeat data.projects tpl=feed-item#]
  </channel>
</rss>
```

com um template por item, `ext/uri/feed.xml/feed-item.tpl`:

```html
<item>
  <title>[#fmt var=item.title type=plain#]</title>
  <link>[#base-url#]/projects/[#item.title_slug#]</link>
  <description>[#fmt var=item.description type=plain#]</description>
</item>
```

Todo site já responde `sitemap.xml` e `robots.txt`. Um recurso acrescenta seus registros ao sitemap com uma configuração `sitemap` no seu `.meta`.

## Texto simples

```html
[#http-header txt#][#data .config.site#][#get data.config.site.name#]
Projects: [#data-count projects#]
```

## CSV

```html
[#http-header csv#]title,sector,year
[#data projects filter=published:1#][#repeat data.projects tpl=csv-row#]
```

com `csv-row.tpl` contendo uma linha por registro. O admin também exporta qualquer recurso para usuários com `export-<resource>`.

## Arquivos

Os arquivos enviados à biblioteca de mídia são servidos em `/download/<uuid>`, com o tipo e o nome guardados.

Para servir um arquivo com suas próprias regras, como um documento só para membros ou um arquivo gerado na hora, deixe uma biblioteca enviá-lo:

```php
<?php
// ext/lib/member-document.php

function member_document_sc($params)
{
    load_library('access');
    if (!access_by_feature('view-member-documents')) {
        http_response_code(403);
        exit();
    }
    $path = $GLOBALS['SYSTEM']['file_base'] . 'ext/data/.member-files/handbook.pdf';
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment; filename="Member handbook.pdf"');
    header('Content-Length: ' . filesize($path));
    readfile($path);
    exit();
}
```

`ext/uri/members/handbook.pdf/index.tpl` contém `[#member-document#]`. O mesmo padrão envia um ZIP, uma imagem gerada na hora ou um arquivo de calendário: os cabeçalhos e os bytes são seus.

## Documentos PDF

O módulo de PDF transforma em PDF o HTML dos seus próprios templates, guarda o resultado em cache e o envia como download:

```bash
./nimbly module:install pdf
```

```php
load_library('pdf');
$pdf = pdf_render_cached_document([
    'paper_size' => 'a4',
    'orientation' => 'portrait',
    'pages' => [$html],
]);
pdf_send_download($pdf, 'Project-overview.pdf');
exit();
```

A chave do cache cobre o documento e o renderizador, então um texto ou template alterado gera um novo PDF sozinho.

## Imagens

As imagens enviadas são servidas em `/img/<uuid>/<size>`, no tamanho que o endereço pede e em WebP: `800w` para uma largura, `400x400c` para um recorte. Nos templates, `[#get-img-html#]` escreve o markup responsivo. Veja [Mídia e edição inline](/pt/docs/guides/media/).

## Redirecionamentos e códigos de status

```html
[#redirect [#base-url#]/en/#]
```

```html
[#http-header 404#][#http-header json#]{"error": "not found"}
```

Uma rota dinâmica que não aceita uma requisição cai na página 404 do site, que `ext/uri/errors/404/` pode substituir.

## A API REST

Todo recurso também responde em `/api/v1/<resource>` com JSON, para listar, ler, criar, alterar e excluir, com as permissões de quem chama. Use-a para apps e integrações, e escreva rotas próprias para o que ela não cobre. Veja a [referência da API REST](/pt/docs/reference/api/).
