Skip to main content

Identificar las entregas de los webhooks

Aprenda a escribir código para escuchar y responder a las entregas de webhook.

Introducción

Cuando se crea un webhook, se especifica una dirección URL y se suscribe a los tipos de eventos. Cuando se produce un evento al que se suscribe el webhook, GitHub enviará una solicitud HTTP con datos sobre el evento a la dirección URL especificada. Si el servidor está configurado para escuchar las entregas de webhook en esa dirección URL, puede tomar medidas cuando reciba una.

En este artículo se describe cómo escribir código para permitir que el servidor escuche y responda a las entregas de webhook. Probarás el código mediante el equipo o el espacio de código como servidor local.

Configuración

Para probar el webhook localmente, puedes usar una dirección URL del proxy de webhook para reenviar webhooks de GitHub al equipo o codespace. En este artículo se usa smee.io para proporcionar una dirección URL del proxy de webhook y reenviar webhooks.

Obtención de una dirección URL del proxy de webhook

  1. Abra el explorador y vaya a https://smee.io/.
  2. Haz clic en Iniciar un nuevo canal.
  3. Copia la dirección URL completa en "Dirección URL del proxy de webhook". Usarás esta dirección URL en los próximos pasos de configuración.

Reenviar de webhooks

  1. Si aún no tienes instalado smee-client, ejecuta el siguiente comando en el terminal:

    Shell
    npm install --global smee-client
    
  2. Para recibir webhooks reenviados desde smee.io, ejecuta el siguiente comando en el terminal. Reemplaza WEBHOOK_PROXY_URL por la dirección URL del proxy de webhook anterior.

    Shell
    smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000
    

    Deberías ver una salida con el siguiente aspecto, en la que WEBHOOK_PROXY_URL es la dirección URL del proxy del webhook.

    Shell
    Forwarding WEBHOOK_PROXY_URL to http://127.0.0.1:3000/webhook
    Connected WEBHOOK_PROXY_URL
    

    Ten en cuenta que la ruta de acceso es /webhook y el puerto es 3000. Usarás estos valores más adelante al escribir código para gestionar las entregas de webhook.

  3. Deja que se ejecute mientras pruebas el webhook. Cuando quieras detener el reenvío de webhooks, escribe Ctrl+C.

Creación de un webhook

  1. Crea un webhook con la siguiente configuración: Para obtener más información, vea «Crear webhooks».

    • Para la dirección URL, usa la dirección URL del proxy de webhook anterior.
    • Si tienes la opción de elegir el tipo de contenido, usa JSON.

Escritura de código para gestionar las entregas de webhook

Para controlar las entregas de webhook, debes escribir código que haga lo siguiente:

  • Inicializar el servidor para escuchar las solicitudes a la dirección URL del webhook
  • Leer los encabezados HTTP y el cuerpo de la solicitud
  • Realizar la acción deseada en respuesta a la solicitud

Puedes usar cualquier lenguaje de programación que se pueda ejecutar en el servidor.

En los ejemplos siguientes se imprime un mensaje cuando se recibe una entrega de webhook. Sin embargo, puedes modificar el código para realizar otra acción, como realizar una solicitud a la API GitHub o enviar un mensaje de Slack.

Ejemplo de Ruby

En este ejemplo se usa la gema de Rruby, Sinatra, para definir rutas y controlar las solicitudes HTTP. Para más información, consulta el archivo LÉAME de Sinatra.

Ejemplo de Ruby: instalación de dependencias

Para usar este ejemplo, debes instalar la gema Sinatra en el proyecto de Ruby. Por ejemplo, puedes hacerlo con Bundler:

  1. Si aún no tienes instalado Bundler, ejecuta el siguiente comando en el terminal:

    Shell
    gem install bundler
    
  2. Si aún no tienes un archivo Gemfile para la aplicación, ejecuta el siguiente comando en el terminal:

    Shell
    bundle init
    
  3. Si aún no tienes un archivo Gemfile.lock para la aplicación, ejecuta el siguiente comando en el terminal:

    Shell
    bundle install
    
  4. En el terminal, ejecuta el siguiente comando para instalar la gema Sinatra:

    Shell
    bundle add sinatra
    

Ejemplo de Ruby: escritura del código

Crea un archivo de Ruby con el siguiente contenido. Modifica el código para gestionar los tipos de eventos a los que se suscribe el webhook, así como el ping evento al que GitHub envía al crear un webhook. En este ejemplo se gestionan los eventos issues y ping.

Ruby
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 10 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 y 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 10 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

Ejemplo de Ruby: prueba del código

