# Functions no Firewall

Uma função em um [firewall](/pt-br/documentacao/plataforma/firewall/) é código JavaScript que o firewall executa em uma requisição quando uma das suas regras a chama. O código recebe a requisição como um evento `firewall`. Os métodos desse evento decidem o que acontece com a requisição: adicionam headers e a deixam seguir, a negam, a descartam ou a respondem. Para acompanhar uma requisição da regra até a função e de volta, consulte [Como Firewall funciona](/pt-br/documentacao/plataforma/firewall/como-funciona/).

Uma função em um firewall é executada antes da aplicação, então o código dela decide se uma requisição chega ou não à aplicação. O código que participa de servir uma requisição que o firewall permitiu roda em uma aplicação, a partir de uma função cujo ambiente de execução é `application`. Para a instância que coloca essa função em uma aplicação, consulte [Instâncias de função](/pt-br/documentacao/plataforma/applications/functions-instances/).

---

## Ambiente de execução

Toda função carrega um ambiente de execução, e um firewall executa somente uma função cujo ambiente é `firewall`. Você define o ambiente ao criar a função em [Functions](/pt-br/documentacao/plataforma/functions/):

| Interface | Configuração                                                   | Valor para uma função de firewall |
| --------- | -------------------------------------------------------------- | --------------------------------- |
| API       | `execution_environment`, um campo da função                    | `firewall`                        |
| Azion CLI | `--execution-environment`, uma flag de `azion create function` | `firewall`                        |

O campo da API recebe `application` ou `firewall`, e o padrão é `application`. Uma função criada sem o campo é uma função de aplicação, e a API recusa uma instância dela em um firewall. A ajuda da CLI diz `Either 'edge_application' or 'edge_firewall'` para a flag. Nenhum dos dois valores está no enum da API, e a API recusa ambos. `azion describe function --function-id <function-id> --format json` imprime o campo de uma função existente, como `"execution_environment": "application"`.

No Azion Console, o campo **Function** de uma instância de função lista somente as funções cujo ambiente é `firewall`.

