# Instale Send Event to Endpoint

Azion **Send Event to Endpoint** é uma integração *serverless* disponível no **Marketplace da Azion**. Essa integração permite transmitir dados de uma requisição para um endpoint HTTP, recolhendo os dados de requisição e os transmitindo para um endpoint definido pelo usuário por meio de uma API Javascript.

A integração também possibilita que você especifique que tipo de dados deseja recolher editando um arquivo `JSON`.

Após o envio dos dados coletados, a integração permite que a requisição prossiga através do Rules Engine.

---

## Obtenha a integração

Para usar a integração **Send Event to Endpoint**, siga estes passos:

1. Acesse o [Azion Console](/pt-br/documentacao/produtos/guias/como-acessar-o-azion-console/) > **Marketplace**.
2. Na homepage do Marketplace, selecione o card da integração.
3. Quando a página da integração abrir, clique no botão **Install**.

Aparecerá uma mensagem indicando que sua integração foi instalada com sucesso.

:::tip
Você pode procurar qualquer integração navegando pelos cards, usando os filtros ou digitando uma palavra-chave na barra de busca.
:::

---

## Configure a integração

### Configure um firewall

Para iniciar este processo, siga os passos:

1. Em **Products menu**, selecione **Firewall** na seção **Secure**.
2. Clique no botão **+ Firewall**.
3. Dê um nome fácil de lembrar ao seu firewall.
4. Habilite o switch para **Functions**.
5. Clique no botão **Save**

Pronto. Você instanciou o firewall para sua função.

### Instancie a integração

Para instanciar a integração **Send Event to Endpoint**, enquanto ainda estiver na página do **Firewall**:

1. Selecione a aba **Functions Instances** e siga estas passos:
2. Clique no botão **+ Function Instance**.
3. Dê um nome fácil de lembrar à sua instância.
4. No menu suspenso, selecione a função **Send Event to Endpoint**.
  - Esta ação irá carregar a aba **Arguments**.

O formulário `JSON` dos **Arguments** para esta integração ficará assim:

```json
{
  "metadata": ["remote_addr"],
  "headers": ["x-hello"],
  "body": ["message", "user.id"],
  "http_connection_args": {
	"endpoint": "http://example_api:3000/test",
	"headers": {
  	"Authorization": "FakeAuth",
  		"X-Provider": "Azion Cells"
	}
  }
}
```

**Onde**:

| **Campo** | **Obrigatório** | **Tipo de dado** | **Notas** |
|---|---|---|---|
| `metadata` | Não | Null ou Array | Define quais campos de metadados serão transmitidos.<br /><br />Quando for definido como `null` (ou não for definido), todos os campos de metadados serão transmitidos.<br /><br />Se você não quiser transmitir nenhum metadado, deverá definir uma matriz vazia `[ ]` como o valor desse campo. |
| `headers` | Não | Null ou Array | Define quais cabeçalhos de requisição serão transmitidos.<br /><br />Quando for definido como `null` (ou não for definido), todos os cabeçalhos de requisição serão transmitidos.<br /><br />Se você não quiser transmitir nenhum cabeçalho, deverá definir uma matriz vazia `[ ]` como o valor desse campo. |
| `body` | Não | Null ou Array | Define quais campos do `body request` serão transmitidos.<br /><br />Quando for definido como `null` (ou não for definido), todos os campos do corpo da requisição serão transmitidos.<br /><br />Se você não quiser transmitir nenhum campo `body request`, você deverá definir uma matriz vazia `[ ]` como o valor desse campo.<br /><br />Para filtrar campos de vários níveis, use a notação de ponto. Por exemplo, se você usar a string `user.name`, a função procurará o campo "name" dentro do objeto "user" no `body request`. |
| `connection_args` | Sim | Objeto | Define os dados que serão usados para transmitir os dados da requisição.<br /><br /><br />A URL na qual os dados serão postados é definida pelo endpoint.<br /><br /><br />Os cabeçalhos especificam quais cabeçalhos serão incluídos na requisição de busca.<br /><br /><br />Um cabeçalho adicional <br />`Content-Type: application/json`<br /> será usado. |
| `s3_connection_args` | Não | Objeto | Define os argumentos a serem usados com um bucket S3. |
| `s3_connection_args.endpoint` | Apenas ao usar `s3_connection_args` | String | Define o endpoint do provedor S3. |
| `s3_connection_args.bucket` | Apenas ao usar `s3_connection_args` | String | Define o nome do bucket de destino. |
| `s3_connection_args.region` | Apenas ao usar <br />`s3_connection_args` | String | Define a região do bucket S3. |
| `s3_connection_args.access_key` | Apenas ao usar <br />`s3_connection_args` | String | Define a chave de acesso usada para conectar-se com o bucket S3. |
| `s3_connection_args.secret_key` | Apenas ao usar <br />`s3_connection_args` | String | Define uma chave secreta para ser usada na conexão com o bucket S3. |
| `s3_connection_args.file_path` | Não | String | Define o caminho do arquivo criado para armazenar a função.<br />Valor padrão: `/` |
| `s3_connection_args.use_date_prefix` | Não | String | Quando habilitado, incluirá uma sub-pasta com a data atual (no formato YYYY-MM-DD) para o caminho do arquivo.<br />Valor padrão: `true` |