Para probar el webhook, puedes usar el equipo o el espacio de código para actuar como servidor local. Si tienes problemas con estos pasos, consulte la solución de problemas.

  1. Asegúrate de que estás reenviando webhooks. Si ya no vas a reenviar webhooks, sigue los pasos descritos en Reenviar webhooks de nuevo.

  2. En una ventana de terminal independiente, ejecuta el siguiente comando para iniciar un servidor local en el equipo o el espacio de código. Sustituye FILE_PATH por la ruta de acceso al archivo donde se almacena el código de la sección anterior. Ten en cuenta que PORT=3000 coincide con el puerto que especificaste para el reenvío de webhooks en el paso anterior.

    Shell
    PORT=3000 ruby FILE_NAME
    

    Deberías ver un resultado que indica algo parecido a "Sinatra ha tomado la fase en 3000".

  3. Desencadena tu webhook. Por ejemplo, si has creado un webhook de repositorio que está suscrito al evento issues, abre una incidencia en el repositorio. También puedes volver a entregar una entrega reciente de webhook. Para obtener más información, vea «Entregar webhooks».

  4. Vaya a la dirección URL del proxy del webhook en smee.io. Deberías ver un evento que corresponde al evento que desencadenaste o volviste a entregar. Esto indica que GitHub envió correctamente una entrega de webhook a la dirección URL de carga especificada.

  5. En la ventana de terminal en la que ejecutaste smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000, deberías ver algo parecido a POST http://127.0.0.1:3000/webhook - 202. Esto indica que smee reenvió correctamente el webhook al servidor local.

  6. En la ventana de terminal donde ejecutaste PORT=3000 ruby FILE_NAME, deberías ver un mensaje correspondiente al evento que se envió. Por ejemplo, si usas el código de ejemplo anterior y vuelves a entregar el evento ping, deberías ver que "GitHub envió el evento ping". También puedes ver otras líneas que Sinatra imprime automáticamente.

  7. En ambas ventanas de terminal, escribe Ctrl+C para detener el servidor local y dejar de escuchar webhooks reenviados.

Ahora que ha probado el código localmente, puede realizar cambios para usar el webhook en producción. Para más información, consulte la sección “Pasos siguientes”. Si tiene problemas para probar el código, pruebe los pasos descritos en “Solución de problemas”.

Ejemplo de JavaScript

En este ejemplo se usa Node.js y la biblioteca Express para definir rutas y controlar las solicitudes HTTP. Para obtener más información, vea “expressjs.com”.

Para obtener un ejemplo que usa el SDK de Octokit.js de GitHub, vea “Creación de una aplicación de GitHub que responda a eventos de webhook”.

Este ejemplo requiere que el equipo o el codespace ejecuten Node.js versión 12 o posterior y npm versión 6.12.0 o posterior. Para más información, consulta Node.js.

Ejemplo de JavaScript: instalación de dependencias

Para usar este ejemplo, debe instalar la biblioteca express en el proyecto Node.js. Por ejemplo:

Shell
npm install express

Ejemplo de JavaScript: escribe el código

Cree un archivo JavaScript con los siguientes contenidos: Modifica el código para gestionar los tipos de eventos a los que se suscribe el webhook, así como el ping evento al que GitHub envía al crear un webhook. En este ejemplo se gestionan los eventos issues y ping.

