azukiapp/azk

View on GitHub
docs/content/pt-BR/adding-services/ngrok.md

Summary

Maintainability
Test Coverage
# ngrok

![ngrok](../resources/images/ngrok.png)
> Screenshot da [página do GitHub do ngrok](https://github.com/inconshreveable/ngrok)

> Nota: Você pode checar o resultado final na branch [ngrok-final](https://github.com/azukiapp/azkdemo-services/tree/ngrok-final) do projeto [azkdemo-services](https://github.com/azukiapp/azkdemo-services/).

[ngrok](https://ngrok.com/) é um proxy reverso que cria um "túnel" seguro a partir de um endpoint público para um web service sendo executado localmente. Em outras palavras, você pode utilizar o ngrok para expor uma porta em seu sistema, por exemplo, a porta em que sua aplicação Node.js está rodando, a uma URL pública. Ele também disponibiliza uma interface web muito legal para analisar todo o tráfego enviado através da sua aplicação, e até mesmo repetir chamadas (GET, POST, etc).

![interface web do ngrok](../resources/images/azk-services-5.png)

Um cenário onde ngrok pode ser realmente útil é se você precisa testar webhooks. Um webhook é basicamente um request POST feito para o seu serviço web. Um monte de empresas como [GitHub](https://developer.github.com/webhooks/), [Evernote](https://dev.evernote.com/doc/articles/polling_notification.php), [SendGrid](https://sendgrid.com/docs/API_Reference/Webhooks/index.html), [Twilio](https://www.twilio.com/platform/webhooks), oferecem webhooks para diferentes fins.

No nosso caso, o que nós vamos fazer é adicionar o ngrok a nossa aplicação, e para simplificar, adicionar uma endpoint GET que podemos usar para adicionar uma mensagem para a caixa de mensagens do nosso aplicativo, semelhante ao que aconteceu quando mandamos e-mails clicando no botão "Send email" na [última seção](./mailcatcher.md).

Vamos começar! Vamos assumir que você está vindo da seção anterior, [MailCatcher](./mailcatcher.md). Caso queira começar diretamente dessa seção, baixe o projeto base e troque de branch executando:

```javascript
$ git clone https://github.com/azukiapp/azkdemo-services.git
$ git checkout mailcatcher-final
```

Antes de tudo, vamos adicionar o sistema `ngrok` ao nosso Azkfile.js. Abra o arquivo e adicione-o no final:

```javascript
...
  // MailCatcher system
  mail: {
    ...
  }

  // ngrok system
  ngrok: {
    // Dependent systems
    depends: ["azkdemo-services"],
    // More images:  http://images.azk.io
    image: {"docker": "azukiapp/ngrok:latest"},
    wait: {"retry": 20, "timeout": 1000},
    http: {
      domains: [
        "#{manifest.dir}-#{system.name}.#{azk.default_domain}",
      ],
    },
    ports: {
      // exports global variables
      http: "4040",
    },
    envs: {
      // set instances variables
      NGROK_CONFIG: "/ngrok/ngrok.yml",
      NGROK_LOG: "/ngrok/logs/ngrok.log",
    },
  },
}
```

Você pode ver que nós adicionamos o nosso sistema principal "azkdemo-services" como uma dependência para o nosso sistema "ngrok". Por que isso?

Ao contrário de outros serviços, como o MailCatcher, o ngrok precisa de um serviço web funcionando em uma porta antes que possa ser executado. Ao adicionar a nossa aplicação Node.js para o parâmetro `depends`, podemos garantir que isso será o caso.

Só mais uma coisa antes de executarmos nossos sistemas, nós precisamos passar para o ngrok não só a porta, mas a URL onde ele pode encontrar nossa aplicação. Então, vamos fazer isso exportando uma variável de ambiente no nosso sistema "azkdemo-services". Vamos adicionar a propriedade `export_envs` nele:

```javascript
...
  'azkdemo-services': {
    // Dependent systems
    depends: ["mail", "redis"],
    // More images:  http://images.azk.io
    image: {"docker": "azukiapp/node:0.12"},
    // Steps to execute before running instances
    provision: [
      "npm install",
    ],
    workdir: "/azk/#{manifest.dir}",
    shell: "/bin/bash",
    command: ["npm", "start"],
    wait: {"retry": 20, "timeout": 1000},
    mounts: {
      '/azk/#{manifest.dir}': path("."),
      '/azk/#{manifest.dir}/node_modules': persistent("#{system.name}-node_modules"),
    },
    scalable: {"default": 1},
    http: {
      domains: [ "#{system.name}.#{azk.default_domain}" ]
    },
    envs: {
      // set instances variables
      NODE_ENV: "dev",
    },
    export_envs: {
      // exports variables for dependent systems
      APP_URL: "#{system.name}.#{azk.default_domain}:#{net.port.http}",
    },
  },
  ...
}
```

A variável APP_URL estará disponível para o sistema "ngrok", e usará isso para expor nossa aplicação Node.js. Vamos levantar nossos sistemas:

```
$ azk start
```

Você deverá ver o seguinte output:

```
┌───┬─────────────────────┬───────────┬──────────────────────────────────────────┬────────────────────────────┬──────────────┐
│   │ System              │ Instances │ Hostname/url                             │ Instances-Ports            │ Provisioned  │
├───┼─────────────────────┼───────────┼──────────────────────────────────────────┼────────────────────────────┼──────────────┤
│ ↑ │ redis               │ 1         │ dev.azk.io                               │ 1-6379:49351               │ -            │
├───┼─────────────────────┼───────────┼──────────────────────────────────────────┼────────────────────────────┼──────────────┤
│ ↑ │ mail                │ 1         │ http://mail.azkdemo.dev.azk.io           │ 1-smtp:49358, 1-http:49357 │ -            │
├───┴─────────────────────┴───────────┴──────────────────────────────────────────┴────────────────────────────┴──────────────┤
│ ↑ │ azkdemo-services    │ 1         │ http://azkdemo-services.dev.azk.io       │ 1-http:49352               │ -            │
├───┼─────────────────────┼───────────┼──────────────────────────────────────────┼────────────────────────────┼──────────────┤
│ ↑ │ ngrok               │ 1         │ http://azkdemo-services-ngrok.dev.azk.io │ 1-http:49340               │ -            │
└───┴─────────────────────┴───────────┴──────────────────────────────────────────┴────────────────────────────┴──────────────┘
```

Vamos abrir nossa URL do ngrok: http://azkdemo-services-ngrok.dev.azk.io

![ngrok's neat web interface](../resources/images/azk-services-5.png)

Legal, o ngrok está funcionando e já podemos verificar sua interface de administração que nos permite analisar e repetir requests. Uma coisa que ainda não conseguimos fazer é realmente ver nossa URL que o ngrok criou como um endpoint público. Então vamos corrigir isso.

Primeiro de tudo, vamos criar uma nova pasta chamada "logs" no diretório do projeto:

```
$ mkdir logs
```

Agora, o que nós podemos fazer é "sincronizar" todos os arquivos de log criados dentro do sistema ngrok ao nosso diretório do projeto. Vamos fazer isso editando o Azkfile.js, dentro do sistema `ngrok`, e adicionando o parâmetro` mounts`:

```javascript
...
  // ngrok system
  ngrok: {
    // Dependent systems
    depends: ["azkdemo-services"],
    // More images:  http://images.azk.io
    image: {"docker": "azukiapp/ngrok:latest"},
    wait: {"retry": 20, "timeout": 1000},
    http: {
      domains: [
        "#{manifest.dir}-#{system.name}.#{azk.default_domain}",
      ],
    },
    ports: {
      // exports global variables
      http: "4040",
    },
    mounts: {
      '/ngrok/logs' : path("./logs"),
    },
    envs: {
      // set instances variables
      NGROK_CONFIG: "/ngrok/ngrok.yml",
      NGROK_LOG: "/ngrok/logs/ngrok.log",
    },
  },
  ...
}
```

 O parâmetro `mounts` irá definir:

- `'ngrok/logs'`: a pasta e seu conteúdo, criadas dentro de nosso sistema (`ngrok` neste caso) que queremos "sincronizar".
- `path("./logs)"`: o parâmetro `path` vai definir onde esses arquivos estarão disponíveis dentro da pasta do nosso projeto. Nesse caso, os arquivos estarão na pasta `./logs` que criamos no passo anterior.

Vamos reiniciar o nosso sistema para atualizá-lo com essas alterações:

```
$ azk restart
```

Agora, depois de reiniciar o sistema e eles estarem funcionando, você deve ver um novo arquivo criado dentro da nossa pasta `logs` chamado de `ngrok.log`. Abra o arquivo e você verá um monte de outputs de log do `ngrok`. Procure por "Tunnel established at" e você será capaz de ver o nosso endpoint público que o `ngrok` disponibilizou.

Copie esse endereço (algo como https://f896d41.ngrok.com) no seu navegador e abra-o. Você deverá ver exatamente a sua aplicação:

![azkdemo services](../resources/images/azk-services-6.png)

A diferença de acessar essa URL ao invés da mostrada no output do comando `azk start` é que você pode compartilhar ela com outras pessoas, e elas serão capazez de acessá-la, o que é exatamente a razão pela qual elas são úteis para testar rapidamente webhooks sem a necessidade de realizar o deploy de sua aplicação.

Assim como dissemos no início do tutorial, agora vamos adicionar um endpoint GET em nossa aplicação que irá adicionar uma mensagem a caixa de mensagens. Abra o arquivo `src/index.js` e adicione um endpoint `/webhook` a ele:

```javascript
...
// Send mail
app.get('/mail', require('./send_email.js'));

// Webhooks
app.get('/webhook', function(req, res) {
  io.sockets.emit('msgs', req.param('msg'));
  res.send('Message sent');
});

// setup views with ejs
app.use('/public', express.static(path.join(rootPath, 'public')));
...
```

Salve o arquivo, e uma vez que estamos usando `nodemon`, ele irá recarregar automaticamente a nossa aplicação. Sua URL do `ngrok` também continuará a mesma. Se você já tinha uma aba aberto do passo anterior, basta abrir uma nova com o mesmo endereço (novamente, algo como https://f896d41.ngrok.com). Agora você deve ter duas abas abertas com a nossa aplicação. Na segunda aba, adicione ao final do endereço o seguinte:

```
https://f896d41.ngrok.com/webhook?msg=hello
```

A página deve atualizar e mostrar um texto "Message sent"! Volte para a primeira aba, e você deve ver uma mensagem dizendo "ngrok: hello":

![azkdemo ngrok](../resources/images/azk-services-7.png)

E é isso!

Testar um webhook de outro serviço como os mencionadas no início deve ser tão simples quanto mudar o endpoint `/webhook` para POST ao invés de GET, e, em seguida, trabalhar com os dados que serão enviados como parte do objeto `req`. :)

> Nota: Você pode checar o resultado final na branch [ngrok-final](https://github.com/azukiapp/azkdemo-services/tree/ngrok-final) do projeto [azkdemo-services](https://github.com/azukiapp/azkdemo-services/).