Uma função com o ambiente `firewall` ainda não é executada em nenhuma requisição até que outros dois objetos apontem para ela. Uma [instância de função](/pt-br/documentacao/plataforma/firewall/functions-instances/) coloca a função em um firewall, e uma regra cujo comportamento *Run Function* nomeia essa instância a chama. Para escrever essa regra, consulte [Run Function](/pt-br/documentacao/plataforma/firewall/rules-engine/#run-function).

O firewall também precisa ter Functions habilitado. Até que tenha, Azion Console oculta a aba **Functions Instances** do firewall e lista o comportamento como *Run Function - required Functions*, que não pode ser selecionado. O switch **Functions** fica na seção **Modules** da aba **Main Settings** do firewall. Um firewall criado pela API, pela CLI ou pela página de criação do Azion Console começa com Functions habilitado. O drawer de criação do Azion Console começa com ele desativado.

---

## O evento firewall

Uma função em um firewall registra um listener para o evento `firewall` com `addEventListener`. O listener recebe o evento, que carrega a requisição em `event.request` e os métodos que decidem o que acontece com ela.

Para ler um header que a requisição já carrega, chame `event.request.headers.get(<name>)`. O exemplo [Functions em um firewall](/pt-br/documentacao/plataforma/functions/general-firewall-example/) lê vários headers da requisição dessa forma para escolher o que o seu handler faz.

Toda função em um firewall precisa terminar com um resultado final, como `event.continue()`, `event.deny()` ou `event.drop()`. Para escrever condicionais que sempre chegam a um resultado, consulte [Boas práticas de Firewall](/pt-br/documentacao/plataforma/firewall/boas-praticas/).

---

## Métodos do evento

A tabela lista os métodos que uma função em um firewall chama no evento `firewall`, em ordem alfabética.

| Método                      | Argumentos                                         | O que faz                                                                                                                               |
| --------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `event.addRequestHeader()`  | Um nome de header e o seu valor                    | Adiciona o header à requisição que segue para a origem                                                                                  |
| `event.addResponseHeader()` | Um nome de header e o seu valor                    | Adiciona o header à resposta que o usuário recebe                                                                                       |
| `event.args()`              | O nome de um argumento, como `'arg_name'`          | Lê esse argumento dos **Arguments** da instância de função                                                                              |
| `event.continue()`          | Nenhum                                             | Encerra a função com um resultado final. O firewall retoma o processamento a partir do comportamento *Run Function* que chamou a função |
| `event.deny()`              | Nenhum                                             | Finaliza a requisição com HTTP `403 Forbidden`. O status, o corpo e o motivo são fixos                                                  |
| `event.drop()`              | Nenhum                                             | Finaliza a requisição sem resposta ao cliente                                                                                           |
| `event.respondWith()`       | Um objeto `Response`                               | Intercepta a requisição e a responde com uma resposta personalizada, cujo status, headers e conteúdo o objeto define                    |
| `event.waitUntil()`         | Uma promise, como a que um handler `async` retorna | Executa um handler `async` a partir do listener síncrono. Sem ele, a promise pode terminar em exceções inesperadas                      |

### event.addRequestHeader

`event.addRequestHeader()` adiciona um header à requisição que segue para a origem. Ele recebe dois argumentos, o nome do header e o seu valor. Este listener adiciona dois headers e deixa a requisição seguir:

```javascript
  addEventListener("firewall", (event) => {
      event.addRequestHeader("X-Custom-Header-1", "1");
      event.addRequestHeader("X-Custom-Header-2", "2");
      event.continue();
  });
```

### event.addResponseHeader

`event.addResponseHeader()` adiciona um header à resposta que o usuário recebe. Ele recebe os mesmos dois argumentos, o nome do header e o seu valor. Este listener adiciona dois headers de resposta e deixa a requisição seguir:

```javascript
  addEventListener("firewall", (event) => {
      event.addResponseHeader("X-Custom-Header-3", "3");
      event.addResponseHeader("X-Custom-Header-4", "4");
      event.continue();
  });
```

### event.deny

`event.deny()` finaliza a requisição com HTTP `403 Forbidden`. Ele não recebe argumentos, então a função não pode alterar o status, o corpo nem o motivo dessa resposta. Para uma resposta que a função controla, o método a chamar é `event.respondWith()`. Este listener nega toda requisição que recebe:

```javascript
  addEventListener("firewall", (event) => {
      event.deny();
  });
```

### event.drop

`event.drop()` finaliza a requisição sem resposta ao cliente e não recebe argumentos. Este listener descarta toda requisição que recebe:

```javascript
  addEventListener("firewall", (event) => {
      event.drop();
  });
```

### event.respondWith

`event.respondWith()` intercepta a requisição e a responde com uma resposta personalizada. Ele recebe um objeto `Response`, que define o status, os headers e o conteúdo da resposta. A chamada desta seção é executada dentro de um listener `firewall` e responde com um corpo JSON, o status `599` e um `content-type` igual a `application/json`:

```javascript
    event.respondWith(new Response('{"my_custom_response": true}', {
        status: 599,
        headers: { "content-type": "application/json" }
    }));
```

---

## Metadados

Uma função em um firewall lê metadados da requisição para filtrar o acesso à aplicação e aplicar lógicas diferentes por cenário. Quatro grupos desses metadados descrevem de onde uma requisição vem e como ela chega. A referência [API de metadados](/pt-br/documentacao/devtools/runtime/api-reference/metadata/) lista os campos de cada grupo.

| Grupo  | O que contém                                                                               | Campos                                                                                     |
| ------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| GeoIP  | De onde a requisição vem. Use-o para negar o acesso à aplicação a partir de certos lugares | [Metadados de GeoIP](/pt-br/documentacao/devtools/runtime/api-reference/metadata/#geoip)   |
| Remote | O endereço IP e a porta TCP que o cliente usa                                              | [Metadados de Remote](/pt-br/documentacao/devtools/runtime/api-reference/metadata/#remote) |
| Server | O protocolo que a requisição usa                                                           | [Metadados de Server](/pt-br/documentacao/devtools/runtime/api-reference/metadata/#server) |
| TLS    | Detalhes disponíveis quando a requisição chega por uma conexão TLS segura                  | [Metadados de TLS](/pt-br/documentacao/devtools/runtime/api-reference/metadata/#tls)       |

---

## Limites

Uma função em um firewall é executada dentro de dois conjuntos de limites. Os limites da própria função, como tamanho do código, memória, tempo de CPU e sub-requisições, estão em [Limites de Functions](/pt-br/documentacao/plataforma/functions/limites/). Os limites do firewall e das suas instâncias de função estão em [Limites de Firewall](/pt-br/documentacao/plataforma/firewall/limites/).

Os argumentos de uma instância de função, que a função lê com `event.args()`, comportam no máximo 100.000 bytes. Um payload maior é recusado com `Value size (in bytes) is too big. Maximum size allowed is 100000 bytes.`

---

## Erros

Duas recusas vêm do ambiente de execução de uma função. Azion CLI imprime cada mensagem entre colchetes, depois de `Error: Failed to create function:` ou de `Error: failed to create the Firewall Function Instance:`. `azion create function` encerra a mensagem com `Check your settings and try again. If the error persists, contact Azion support`.

| Mensagem                                                                               | Comando                          | O que causa                                                                                   | O que fazer                                                 |
| -------------------------------------------------------------------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `"edge_firewall" is not a valid choice.`                                               | `azion create function`          | `--execution-environment edge_firewall`, um valor que a ajuda da CLI lista e a API não aceita | Use `--execution-environment firewall`                      |
| `Invalid edge function runtime. You should use a function designed for Edge Firewall.` | `azion create firewall-instance` | O ambiente de execução da função é `application`                                              | Instancie uma função cujo ambiente de execução é `firewall` |

---

## Recursos relacionados

- [Execute uma função em um firewall](/pt-br/documentacao/guias/desenvolvimento-de-aplicacoes/functions-e-runtime/firewall.md): O procedimento que cria uma função, a instancia em um firewall e a chama a partir de uma regra no Azion Console.
- [Instancie uma função em um firewall](/pt-br/documentacao/guias/seguranca-de-aplicacoes/firewall-e-waf/instanciar-functions.md): O procedimento que cria uma instância de função em um firewall pela Azion API.
- [Exemplos em JavaScript](/pt-br/documentacao/plataforma/functions/javascript-exemplos.md#firewall): Funções completas que são executadas em um firewall, para copiar como ponto de partida.
- [Boas práticas de Firewall](/pt-br/documentacao/plataforma/firewall/boas-praticas.md): Como escrever condicionais e código assíncrono para que uma função de firewall sempre chegue ao seu resultado.
