Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/disgoorg/disgo/llms.txt

Use this file to discover all available pages before exploring further.

The httpserver package provides an HTTP server for receiving Discord interactions through outgoing webhooks, with built-in request verification and interaction handling.

Installation

import "github.com/disgoorg/disgo/httpserver"

Server

New

Creates a new HTTP server for handling Discord interactions.
func New(
    publicKey string,
    eventHandlerFunc EventHandlerFunc,
    opts ...ConfigOpt
) (Server, error)
publicKey
string
required
Your application’s public key from the Discord Developer Portal (hex-encoded)
eventHandlerFunc
EventHandlerFunc
required
Function to handle incoming interactions
opts
...ConfigOpt
Optional configuration options

Server interface

type Server interface {
    // Start starts the HTTP server
    Start()

    // Close closes the HTTP server
    Close(ctx context.Context)
}

Event handling

EventHandlerFunc

Function signature for handling interaction events.
type EventHandlerFunc func(responseFunc RespondFunc, event EventInteractionCreate)
responseFunc
RespondFunc
required
Function to call to respond to the interaction
event
EventInteractionCreate
required
The interaction event data

RespondFunc

Function signature for responding to interactions.
type RespondFunc func(response discord.InteractionResponse) error
response
discord.InteractionResponse
required
The interaction response to send

EventInteractionCreate

Represents an incoming interaction event.
type EventInteractionCreate struct {
    discord.Interaction
}
Interaction
discord.Interaction
The underlying Discord interaction (can be any interaction type)

Request verification

VerifyRequest

Verifies that a request is from Discord using Ed25519 signature verification.
func VerifyRequest(verifier Verifier, r *http.Request, key PublicKey) bool
verifier
Verifier
required
The verifier implementation to use
r
*http.Request
required
The HTTP request to verify
key
PublicKey
required
Your application’s public key (decoded from hex)
Returns true if the request signature is valid, false otherwise.

Verifier interface

type Verifier interface {
    // Verify verifies the signature of the message using the public key
    Verify(publicKey PublicKey, message []byte, sig []byte) bool

    // SignatureSize is the size, in bytes, of signatures
    SignatureSize() int
}

DefaultVerifier

The default Ed25519 signature verifier.
type DefaultVerifier struct{}

func (DefaultVerifier) Verify(publicKey PublicKey, message []byte, sig []byte) bool

func (DefaultVerifier) SignatureSize() int

PublicKey

Type alias for Ed25519 public keys.
type PublicKey = []byte

Handler function

HandleInteraction

Creates an http.HandlerFunc for handling Discord interactions.
func HandleInteraction(
    verifier Verifier,
    publicKey PublicKey,
    logger *slog.Logger,
    handleFunc EventHandlerFunc
) http.HandlerFunc
verifier
Verifier
required
The signature verifier
publicKey
PublicKey
required
Your application’s public key
logger
*slog.Logger
required
Logger for request/response logging
handleFunc
EventHandlerFunc
required
Function to handle verified interactions
This function automatically:
  • Verifies the request signature
  • Parses the interaction payload
  • Handles interaction timeouts (3 seconds)
  • Sends the response back to Discord

Configuration

WithLogger

Sets a custom logger.
func WithLogger(logger *slog.Logger) ConfigOpt

WithHTTPServer

Sets a custom http.Server instance.
func WithHTTPServer(httpServer *http.Server) ConfigOpt

WithServeMux

Sets a custom http.ServeMux.
func WithServeMux(serveMux *http.ServeMux) ConfigOpt

WithURL

Sets the URL path for the interaction endpoint.
func WithURL(url string) ConfigOpt
url
string
required
The endpoint path (default: “/interactions/callback”)

WithAddress

Sets the server address.
func WithAddress(address string) ConfigOpt
address
string
required
The address to listen on (default: “:80”)

WithTLS

Enables TLS with certificate and key files.
func WithTLS(certFile string, keyFile string) ConfigOpt
certFile
string
required
Path to the TLS certificate file
keyFile
string
required
Path to the TLS key file

WithVerifier

Sets a custom signature verifier.
func WithVerifier(verifier Verifier) ConfigOpt

Example usage

Basic server

package main

