Configuración de webhooks de GitHub con ngrok

Clase 4 de 30Curso de Ciberseguridad para Desarrollo Web

Resumen

Aprende a crear una API REST en Go con Gorilla Mux, gestionar dependencias con go mod y recibir webhooks de GitHub en local usando ngrok. El enfoque es práctico y transversal: más allá del lenguaje, se refuerzan conceptos como router, handler, lectura de request body y la práctica de fallar rápido ante errors.

¿Cómo preparar el entorno en Go y gestionar dependencias?

Configura el proyecto en una carpeta llamada GitHubTracker y habilita el manejo de dependencias con go mod. Se usa go get para traer Gorilla Mux. Para tener dependencias locales, se crea la carpeta vendor y se sincroniza con go mod vendor. También se verifica el estado con go mod tidy y se revisan los archivos go.mod y go.sum.

  • Crea el módulo con go mod init y define el nombre del proyecto.
  • Instala Gorilla Mux con go get y revisa go.mod actualizado.
  • Usa vendor para dependencias locales y evitar fallos de resolución.
  • Sincroniza y limpia referencias con go mod tidy.
# dentro de GitHubTracker
go mod init GitHubTracker

# dependencia del *router*
go get github.com/gorilla/mux

# dependencias locales
go mod vendor

# sincronizar referencias
go mod tidy

¿Cómo crear un endpoint con Gorilla Mux y procesar requests?

Se implementa un router con Gorilla Mux, se define el endpoint POST en "/hello" y un handler que lee el body como bytes con io.ReadAll. Se imprime un mensaje de llegada y, si hay error, se falla rápido: se reporta y se interrumpe la ejecución del método.

¿Qué código mínimo se implementa?

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"

    "github.com/gorilla/mux"
)

func postHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Received post request")
    defer r.Body.Close()

    body, err := io.ReadAll(r.Body)
    if err != nil {
        fmt.Println("Error reading the request")
        log.Println(err)
        return
    }

    fmt.Println(string(body))
}

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/hello", postHandler).Methods("POST")

    fmt.Println("ServerListening on port 8080")
    if err := http.ListenAndServe(":8080", r); err != nil {
        log.Println(err)
    }
}
  • Router con mux.NewRouter y handler con HandleFunc.
  • Endpoint POST: "/hello".
  • Lectura del body con io.ReadAll y conversión a string.
  • Mensajes de diagnóstico: "Received post request" y "Error reading the request".

¿Cómo configurar ngrok y webhooks de GitHub para pruebas locales?

Se expone el servicio local en el puerto 8080 con ngrok para obtener una URL pública temporal. Luego, en el repositorio de GitHub, se crea un webhook que apunte a esa URL más la ruta "/hello". Se elige Content type JSON, sin secret por ahora, con verificación SSL habilitada, y se activa el evento de push. Para dispararlo, se hace commit y push del código. Se recomienda añadir un .gitignore para excluir la carpeta vendor y archivos como .DS_Store.

¿Qué comandos y archivos usar?

# ejecutar el servidor local
go run main.go

# en otra terminal, exponer el puerto 8080
ngrok http 8080
/vendor/
.DS_Store

¿Qué configurar en GitHub Webhooks?

  • Ruta del payload: URL pública de ngrok + "/hello".
  • Content type: application/json.
  • Sin secret por el momento.
  • SSL verification: enabled.
  • Evento: push.
  • Si tienes two factor authentication, completa la verificación.

Al hacer push, en GitHub se ven las "Recent deliveries": primero un "ping" de creación y luego el push. El payload es amplio, pero el apartado head_commit concentra lo útil para el seguimiento:

  • id del commit.
  • timestamp del commit.
  • autor: nombre y email.
  • archivos cambiados.
  • mensaje del commit.

¿Te gustaría que añadamos validación de firma con secret o persistencia del payload en base de datos en la siguiente parte? Deja tus dudas y comenta qué te gustaría automatizar con estos webhooks.