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.
Configurar
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
- Abra el explorador y vaya a https://smee.io/.
- Haz clic en Iniciar un nuevo canal.
- 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
-
Si aún no tienes instalado smee-client, ejecuta el siguiente comando en el terminal:
Shell npm install --global smee-client
npm install --global smee-client
-
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
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
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 es3000
. Usarás estos valores más adelante al escribir código para gestionar las entregas de webhook. -
Deja que se ejecute mientras pruebas el webhook. Cuando quieras detener el reenvío de webhooks, escribe Ctrl+C.
Creación de un webhook
-
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:
-
Si aún no tienes instalado Bundler, ejecuta el siguiente comando en el terminal:
Shell gem install bundler
gem install bundler
-
Si aún no tienes un archivo Gemfile para la aplicación, ejecuta el siguiente comando en el terminal:
Shell bundle init
bundle init
-
Si aún no tienes un archivo Gemfile.lock para la aplicación, ejecuta el siguiente comando en el terminal:
Shell bundle install
bundle install
-
En el terminal, ejecuta el siguiente comando para instalar la gema Sinatra:
Shell bundle add sinatra
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
.
# 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 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 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
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.
-
Asegúrate de que estás reenviando webhooks. Si ya no vas a reenviar webhooks, sigue los pasos descritos en Reenviar webhooks de nuevo.
-
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 quePORT=3000
coincide con el puerto que especificaste para el reenvío de webhooks en el paso anterior.Shell PORT=3000 ruby FILE_NAME
PORT=3000 ruby FILE_NAME
Deberías ver un resultado que indica algo parecido a "Sinatra ha tomado la fase en 3000".
-
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». -
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.
-
En la ventana de terminal en la que ejecutaste
smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000
, deberías ver algo parecido aPOST http://127.0.0.1:3000/webhook - 202
. Esto indica que smee reenvió correctamente el webhook al servidor local. -
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 eventoping
, deberías ver que "GitHub envió el evento ping". También puedes ver otras líneas que Sinatra imprime automáticamente. -
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:
npm install express
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
.
// 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 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 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}`);
});
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.
-
Asegúrate de que estás reenviando webhooks. Si ya no vas a reenviar webhooks, sigue los pasos descritos en Reenviar webhooks de nuevo.
-
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
node FILE_NAME
Debería ver la salida que indica
Server is running on port 3000
. -
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». -
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.
-
En la ventana de terminal en la que ejecutaste
smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000
, deberías ver algo parecido aPOST http://127.0.0.1:3000/webhook - 202
. Esto indica que smee reenvió correctamente el webhook al servidor local. -
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 eventoping
, deberías ver que "GitHub envió el evento ping". -
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».