Esta integração retornará uma resposta com os dados transmitidos em um arquivo `JSON` com a seguinte aparência:

```json
{
  "body": {
	"field_a": <data>,
	...
  },
  "geoip_asn": <data>,
  "geoip_city": <data>,
  "geoip_city_continent_code": <data>,
  "geoip_city_country_code": <data>,
  "geoip_city_country_name": <data>,
  "geoip_continent_code": <data>,
  "geoip_country_code": <data>,
  "geoip_country_name": <data>,
  "geoip_region": <data>,
  "geoip_region_name": <data>,
  "headers": {
	"x-header-a": <data>,
	...
  },
  "remote_addr": <data>,
  "remote_port": <data>,
  "remote_user": <data>,
  "request_id": <data>,
  "request_url": <data>,
  "server_protocol": <data>,
  "ssl_cipher": <data>,
  "ssl_protocol": <data>
}
```

Observe como os campos `request_id`, `request_url` e metadados serão entregues na raiz do arquivo `JSON`, enquanto os campos body e os cabeçalhos da requisição serão enviados nos objetos.

Você também pode usar um arquivo `JSON` "catch-all" para as Args, como este:

```json
{
    "connection_args": {
        "endpoint": "http://example_api:3000/test",
    }
}
```

#### Saída dos arquivos S3

:::caution[Compatibilidade com HMAC no Amazon S3]
Esta integração **não é compatível com autenticação HMAC via AWS Signature Version 4 (SigV4)**. Se o seu bucket Amazon S3 estiver com HMAC habilitado, a função falhará ao tentar entregar os dados e você verá o seguinte erro no **Real-Time Events**:

```xml
<Error>
  <Code>InvalidRequest</Code>
  <Message>Missing required header for this request: x-amz-content-sha256</Message>
</Error>
```

O header `x-amz-content-sha256` é exigido pela autenticação HMAC SigV4 da AWS, que esta integração não gera.

**Para resolver esse problema**, desabilite a autenticação HMAC no seu bucket S3. Consulte a [documentação da AWS sobre autenticação no S3](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html) para mais detalhes.
:::

Para cada nova execução da função, um novo arquivo será gerado no bucket S3 fornecido. O arquivo será nomeado com base no ID da requisição que iniciou a função.

Exemplo: se o parâmetro `connection_args.file_path` estiver definido como `/meus-dados/` e a função for executada em 9 de maio de 2023, com o ID da requisição `abcd-1234`, o arquivo resultante será salvo em `/meus-dados/2023-05-09/abcd-1234.json`. Se o parâmetro `connection_args.use_date_prefix` estiver definido como `false`, o arquivo resultante será salvo como `/meus-dados/abcd-1234.json`.

Se não forem fornecidos `http_connection_args` ou `s3_connection_args` nos argumentos JSON, a função não terá nenhum argumento de conexão válido para utilizar. A requisição será encerrada e uma mensagem de erro em formato JSON será enviada para indicar a causa do problema.

```json
{
  "error": "A001",
  "detail": "The function instance is missing or has invalid required arguments."
}
```

Se a função não conseguir se conectar ao endpoint HTTP ou ao provedor S3, a requisição do usuário será ignorada. Independentemente disso, um registro de erro será criado, ao qual o cliente poderá ter acesso por meio do Data Stream.

Por exemplo, se uma chave de acesso inválida for usada, será exibido o seguinte aviso:

```json
[Send event to endpoint] S3 connection error; 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Error>
	<Code>InvalidAccessKeyId</Code>
	<Message>The key 'DAKEY' is not valid</Message>
</Error>
```

Por fim, se você fornecer as opções de conexão corretas tanto para o endpoint HTTP quanto para o bucket S3, a função entregará os dados do evento para ambas as fontes simultaneamente.

### Configure o Rules Engine

Para concluir, você precisa configurar o **Rules Engine** para definir o *comportamento* e os *critérios* para executar a integração.

Ainda na página **Firewall**:

1. Selecione a aba **Rules Engine**.
2. Clique no botão **+ Rule Engine**.
3. Dê um nome fácil de lembrar à sua nova regra.
4. Selecione um *criteria* (critério) para executar a integração.
  - Exemplo: if `Host` *matches* `yourdomain.com`.
5. Abaixo, selecione um *behavior* (comportamento) para os *criteria* (critérios). Neste caso, será **Run Function**.
   - Selecione a função adequada de acordo com o nome que você deu na etapa de instanciação.
6. Clique no botão **Save**.

Agora, no Console, você deve configurar seu domínio para que ele seja protegido pelo seu firewall.

7. No **Products menu**, selecione **Workloads**.
8. Clique no domínio que você deseja proteger com sua função **Sent Event to Endpoint**.
9. Na seção **Settings**, clique no seletor de `Firewall` e escolha o firewall que você acabou de criar.
10. Clique no botão **Save**.

Pronto. Agora, a integração **Send Event to Endpoint** está sendo executada para cada requisição feita ao domínio indicado.

---