Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Slack Webhook

Go Version License Go Report Card codecov

A lightweight, high-performance Slack webhook client for Go with connection pooling, context support, and comprehensive configuration options.

Note: This library is a complete rewrite and extension of ashwanthkumar/slack-go-webhook. It maintains the same core API for backward compatibility while adding significant performance improvements, new features, and better Go practices. Special thanks to @ashwanthkumar for the original implementation.

Features

  • 🚀 High Performance - Connection pooling with configurable idle connections
  • ⏱️ Context Support - Full context support for cancellation and timeouts
  • 🔧 Flexible Configuration - Functional options pattern for easy customization
  • 🌐 Proxy Support - HTTP/HTTPS proxy support
  • 📦 Batch Sending - Send multiple messages efficiently
  • 🧪 Tested - Comprehensive test suite with testify
  • 📝 Type Safe - Strongly typed Slack message structures
  • 🔒 Keep-Alive - HTTP keep-alive for connection reuse
  • 🎯 100% Compatible - Fully compatible with the original library's API

Credits & Acknowledgments

This project is built upon the work of:

Key Improvements Over the Original

Feature Original This Library
HTTP Client gorequest Native net/http
Connection Pooling
Context Support
Proxy Support
Batch Sending
Configurable Timeouts Limited Full
Connection Keep-Alive
Functional Options
Test Coverage Limited Comprehensive
Go Modules

Installation

go get github.com/fishfinal/slack-webhook

Quick Start

package main

import (
    "log"
    "github.com/fishfinal/slack-webhook"
)

func main() {
    // Create a new webhook client
    // Note: API is fully compatible with ashwanthkumar/slack-go-webhook
    webhook := slack.NewWebhook("https://hooks.slack.com/services/XXX/YYY/ZZZ")

    // Send a simple message
    payload := slack.Payload{
        Text:     "Hello from Slack Webhook!",
        Username: "MyBot",
        Channel:  "#general",
    }

    if err := webhook.Send(payload); err != nil {
        log.Fatalf("Failed to send message: %v", err)
    }
}

Migration from ashwanthkumar/slack-go-webhook

Migrating from the original library is straightforward as the core API remains compatible:

// Original library
import "github.com/ashwanthkumar/slack-go-webhook"

// New library - just change the import path
import "github.com/fishfinal/slack-webhook"

// Everything else remains the same!
webhook := slack.NewWebhook(url)
payload := slack.Payload{...}
err := webhook.Send(payload)

Advanced Usage

Configuration Options

// Create with custom configuration
webhook := slack.NewWebhook(
    "https://hooks.slack.com/services/XXX/YYY/ZZZ",
    slack.WithTimeout(15*time.Second),
    slack.WithProxy("http://proxy.example.com:8080"),
    slack.WithConnectionPool(200, 20, 120*time.Second),
    slack.WithMaxIdleConns(100),
    slack.WithMaxIdleConnsPerHost(10),
    slack.WithIdleConnTimeout(90*time.Second),
)

Sending Messages with Attachments

payload := slack.Payload{
    Text:     "Check out this message!",
    Username: "NotificationBot",
    Channel:  "#alerts",
    Attachments: []slack.Attachment{
        {
            Title:  stringPtr("Deployment Status"),
            Text:   stringPtr("Deployment completed successfully!"),
            Color:  stringPtr("#36a64f"), // Green
            Fields: []*slack.Field{
                {Title: "Environment", Value: "Production", Short: true},
                {Title: "Version", Value: "v2.1.0", Short: true},
                {Title: "Deployed By", Value: "@devops", Short: false},
            },
            Footer:     stringPtr("Deployment System"),
            FooterIcon: stringPtr("https://example.com/icon.png"),
            Timestamp:  int64Ptr(time.Now().Unix()),
        },
    },
}

err := webhook.Send(payload)

Sending Messages with Actions (Interactive Buttons)

payload := slack.Payload{
    Text:     "What would you like to do?",
    Channel:  "#general",
    Attachments: []slack.Attachment{
        {
            Text:  stringPtr("Choose an action:"),
            Color: stringPtr("#3AA3E3"),
            Actions: []slack.Action{
                {
                    Type:  "button",
                    Text:  "Approve",
                    Url:   "https://example.com/approve",
                    Style: "primary",
                },
                {
                    Type:  "button",
                    Text:  "Reject",
                    Url:   "https://example.com/reject",
                    Style: "danger",
                },
            },
        },
    },
}

err := webhook.Send(payload)

Batch Sending

payloads := []slack.Payload{
    {Text: "Message 1", Channel: "#general"},
    {Text: "Message 2", Channel: "#general"},
    {Text: "Message 3", Channel: "#general"},
}

errors := webhook.SendBatch(payloads)
for _, err := range errors {
    log.Printf("Batch error: %v", err)
}

Context Support

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

// Send with context
if err := webhook.SendWithContext(ctx, payload); err != nil {
    log.Printf("Send failed: %v", err)
}

// Get raw HTTP response with context
resp, err := webhook.SendReceiveResponse(ctx, payload)
if err != nil {
    log.Printf("Request failed: %v", err)
}
defer resp.Body.Close()

