Introdução
Ao criar um webhook, você especifica um URL e assina tipos de eventos. Quando ocorrer um evento no qual seu webhook está inscrito, o GitHub enviará uma solicitação HTTP com dados sobre o evento para o URL que você especificou. Se o seu servidor estiver configurado para ouvir entregas de webhooks nesse URL, ele poderá agir quando receber um.
Este artigo descreve como escrever código para permitir que seu servidor ouça e responda a entregas de webhooks. Você testará seu código usando seu computador ou codespace como um servidor local.
Instalação
Para testar seu webhook localmente, você pode usar um URL proxy de webhook para encaminhar webhooks do GitHub para seu computador ou codespace. Este artigo usa o smee.io para fornecer um URL de proxy de webhook e encaminhar webhooks.
Obter a URL de proxy de webhook
- No navegador, navegue até https://smee.io/.
- Clique em Iniciar um novo canal.
- Copie a URL completa em "URL de Proxy de Webhook". Você usará esse URL nas etapas de configuração a seguir.
Encaminhar webhooks
-
Se você ainda não tiver o smee-client instalado, execute o seguinte comando no seu terminal:
Shell npm install --global smee-client
npm install --global smee-client
-
Para receber webhooks encaminhados de smee.io, execute o seguinte comando em seu terminal. Substitua
WEBHOOK_PROXY_URL
pela URL de proxy de webhook anterior.Shell smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000
smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000
Você deverá ver uma saída semelhante a esta, em que
WEBHOOK_PROXY_URL
é a URL de proxy de webhook:Shell Forwarding WEBHOOK_PROXY_URL to http://127.0.0.1:3000/webhook Connected WEBHOOK_PROXY_URL
Forwarding WEBHOOK_PROXY_URL to http://127.0.0.1:3000/webhook Connected WEBHOOK_PROXY_URL
Observe que o caminho é
/webhook
e a porta é3000
. Você usará esses valores posteriormente quando escrever o código para lidar com entregas de webhooks. -
Mantenha isso em execução enquanto você testa seu webhook. Quando quiser interromper o encaminhamento de webhooks, pressione Ctrl+C .
Criar um webhook
-
Crie um webhook com as seguintes configurações. Para saber mais, confira Criar webhooks.
- Para o URL, use o URL do proxy do webhook que você usou anteriormente.
- Se tiver a opção de escolher o tipo de conteúdo, use JSON.
Escrever código para lidar com entregas de webhooks
Para lidar com entregas de webhooks, você precisa escrever um código que faça o seguinte:
- Inicialize seu servidor para escutar as solicitações ao URL do webhook
- Leia os cabeçalhos e o corpo HTTP da solicitação
- Realize a ação desejada em resposta à solicitação
Você pode usar qualquer linguagem de programação que possa ser executada no seu servidor.
Os exemplos a seguir imprimem uma mensagem quando uma entrega de webhook é recebida. No entanto, você pode modificar o código para executar outra ação, como fazer uma solicitação à API do GitHub ou enviar uma mensagem do Slack.
Exemplo do Ruby
Este exemplo usa uma gem do Ruby, o Sinatra, para definir rotas e lidar com solicitações HTTP. Para obter mais informações, confira o LEIAME do Sinatra.
Exemplo com Ruby: Instalar dependências
Para usar este exemplo, você deve instalar a gem Sinatra no seu projeto Ruby. Por exemplo, faça isso com o Bundler:
-
Caso ainda não tenha o Bundler instalado, execute o seguinte comando no terminal:
Shell gem install bundler
gem install bundler
-
Caso ainda não tenha um Gemfile para seu aplicativo, execute o seguinte comando no terminal:
Shell bundle init
bundle init
-
Caso ainda não tenha um Gemfile.lock para seu aplicativo, execute o seguinte comando no terminal:
Shell bundle install
bundle install
-
Instale a gem Sinatra executando o seguinte comando em seu terminal:
Shell bundle add sinatra
bundle add sinatra
Exemplo com Ruby: Escrever o código
Crie um arquivo Ruby com o seguinte conteúdo. Modifique o código para lidar com os tipos de eventos nos quais seu webhook está inscrito, bem como o evento ping
que o GitHub envia quando você cria um webhook. Este exemplo lida com os eventos issues
e ping
.
# These are the dependencies for this code. You installed the `sinatra` gem earlier. For more information, see "[Ruby example: Install dependencies](#ruby-example-install-dependencies)." The `json` library is a standard Ruby library, so you don't need to install it. require 'sinatra' require 'json' # The `/webhook` route matches the path that you specified for the smee.io forwarding. For more information, see "[Forward webhooks](#forward-webhooks)." # # Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook. post '/webhook' do # Respond to indicate that the delivery was successfully received. # Your server should respond with a 2XX response within 30 seconds of receiving a webhook delivery. If your server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure. status 202 # Check the `X-GitHub-Event` header to learn what event type was sent. # Sinatra changes `X-GitHub-Event` to `HTTP_X_GITHUB_EVENT`. github_event = request.env['HTTP_X_GITHUB_EVENT'] # You should add logic to handle each event type that your webhook is subscribed to. # For example, this code handles the `issues` and `ping` events. # # If any events have an `action` field, you should also add logic to handle each action that you are interested in. # For example, this code handles the `opened` and `closed` actions for the `issue` event. # # For more information about the data that you can expect for each event type, see "[AUTOTITLE](/webhooks/webhook-events-and-payloads)." if github_event == "issues" data = JSON.parse(request.body.read) action = data['action'] if action == "opened" puts "An issue was opened with this title: #{data['issue']['title']}" elsif action == "closed" puts "An issue was closed by #{data['issue']['user']['login']}" else puts "Unhandled action for the issue event: #{action}" end elsif github_event == "ping" puts "GitHub sent the ping event" else puts "Unhandled event: #{github_event}" end end
require 'sinatra'
require 'json'
These are the dependencies for this code. You installed the sinatra
gem earlier. For more information, see "Ruby example: Install dependencies." The json
library is a standard Ruby library, so you don't need to install it.
post '/webhook' do
The /webhook
route matches the path that you specified for the smee.io forwarding. For more information, see "Forward webhooks."
Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook.
status 202
Respond to indicate that the delivery was successfully received. Your server should respond with a 2XX response within 30 seconds of receiving a webhook delivery. If your server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure.
github_event = request.env['HTTP_X_GITHUB_EVENT']
Check the X-GitHub-Event
header to learn what event type was sent.
Sinatra changes X-GitHub-Event
to HTTP_X_GITHUB_EVENT
.
if github_event == "issues"
data = JSON.parse(request.body.read)
action = data['action']
if action == "opened"
puts "An issue was opened with this title: #{data['issue']['title']}"
elsif action == "closed"
puts "An issue was closed by #{data['issue']['user']['login']}"
else
puts "Unhandled action for the issue event: #{action}"
end
elsif github_event == "ping"
puts "GitHub sent the ping event"
else
puts "Unhandled event: #{github_event}"
end
end
You should add logic to handle each event type that your webhook is subscribed to.
For example, this code handles the issues
and ping
events.
If any events have an action
field, you should also add logic to handle each action that you are interested in.
For example, this code handles the opened
and closed
actions for the issue
event.
For more information about the data that you can expect for each event type, see "Eventos e cargas de webhook."
# These are the dependencies for this code. You installed the `sinatra` gem earlier. For more information, see "[Ruby example: Install dependencies](#ruby-example-install-dependencies)." The `json` library is a standard Ruby library, so you don't need to install it.
require 'sinatra'
require 'json'
# The `/webhook` route matches the path that you specified for the smee.io forwarding. For more information, see "[Forward webhooks](#forward-webhooks)."
#
# Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook.
post '/webhook' do
# Respond to indicate that the delivery was successfully received.
# Your server should respond with a 2XX response within 30 seconds of receiving a webhook delivery. If your server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure.
status 202
# Check the `X-GitHub-Event` header to learn what event type was sent.
# Sinatra changes `X-GitHub-Event` to `HTTP_X_GITHUB_EVENT`.
github_event = request.env['HTTP_X_GITHUB_EVENT']
# You should add logic to handle each event type that your webhook is subscribed to.
# For example, this code handles the `issues` and `ping` events.
#
# If any events have an `action` field, you should also add logic to handle each action that you are interested in.
# For example, this code handles the `opened` and `closed` actions for the `issue` event.
#
# For more information about the data that you can expect for each event type, see "[AUTOTITLE](/webhooks/webhook-events-and-payloads)."
if github_event == "issues"
data = JSON.parse(request.body.read)
action = data['action']
if action == "opened"
puts "An issue was opened with this title: #{data['issue']['title']}"
elsif action == "closed"
puts "An issue was closed by #{data['issue']['user']['login']}"
else
puts "Unhandled action for the issue event: #{action}"
end
elsif github_event == "ping"
puts "GitHub sent the ping event"
else
puts "Unhandled event: #{github_event}"
end
end
Exemplo com Ruby: Testar o código
Para testar seu webhook, você pode usar seu computador ou codespace para atuar como um servidor local. Se tiver problemas com essas etapas, consulte Solução de problemas.
-
Certifique-se de que esteja encaminhando webhooks. Se não estiver mais encaminhando webhooks, siga as etapas em Encaminhar webhooks novamente.
-
Em uma janela de terminal separada, execute o seguinte comando para iniciar um servidor local em seu computador ou codespace. Substitua
FILE_PATH
pelo caminho para o arquivo em que o código da seção anterior está armazenado. Observe quePORT=3000
corresponde à porta que você especificou para o encaminhamento do webhook na etapa anterior.Shell PORT=3000 ruby FILE_NAME
PORT=3000 ruby FILE_NAME
Você deverá ver um resultado que indica algo como "Sinatra has taken the stage on 3000".
-
Acione seu webhook. Por exemplo, se você criou um webhook de repositório que está inscrito no evento
issues
, abra um problema em seu repositório. Você também pode reenviar uma entrega anterior de webhook. Para saber mais, confira Entregar webhooks novamente. -
Navegue até a URL de proxy de webhook no smee.io. Você deverá ver um evento que corresponde ao evento que acionou ou reenviou. Isso indica que o GitHub enviou com êxito uma entrega de webhook ao URL do conteúdo que você especificou.
-
Na janela do terminal em que
smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000
foi executado, você deverá ver algo comoPOST http://127.0.0.1:3000/webhook - 202
. Isso indica que o smee encaminhou com êxito seu webhook ao servidor local. -
Na janela do terminal em que
PORT=3000 ruby FILE_NAME
foi executado, você deverá ver uma mensagem correspondente ao evento que foi enviado. Por exemplo, se você usar o código de exemplo acima e reenviar o eventoping
, deverá ver "GitHub enviou o evento de ping". Você também pode ver algumas outras linhas que o Sinatra imprime automaticamente. -
Em ambas as janelas de terminal, pressione Ctrl+C para interromper o servidor local e parar de escutar os webhooks encaminhados.
Agora que o código já foi testado localmente, você pode fazer alterações para usar o webhook em produção. Para saber mais, confira as Próximas etapas. Se teve problemas para testar o código, tente as etapas em Solução de problemas.
Exemplo de JavaScript
Este exemplo usa o Node.js e a biblioteca Express para definir rotas e lidar com solicitações HTTP. Para obter mais informações, confira: expressjs.com.
Para obter um exemplo que utiliza o SDK Octokit.js do GitHub, confira Criar um Aplicativo GitHub que responde a eventos de webhook.
Este exemplo exige que seu computador ou codespace execute o Node.js versão 12 ou superior e o npm versão 6.12.0 ou superior. Para obter mais informações, confira Node.js.
Exemplo com JavaScript: instalar dependências
Para usar este exemplo, você deve instalar a biblioteca express
em seu projeto Node.js. Por exemplo:
npm install express
npm install express
Exemplo de JavaScript: escrever o código
Crie um arquivo JavaScript com os conteúdos a seguir: Modifique o código para lidar com os tipos de eventos nos quais seu webhook está inscrito, bem como o evento ping
que o GitHub envia quando você cria um webhook. Este exemplo lida com os eventos issues
e ping
.
// You installed the `express` library earlier. For more information, see "[JavaScript example: Install dependencies](#javascript-example-install-dependencies)." const express = require('express'); // This initializes a new Express application. const app = express(); // This defines a POST route at the `/webhook` path. This path matches the path that you specified for the smee.io forwarding. For more information, see "[Forward webhooks](#forward-webhooks)." // // Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook. app.post('/webhook', express.json({type: 'application/json'}), (request, response) => { // Respond to indicate that the delivery was successfully received. // Your server should respond with a 2XX response within 30 seconds of receiving a webhook delivery. If your server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure. response.status(202).send('Accepted'); // Check the `x-github-event` header to learn what event type was sent. const githubEvent = request.headers['x-github-event']; // You should add logic to handle each event type that your webhook is subscribed to. // For example, this code handles the `issues` and `ping` events. // // If any events have an `action` field, you should also add logic to handle each action that you are interested in. // For example, this code handles the `opened` and `closed` actions for the `issue` event. // // For more information about the data that you can expect for each event type, see "[AUTOTITLE](/webhooks/webhook-events-and-payloads)." if (githubEvent === 'issues') { const data = request.body; const action = data.action; if (action === 'opened') { console.log(`An issue was opened with this title: ${data.issue.title}`); } else if (action === 'closed') { console.log(`An issue was closed by ${data.issue.user.login}`); } else { console.log(`Unhandled action for the issue event: ${action}`); } } else if (githubEvent === 'ping') { console.log('GitHub sent the ping event'); } else { console.log(`Unhandled event: ${githubEvent}`); } }); // This defines the port where your server should listen. // 3000 matches the port that you specified for webhook forwarding. For more information, see "[Forward webhooks](#forward-webhooks)." // // Once you deploy your code to a server, you should change this to match the port where your server is listening. const port = 3000; // This starts the server and tells it to listen at the specified port. app.listen(port, () => { console.log(`Server is running on port ${port}`); });
const express = require('express');
You installed the express
library earlier. For more information, see "JavaScript example: Install dependencies."
const app = express();
This initializes a new Express application.
app.post('/webhook', express.json({type: 'application/json'}), (request, response) => {
This defines a POST route at the /webhook
path. This path matches the path that you specified for the smee.io forwarding. For more information, see "Forward webhooks."
Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook.
response.status(202).send('Accepted');
Respond to indicate that the delivery was successfully received. Your server should respond with a 2XX response within 30 seconds of receiving a webhook delivery. If your server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure.
const githubEvent = request.headers['x-github-event'];
Check the x-github-event
header to learn what event type was sent.
if (githubEvent === 'issues') {
const data = request.body;
const action = data.action;
if (action === 'opened') {
console.log(`An issue was opened with this title: ${data.issue.title}`);
} else if (action === 'closed') {
console.log(`An issue was closed by ${data.issue.user.login}`);
} else {
console.log(`Unhandled action for the issue event: ${action}`);
}
} else if (githubEvent === 'ping') {
console.log('GitHub sent the ping event');
} else {
console.log(`Unhandled event: ${githubEvent}`);
}
});
You should add logic to handle each event type that your webhook is subscribed to.
For example, this code handles the issues
and ping
events.
If any events have an action
field, you should also add logic to handle each action that you are interested in.
For example, this code handles the opened
and closed
actions for the issue
event.
For more information about the data that you can expect for each event type, see "Eventos e cargas de webhook."
const port = 3000;
This defines the port where your server should listen. 3000 matches the port that you specified for webhook forwarding. For more information, see "Forward webhooks."
Once you deploy your code to a server, you should change this to match the port where your server is listening.
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
This starts the server and tells it to listen at the specified port.
// You installed the `express` library earlier. For more information, see "[JavaScript example: Install dependencies](#javascript-example-install-dependencies)."
const express = require('express');
// This initializes a new Express application.
const app = express();
// This defines a POST route at the `/webhook` path. This path matches the path that you specified for the smee.io forwarding. For more information, see "[Forward webhooks](#forward-webhooks)."
//
// Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook.
app.post('/webhook', express.json({type: 'application/json'}), (request, response) => {
// Respond to indicate that the delivery was successfully received.
// Your server should respond with a 2XX response within 30 seconds of receiving a webhook delivery. If your server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure.
response.status(202).send('Accepted');
// Check the `x-github-event` header to learn what event type was sent.
const githubEvent = request.headers['x-github-event'];
// You should add logic to handle each event type that your webhook is subscribed to.
// For example, this code handles the `issues` and `ping` events.
//
// If any events have an `action` field, you should also add logic to handle each action that you are interested in.
// For example, this code handles the `opened` and `closed` actions for the `issue` event.
//
// For more information about the data that you can expect for each event type, see "[AUTOTITLE](/webhooks/webhook-events-and-payloads)."
if (githubEvent === 'issues') {
const data = request.body;
const action = data.action;
if (action === 'opened') {
console.log(`An issue was opened with this title: ${data.issue.title}`);
} else if (action === 'closed') {
console.log(`An issue was closed by ${data.issue.user.login}`);
} else {
console.log(`Unhandled action for the issue event: ${action}`);
}
} else if (githubEvent === 'ping') {
console.log('GitHub sent the ping event');
} else {
console.log(`Unhandled event: ${githubEvent}`);
}
});
// This defines the port where your server should listen.
// 3000 matches the port that you specified for webhook forwarding. For more information, see "[Forward webhooks](#forward-webhooks)."
//
// Once you deploy your code to a server, you should change this to match the port where your server is listening.
const port = 3000;
// This starts the server and tells it to listen at the specified port.
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Exemplo de JavaScript: testar o código
Para testar seu webhook, você pode usar seu computador ou codespace para atuar como um servidor local. Se tiver problemas com essas etapas, consulte Solução de problemas.
-
Certifique-se de que esteja encaminhando webhooks. Se não estiver mais encaminhando webhooks, siga as etapas em Encaminhar webhooks novamente.
-
Em uma janela de terminal separada, execute o seguinte comando para iniciar um servidor local em seu computador ou codespace. Substitua
FILE_PATH
pelo caminho para o arquivo em que o código da seção anterior está armazenado.Shell node FILE_NAME
node FILE_NAME
Você deve ver a saída que diz
Server is running on port 3000
. -
Acione seu webhook. Por exemplo, se você criou um webhook de repositório que está inscrito no evento
issues
, abra um problema em seu repositório. Você também pode reenviar uma entrega anterior de webhook. Para saber mais, confira Entregar webhooks novamente. -
Navegue até a URL de proxy de webhook no smee.io. Você deverá ver um evento que corresponde ao evento que acionou ou reenviou. Isso indica que o GitHub enviou com êxito uma entrega de webhook ao URL do conteúdo que você especificou.
-
Na janela do terminal em que
smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000
foi executado, você deverá ver algo comoPOST http://127.0.0.1:3000/webhook - 202
. Isso indica que o smee encaminhou com êxito seu webhook ao servidor local. -
Na janela do terminal em que
node FILE_NAME
foi executado, você deverá ver uma mensagem correspondente ao evento que foi enviado. Por exemplo, se você usar o código de exemplo acima e reenviar o eventoping
, deverá ver "GitHub enviou o evento de ping". -
Em ambas as janelas de terminal, pressione Ctrl+C para interromper o servidor local e parar de escutar os webhooks encaminhados.
Agora que o código já foi testado localmente, você pode fazer alterações para usar o webhook em produção. Para saber mais, confira as Próximas etapas. Se teve problemas para testar o código, tente as etapas em Solução de problemas.
Solução de problemas
Se não obtiver os resultados esperados descritos nas etapas de teste, tente o seguinte:
- Certifique-se de que o webhook esteja usando o URL do proxy do webhook (URL do Smee.io). Para obter mais informações sobre o URL do proxy do webhook, confira Obter um URL do proxy do webhook. Para obter mais informações sobre suas configurações de webhook, confira Criar webhooks.
- Se puder escolher qual tipo de conteúdo usar, certifique-se de que seu webhook use o tipo de conteúdo JSON. Para obter mais informações sobre suas configurações de webhook, confira Criar webhooks.
- Certifique-se de que o cliente smee e o servidor local estejam em execução. Você terá esses processos em execução em duas janelas de terminal separadas.
- Certifique-se de que o servidor esteja escutando a mesma porta para a qual o smee.io está encaminhando webhooks. Muitos dos exemplos neste artigo usam a porta 3000.
- Certifique-se de que o caminho para o qual smee.io esteja encaminhando webhooks corresponda a uma rota definida em seu código. Os exemplos neste artigo usam o caminho
/webhooks
. - Verifique se há mensagens erros nas janelas de terminal em que você está executando o cliente smee e o servidor local.
- Verifique o GitHub para verificar se uma entrega de webhook foi acionada. Para saber mais, confira Visualizar entregas do webhook.
- Verifique o URL do proxy do webhook em smee.io. Você deverá ver um evento que corresponde ao evento que acionou ou reenviou. Isso indica que o GitHub enviou com êxito uma entrega de webhook ao URL do conteúdo que você especificou.
Próximas etapas
Este artigo demonstrou como escrever código para lidar com entregas de webhooks. Ele também demonstrou como testar seu código usando seu computador ou codespace como um servidor local e encaminhar entregas de webhooks do GitHub para seu servidor local via smee.io. Quando terminar de testar seu código, talvez você queira modificá-lo e implantá-lo em um servidor.
Modificar o código
Este artigo apresentou exemplos básicos que imprimem uma mensagem quando uma entrega de webhook é recebida. Talvez você queira modificar o código para executar outra ação. Por exemplo, você pode modificar o código para:
- Fazer uma solicitação à API do GitHub
- Enviar uma mensagem no Slack
- Eventos de log
- Atualizar uma ferramenta externa de gerenciamento de projetos
Verificar se a entrega é proveniente de GitHub
No seu código que lida com entregas de webhook, você deve validar que a entrega é proveniente do GitHub antes de processá-la. Para saber mais, confira Validação de entregas de webhooks.
Implantar seu código em um servidor
Este artigo demonstrou como usar seu computador ou codespace como um servidor enquanto você desenvolve seu código. Quando o código estiver pronto para uso em produção, você deverá implantá-lo em um servidor dedicado.
Ao fazer isso, talvez seja necessário atualizar seu código para refletir o host e a porta em que o servidor está escutando.
Atualizar a URL do webhook
Quando você tiver um servidor configurado para receber tráfego de webhook do GitHub, atualize o URL nas configurações do webhook. Talvez seja necessário atualizar a rota que seu código usa para que ela corresponda à parte do caminho da nova URL. Por exemplo, se a nova URL do webhook for https://example.com/github-webhooks
, você deverá alterar a rota nesses exemplos de /webhooks
para /github-webhooks
.
Você não deve usar o smee.io para encaminhar seus webhooks na produção.
Seguir as práticas recomendadas
Você deve procurar seguir as práticas recomendadas com seus webhooks. Para saber mais, confira Melhores práticas para usar webhooks.