# Processe o corpo de uma requisição

Leia o corpo que o cliente envia e responda pela function, sem encaminhar a requisição para uma origem. O objeto `Request` expõe um método de parse para cada formato, e o header `Content-Type` da requisição diz qual deles chamar. Use este padrão em endpoints que recebem um payload: um receptor de webhook, um handler de formulário ou um endpoint de upload que inspeciona o que recebe antes de armazenar.

Este handler usa o padrão ES Modules, recomendado pela Azion. O restante desta coleção está escrito no padrão Service Worker.

```js
async function handleBodyAsJSON(request) {
  const data = await request.json();

  data.received = true;
  data.timestamp = new Date().toISOString();

  return new Response(JSON.stringify(data), {
    headers: { 'Content-Type': 'application/json' }
  });
}

async function handleBodyAsFormData(request) {
  const form = await request.formData();

  form.append('new-field-1', '1');

  return new Response(form);
}

async function handleBodyAsText(request) {
  const text = await request.text();

  return new Response(text);
}

async function handleBodyAsBlob(request) {
  const blob = await request.blob();

  return new Response(await blob.text());
}

async function handleBodyAsStream(request) {
  const reader = request.body.getReader();
  const decoder = new TextDecoder('utf-8');
  let body = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    body += decoder.decode(value);
  }

  return new Response(body);
}

export default {
  async fetch(request, env, ctx) {
    if (!request.body) {
      return new Response('No request body was sent');
    }

    const contentType = request.headers.get('Content-Type') || '';

    try {
      if (contentType.includes('application/json')) {
        return await handleBodyAsJSON(request);
      }
      if (contentType.includes('multipart/form-data') || contentType.includes('application/x-www-form-urlencoded')) {
        return await handleBodyAsFormData(request);
      }
      if (contentType.includes('text/plain')) {
        return await handleBodyAsText(request);
      }
      if (contentType.includes('application/octet-stream')) {
        return await handleBodyAsBlob(request);
      }
      return await handleBodyAsStream(request);
    } catch (error) {
      return new Response(`Error processing request: ${error.message}`, { status: 400 });
    }
  }
};
```

## Como funciona

O método `fetch` verifica `request.body` primeiro. Uma requisição sem corpo, como um `GET`, responde `No request body was sent` e nunca chega a um parser.

Quando há corpo, o handler lê o header `Content-Type` e direciona para um método de parse. Cada método consome o corpo uma vez e o devolve no formato correspondente:

| `Content-Type`                                               | Método                     | O que o handler faz                                                                                      |
| ------------------------------------------------------------ | -------------------------- | -------------------------------------------------------------------------------------------------------- |
| `application/json`                                           | `request.json()`           | Faz o parse do payload em um objeto, adiciona o campo `received` e um `timestamp`, e o retorna como JSON |
| `multipart/form-data` ou `application/x-www-form-urlencoded` | `request.formData()`       | Lê os campos em um objeto `FormData` e adiciona um campo antes de retorná-lo                             |
| `text/plain`                                                 | `request.text()`           | Lê o corpo como string e o devolve                                                                       |
| `application/octet-stream`                                   | `request.blob()`           | Lê o corpo como binário e retorna seu texto                                                              |
| Qualquer outro                                               | `request.body.getReader()` | Lê o stream bloco a bloco, decodificando cada bloco como UTF-8                                           |

O branch de stream é o fallback, então um content type não reconhecido ainda é lido em vez de descartado. Ele também é o branch a usar quando o corpo é grande o bastante para que manter todo o payload em memória importe: o reader entrega um bloco por vez, e o loop termina quando `done` é verdadeiro.

Um corpo só pode ser lido uma vez. Chamar dois métodos de parse na mesma requisição lança um erro, e por isso o handler escolhe exatamente um branch e o retorna.

Todos os métodos de parse usam `await` dentro do bloco `try`, então um payload malformado é capturado em vez de escapar do handler. Um corpo que não corresponde ao tipo declarado, como `{not json` enviado como `application/json`, responde `400` com a mensagem do próprio parser. Retornar a promise do parser sem `await` deixaria a rejeição fora do `try`, e o cliente receberia um erro de execução.

## Recursos relacionados

- [Exemplos de JavaScript](/pt-br/documentacao/plataforma/functions/javascript-exemplos.md): Veja os demais snippets desta coleção.
- [Request](/pt-br/documentacao/devtools/runtime/api-reference/request.md): Os métodos de parse que este handler chama e o que cada um retorna.
- [Response](/pt-br/documentacao/devtools/runtime/api-reference/response.md): Consulte o status, os headers e as opções de corpo que o construtor aceita.
- [Migre padrões de handler em Functions](/pt-br/documentacao/guias/desenvolvimento-de-aplicacoes/functions-e-runtime/migrar-padroes-de-handler.md): O handler ES Modules que este exemplo usa e seu equivalente em Service Worker.
- [Limites de Functions](/pt-br/documentacao/plataforma/functions/limites.md): Os limites de corpo de requisição e de resposta em que uma execução roda.
- [Desenvolva e teste uma function localmente](/pt-br/documentacao/plataforma/functions/local-development.md): Rode este handler na sua máquina e envie uma requisição antes de fazer o deploy.