// Inspect response
if resp.StatusCode == http.StatusTooManyRequests {
    log.Println("Rate limited!")
}

API Reference

Types

Webhook

The main client structure.

type Webhook struct {
    // Contains unexported fields
}

Payload

The message structure sent to Slack.

type Payload struct {
    Parse       string       `json:"parse,omitempty"`
    Username    string       `json:"username,omitempty"`
    IconUrl     string       `json:"icon_url,omitempty"`
    IconEmoji   string       `json:"icon_emoji,omitempty"`
    Channel     string       `json:"channel,omitempty"`
    Text        string       `json:"text,omitempty"`
    LinkNames   string       `json:"link_names,omitempty"`
    Attachments []Attachment `json:"attachments,omitempty"`
    UnfurlLinks bool         `json:"unfurl_links,omitempty"`
    UnfurlMedia bool         `json:"unfurl_media,omitempty"`
    Markdown    bool         `json:"mrkdwn,omitempty"`
}

Attachment

Rich message attachments.

type Attachment struct {
    Fallback     *string   `json:"fallback"`
    Color        *string   `json:"color"`
    PreText      *string   `json:"pretext"`
    AuthorName   *string   `json:"author_name"`
    AuthorLink   *string   `json:"author_link"`
    AuthorIcon   *string   `json:"author_icon"`
    Title        *string   `json:"title"`
    TitleLink    *string   `json:"title_link"`
    Text         *string   `json:"text"`
    ImageUrl     *string   `json:"image_url"`
    Fields       []*Field  `json:"fields"`
    Footer       *string   `json:"footer"`
    FooterIcon   *string   `json:"footer_icon"`
    Timestamp    *int64    `json:"ts"`
    MarkdownIn   *[]string `json:"mrkdwn_in"`
    Actions      []*Action `json:"actions"`
    CallbackID   *string   `json:"callback_id"`
    ThumbnailUrl *string   `json:"thumb_url"`
}

Functions

NewWebhook

func NewWebhook(webhookUrl string, options ...Option) *Webhook

Creates a new Slack webhook client with optional configuration.

Webhook Methods

Send

func (w *Webhook) Send(payload Payload) error

Sends a message to Slack. Returns error on failure.

SendWithContext

func (w *Webhook) SendWithContext(ctx context.Context, payload Payload) error

Sends a message with context support for cancellation and timeouts.

SendReceiveResponse

func (w *Webhook) SendReceiveResponse(ctx context.Context, payload Payload) (*http.Response, error)

Sends a message and returns the raw HTTP response.

SendBatch

func (w *Webhook) SendBatch(payloads []Payload) []error

Sends multiple messages efficiently using connection pooling.

Attachment Helpers

func (attachment *Attachment) AddField(field Field) *Attachment
func (attachment *Attachment) AddAction(action Action) *Attachment

Configuration Options

Option Description Default
WithTimeout(duration) HTTP client timeout 10s
WithProxy(url) HTTP/HTTPS proxy URL None
WithConnectionPool(maxIdle, maxPerHost, timeout) Connection pool config 100, 10, 90s
WithMaxIdleConns(n) Max idle connections 100
WithMaxIdleConnsPerHost(n) Max idle connections per host 10
WithIdleConnTimeout(duration) Idle connection timeout 90s

Error Handling

The package provides detailed error messages:

err := webhook.Send(payload)
if err != nil {
    // Check error type
    if strings.Contains(err.Error(), "context canceled") {
        // Handle cancellation
    } else if strings.Contains(err.Error(), "Status: 429") {
        // Rate limited
    }
    log.Printf("Error: %v", err)
}

Best Practices

1. Reuse Webhook Client

Create a single webhook client and reuse it across your application:

var globalWebhook = slack.NewWebhook(
    os.Getenv("SLACK_WEBHOOK_URL"),
    slack.WithTimeout(10*time.Second),
    slack.WithConnectionPool(100, 10, 90*time.Second),
)

2. Use Context for Timeouts

Always use context for production requests:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

if err := webhook.SendWithContext(ctx, payload); err != nil {
    // Handle error
}

3. Batch Sending

For multiple messages, use SendBatch to leverage connection pooling:

// Instead of:
for _, p := range payloads {
    webhook.Send(p)
}

// Do:
errors := webhook.SendBatch(payloads)

Testing

# Run tests
go test -v

# Run with coverage
go test -cover

# Run benchmarks
go test -bench=.

# Run specific test
go test -run TestWebhookSuite

Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please make sure to update tests as appropriate and adhere to the existing coding style.

License

This project is licensed under the Apache License, Version 2.0 - see the LICENSE file for details.

Credits

  • Original Library: ashwanthkumar/slack-go-webhook by @ashwanthkumar
  • Inspiration: The original library provided the foundation and API design
  • Rewrite & Extensions: Performance improvements, connection pooling, context support, and additional features

About

A lightweight, high-performance Slack webhook client for Go with connection pooling, context support, and comprehensive configuration options.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages