Skip to content

Building a Slack Webhook Mock Server with Golang: The Ultimate Debugging Tool for Offline Development ​

Schematic diagram of building a Slack Webhook Mock server using Golang

In a development environment without internet access, how can I efficiently debug a Slack Webhook integration?

Preface ​

In daily development, we often need to integrate with third-party services. Take Slack Webhook as an example: when your business system needs to send notifications to Slack, you usually need a real Slack Webhook URL for testing. However, in the following scenarios, this traditional approach will encounter challenges:

  • offline development environment: Unable to access the external network, unable to use the real Slack service

  • Frequent debugging: Every time, real Slack notifications need to be sent, which disturbs team members.

  • Lack of visualization: Unable to intuitively view the structure of the sent Payload

This article will introduce how to build a lightweight Slack Webhook Mock server, allowing you to efficiently debug Webhook integrations even in an offline environment.

Technology selection ​

This project uses the following technology stack:

TechnologyPurpose
GolangA high-performance, compiled language, suitable for building microservices.
GinLightweight web framework, simple and efficient
slack-go-webhookSlack Webhook data structure definition

Project structure:

slack-webhook-server/
├── go.mod
├── main.go
└── README.md

Core implementation ​

1. Data structure definition ​

First, we define a unified API response structure:

go
// Response defines the unified API response format
type Response struct {
    Message string `json:"message"`        // Response message, e.g. "OK"
    Code    int    `json:"code"`           // Business status code, e.g. 100100 for success
    Data    any    `json:"data,omitempty"` // Response data, returned only when needed
}

const (
    CodeWithSuccess = 100100
    CodeWithFailed  = 100101
)

2. Mock server core code ​

go
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "time"

    "github.com/fishfinal/slack-go-webhook"
    "github.com/gin-gonic/gin"
)

func main() {
    engine := gin.Default()

    // Mock endpoint for receiving and displaying Slack webhook payloads
    engine.POST("/webhook/mock/receiver", func(ctx *gin.Context) {
        var payload *slack.Payload
        err := ctx.ShouldBindJSON(&payload)
        if err != nil {
            ctx.JSON(http.StatusBadRequest, Response{
                Message: "Invalid request parameters",
                Code:    CodeWithFailed,
            })
            return
        }

        marshal, err := json.MarshalIndent(payload, "", "  ")
        if err != nil {
            ctx.JSON(http.StatusInternalServerError, Response{
                Message: "Failed to marshal data",
                Code:    CodeWithFailed,
            })
            return
        }

        // Pretty-print the received payload for debugging purposes
        fmt.Printf("\n--- Received Webhook at %s ---\n%s\n",
            time.Now().Format(time.RFC3339),
            string(marshal),
        )

        // Return success response to simulate Slack's behavior
        ctx.JSON(http.StatusOK, Response{
            Message: "OK",
            Code:    CodeWithSuccess,
        })
    })

    fmt.Println("Mock Slack Webhook Server is running on :2769")
    if err := engine.Run(":2769"); err != nil {
        panic(err)
    }
}

3. Code Explanation ​

componentFunction Description
gin.Default()Create a Gin engine and automatically load the Logger and Recovery middleware.
ShouldBindJSON()Parse and bind JSON request to slack.Payload struct
MarshalIndent()Format the output for easier reading and debugging.
Printf()Print received logs with timestamps to the console.

Deploy as a Systemd service ​

To ensure stable operation in production, we deploy it as a Systemd service.

1. Create a service file ​

ini
# /etc/systemd/system/slack-webhook-server.service
[Unit]
Description=Slack Webhook Server - Mock Slack webhook receiver for bot message testing
Documentation=https://github.com/fishfinal/slack-go-webhook
Requires=network-online.target
After=network-online.target

[Service]
Type=simple
WorkingDirectory=/var/lib/slack-webhook-server
User=slack-webhook
Group=slack-webhook
ExecStart=/usr/bin/slack-webhook-server
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
KillSignal=SIGTERM
Restart=on-failure
RestartSec=10s
LimitNOFILE=65536
LimitNPROC=4096

# Logging configuration
StandardOutput=append:/var/log/slack-webhook-server/access.log
StandardError=append:/var/log/slack-webhook-server/error.log

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/slack-webhook-server /var/log/slack-webhook-server

[Install]
WantedBy=multi-user.target

2. Deployment command ​

bash
# Create user and directory
sudo useradd -r -s /bin/false slack-webhook
sudo mkdir -p /var/lib/slack-webhook-server
sudo mkdir -p /var/log/slack-webhook-server
sudo chown -R slack-webhook:slack-webhook /var/lib/slack-webhook-server
sudo chown -R slack-webhook:slack-webhook /var/log/slack-webhook-server

# Install binary files
sudo cp slack-webhook-server /usr/bin/
sudo chmod +x /usr/bin/slack-webhook-server

# Installation service
sudo cp slack-webhook-server.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable slack-webhook-server
sudo systemctl start slack-webhook-server

3. Service Management ​

bash
# 查看状态
sudo systemctl status slack-webhook-server

# View logs
sudo journalctl -u slack-webhook-server -f

# Restart the service
sudo systemctl restart slack-webhook-server

Test verification ​

Send a test request using curl ​

bash
# Send a simple message
curl -X POST http://localhost:2769/webhook/mock/receiver \
  -H "Content-Type: application/json" \
  -d '{"text":"Hello from curl!"}'

# Send the complete Payload
curl -X POST http://localhost:2769/webhook/mock/receiver \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hello from curl!",
    "username": "CurlBot",
    "channel": "#general",
    "attachments": [
      {
        "title": "Deployment Status",
        "text": "Application deployed successfully!",
        "color": "#36a64f",
        "fields": [
          {"title": "Environment", "value": "Production", "short": true},
          {"title": "Version", "value": "v2.1.0", "short": true}
        ]
      }
    ]
  }'

Expected output ​

Server console output:

--- Received Webhook at 2026-06-25T14:30:25+08:00 ---
{
  "username": "CurlBot",
  "channel": "#general",
  "text": "Hello from curl!",
  "attachments": [
    {
      "title": "Deployment Status",
      "text": "Application deployed successfully!",
      "color": "#36a64f",
      "fields": [
        {"title": "Environment", "value": "Production", "short": true},
        {"title": "Version", "value": "v2.1.0", "short": true}
      ]
    }
  ]
}

Client response:

json
{
  "message": "OK",
  "code": 100100
}

Use Cases and Value ​

SceneSolution
offline developmentThe mock server runs entirely locally and does not require access to the external network.
Debug PayloadFormatted console output to intuitively view the request structure
Rapid iterationVerify immediately after modifying business logic, no need for real Slack
Team collaborationUnify the Mock service address to facilitate collaborative debugging among multiple people.
Safety isolationAvoid sending test messages to the real Slack and disrupting team members.

Summary ​

This article introduces how to use Golang and Gin to build a concise and efficient Slack Webhook Mock server. This tool solves the debugging pain points in offline development environments and has the following features:

  • lightweight: Single binary file with low memory usage

  • Easy to deploy: Supports Systemd services and can start automatically at boot

  • Observability: Print requests in real time on the console, and persist logs

  • Safety: Run as a non-root user, following the principle of least privilege

Further reading ​

I hope this blog post helps you debug Slack Webhook integrations more efficiently in an offline development environment.

Last updated on11/07/2026, 02:16 PM
@fishfinal | @fishfinals | [email protected]