JavaScript
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 10 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 y 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 10 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}`);
});

Ejemplo de JavaScript: prueba del código

Para probar el webhook, puedes usar el equipo o el espacio de código para actuar como servidor local. Si tienes problemas con estos pasos, consulte la solución de problemas.

  1. Asegúrate de que estás reenviando webhooks. Si ya no vas a reenviar webhooks, sigue los pasos descritos en Reenviar webhooks de nuevo.

  2. En una ventana de terminal independiente, ejecuta el siguiente comando para iniciar un servidor local en el equipo o el espacio de código. Sustituye FILE_PATH por la ruta de acceso al archivo donde se almacena el código de la sección anterior.

    Shell
    node FILE_NAME
    

    Debería ver la salida que indica Server is running on port 3000.

  3. Desencadena tu webhook. Por ejemplo, si has creado un webhook de repositorio que está suscrito al evento issues, abre una incidencia en el repositorio. También puedes volver a entregar una entrega reciente de webhook. Para obtener más información, vea «Entregar webhooks».

  4. Vaya a la dirección URL del proxy del webhook en smee.io. Deberías ver un evento que corresponde al evento que desencadenaste o volviste a entregar. Esto indica que GitHub envió correctamente una entrega de webhook a la dirección URL de carga especificada.

  5. En la ventana de terminal en la que ejecutaste smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000, deberías ver algo parecido a POST http://127.0.0.1:3000/webhook - 202. Esto indica que smee reenvió correctamente el webhook al servidor local.

  6. En la ventana de terminal donde ejecutaste node FILE_NAME, deberías ver un mensaje correspondiente al evento que se envió. Por ejemplo, si usas el código de ejemplo anterior y vuelves a entregar el evento ping, deberías ver que "GitHub envió el evento ping".

  7. En ambas ventanas de terminal, escribe Ctrl+C para detener el servidor local y dejar de escuchar webhooks reenviados.

Ahora que ha probado el código localmente, puede realizar cambios para usar el webhook en producción. Para más información, consulte la sección “Pasos siguientes”. Si tiene problemas para probar el código, pruebe los pasos descritos en “Solución de problemas”.

Solución de problemas

Si no ves los resultados esperados descritos en los pasos de prueba, prueba lo siguiente:

  • Asegúrate de que el webhook usa la dirección URL del proxy de webhook (URL de Smee.io). Para más información sobre la dirección URL del proxy de webhook, consulta "Obtención de una dirección URL del proxy de webhook". Para obtener más información sobre la configuración de webhooks, consulte “Crear webhooks”.
  • Asegúrese de que su webhook use el tipo de contenido JSON, si existe la opción de elegir qué tipo de contenido utilizar. Para obtener más información sobre la configuración de webhooks, consulta "Crear webhooks".
  • Asegúrate de que tanto el cliente smee como el servidor local se estén ejecutando. Tendrás estos procesos ejecutándose en dos ventanas de terminal independientes.
  • Asegúrese de que el servidor escuche el mismo puerto en el que smee.io está reenviando webhooks. Muchos de los ejemplos de este artículo usan puerto 3000.
  • Asegúrese de que la ruta de acceso en la que smee.io está reenviando webhooks coincida con una ruta definida en el código. Todos los ejemplos de este artículo utilizan la ruta /webhooks.
  • Compruebe si hay mensajes de error en las ventanas de terminal en las que está ejecutando el cliente smee y el servidor local.
  • Compruebe GitHub para verificar si se desencadenó una entrega de webhook. Para obtener más información, vea «Visualizar las entregas de los webhooks».
  • Comprueba la dirección URL del proxy del webhook en smee.io. Deberías ver un evento que corresponde al evento que desencadenaste o volviste a entregar. Esto indica que GitHub envió correctamente una entrega de webhook a la dirección URL de carga especificada.

Pasos siguientes

En este artículo se mostró cómo escribir código para gestionar las entregas de webhook. También se mostró cómo probar el código mediante el uso del equipo o el espacio de código como servidor local y el reenvío de entregas de webhook de GitHub al servidor local a través de smee.io. Una vez que hayas terminado de probar el código, es posible que quieras modificarlo e implementarlo en un servidor.

Modificará el código

En este artículo se proporcionan ejemplos básicos que imprimen un mensaje cuando se recibe una entrega de webhook. Es posible que desees modificar el código para realizar alguna otra acción. Por ejemplo, podrías modificar el código para hacer lo siguiente:

  • Realizar una solicitud a la API de GitHub
  • Enviar un mensaje en Slack
  • Registrar eventos
  • Actualizar una herramienta de administración de proyectos externa

Comprobar que la entrega procede de GitHub

En el código que gestiona las entregas de webhook, debes validar que la entrega procede de GitHub antes de seguir procesando la entrada. Para obtener más información, consulta "Validación de entregas de webhook".

Implementar el código en un servidor

En este artículo se muestra cómo usar el equipo o el espacio de código como servidor mientras desarrollas el código. Una vez que el código esté listo para su uso en producción, debes implementarlo en un servidor dedicado.

Al hacerlo, es posible que tengas que actualizar el código para reflejar el host y el puerto donde escucha el servidor.

Actualización de la dirección URL del webhook

Una vez que tengas un servidor configurado para recibir tráfico de webhook de GitHub, actualiza la dirección URL en la configuración del webhook. Es posible que tenga que actualizar la ruta que controla el código para que coincida con la parte de la ruta de acceso de la nueva dirección URL. Por ejemplo, si la nueva dirección URL de webhook es https://example.com/github-webhooks, debe cambiar la ruta de estos ejemplos de /webhooks a /github-webhooks.

No debes usar smee.io para reenviar los webhooks en producción.

Seguimiento de los procedimientos recomendados

Debes intentar seguir los procedimientos recomendados con los webhooks. Para obtener más información, vea «Procedimientos recomendados para usar webhooks».

Información adicional