import (
    "context"
    "log"
    "log/slog"
    "os"
    "os/signal"
    "syscall"

    "github.com/disgoorg/disgo/discord"
    "github.com/disgoorg/disgo/httpserver"
)

func main() {
    publicKey := os.Getenv("PUBLIC_KEY")

    server, err := httpserver.New(publicKey, handleInteraction,
        httpserver.WithAddress(":8080"),
        httpserver.WithURL("/interactions"),
        httpserver.WithLogger(slog.Default()),
    )
    if err != nil {
        log.Fatal("failed to create server: ", err)
    }

    server.Start()
    log.Println("Server started on :8080")

    s := make(chan os.Signal, 1)
    signal.Notify(s, syscall.SIGINT, syscall.SIGTERM)
    <-s

    server.Close(context.TODO())
}

func handleInteraction(respond httpserver.RespondFunc, event httpserver.EventInteractionCreate) {
    switch data := event.Data.(type) {
    case discord.SlashCommandInteractionData:
        err := respond(discord.InteractionResponse{
            Type: discord.InteractionResponseTypeCreateMessage,
            Data: discord.MessageCreate{
                Content: "Hello from DisGo HTTP server!",
            },
        })
        if err != nil {
            log.Println("failed to respond:", err)
        }
    }
}

With TLS

server, err := httpserver.New(publicKey, handleInteraction,
    httpserver.WithAddress(":443"),
    httpserver.WithTLS("cert.pem", "key.pem"),
)
if err != nil {
    log.Fatal(err)
}

server.Start()

Handling different interaction types

func handleInteraction(respond httpserver.RespondFunc, event httpserver.EventInteractionCreate) {
    switch data := event.Data.(type) {
    case discord.SlashCommandInteractionData:
        handleSlashCommand(respond, event, data)

    case discord.ComponentInteractionData:
        handleComponent(respond, event, data)

    case discord.ModalSubmitInteractionData:
        handleModalSubmit(respond, event, data)
    }
}

func handleSlashCommand(
    respond httpserver.RespondFunc,
    event httpserver.EventInteractionCreate,
    data discord.SlashCommandInteractionData,
) {
    err := respond(discord.InteractionResponse{
        Type: discord.InteractionResponseTypeCreateMessage,
        Data: discord.MessageCreate{
            Content: "Command received: " + data.CommandName(),
        },
    })
    if err != nil {
        log.Println("failed to respond:", err)
    }
}

func handleComponent(
    respond httpserver.RespondFunc,
    event httpserver.EventInteractionCreate,
    data discord.ComponentInteractionData,
) {
    err := respond(discord.InteractionResponse{
        Type: discord.InteractionResponseTypeUpdateMessage,
        Data: discord.MessageUpdate{
            Content: discord.NewNullablePtr("Button clicked!"),
        },
    })
    if err != nil {
        log.Println("failed to respond:", err)
    }
}

func handleModalSubmit(
    respond httpserver.RespondFunc,
    event httpserver.EventInteractionCreate,
    data discord.ModalSubmitInteractionData,
) {
    err := respond(discord.InteractionResponse{
        Type: discord.InteractionResponseTypeCreateMessage,
        Data: discord.MessageCreate{
            Content: "Modal submitted!",
            Flags:   discord.MessageFlagEphemeral,
        },
    })
    if err != nil {
        log.Println("failed to respond:", err)
    }
}

Deferred responses

func handleInteraction(respond httpserver.RespondFunc, event httpserver.EventInteractionCreate) {
    // Acknowledge the interaction immediately
    err := respond(discord.InteractionResponse{
        Type: discord.InteractionResponseTypeDeferredCreateMessage,
    })
    if err != nil {
        log.Println("failed to defer:", err)
        return
    }

    // Process the command in the background
    go func() {
        // Do some long-running work...
        time.Sleep(5 * time.Second)

        // Follow up with the actual response using the REST API
        // You'll need to use the rest client to edit the original response
    }()
}

Security notes

  • Always verify requests using the provided verification mechanism
  • Keep your public key secure and never commit it to version control
  • Use environment variables or secure configuration management for sensitive data
  • The server automatically rejects requests with invalid signatures
  • Interactions must be responded to within 3 seconds or they will timeout