Thunder

Thunder is a fast and lightweight web framework built on top of Gin, designed to accelerate Go web application development. It provides out-of-the-box solutions for common requirements like authentication, cloud storage, database access, payment integration, and more.
Features
- π₯ Gin-based: Built on top of the popular Gin web framework for high performance
- βοΈ Cloud Storage: Support for multiple cloud storage services (Qiniu Cloud, Alibaba Cloud OSS)
- ποΈ Database Access: GORM integration with PostgreSQL and MySQL support
- βοΈ Configuration Management: Viper-based configuration system with hot reloading
- π Logging: Structured logging with customizable output formats
- π Authentication & Authorization: JWT-based authentication middleware
- π° Payment Integration: WeChat Pay integration for native, JSAPI, and H5 payments
- π Event System: Built-in event management system
- π‘οΈ Security: CORS middleware, request validation
- π€ File Upload: Easy integration with cloud storage services
- π Subscription Management: Built-in subscription system with plan support (free, basic, pro, enterprise)
Installation
go get github.com/mszlu521/thunder
Quick Start
package main
import (
"github.com/mszlu521/thunder/config"
"github.com/mszlu521/thunder/server"
)
func main() {
// Initialize configuration
conf := config.Init()
config := config.GetConfig()
// Create server instance
s := server.NewServer(config)
// Start server
s.Start()
}
Configuration
Thunder uses YAML configuration files. Create a config.yml file in your etc directory:
server:
mode: "release"
host: "127.0.0.1"
port: 8080
readTimeout: "5s"
writeTimeout: "5s"
log:
level: "info"
format: "json"
addSource: false
jwt:
secret: "your-jwt-secret"
expire: "24h"
db:
postgres:
host: "localhost"
port: 5432
user: "postgres"
password: "password"
database: "mydb"
sslmode: "disable"
maxIdleConns: 10
maxOpenConns: 100
pingTimeout: "5s"
redis:
addr: "localhost:6379"
password: ""
db: 0
poolSize: 100
maxIdleConns: 10
maxOpenConns: 1000
auth:
isAuth: true
ignores:
- "/api/v1/public/**"
- "/health"
needLogins:
- "/api/v1/user/**"
upload:
prefix: "/uploads"
qiniu:
bucket: "your-qiniu-bucket"
accessKey: "your-qiniu-access-key"
secretKey: "your-qiniu-secret-key"
region: "z0"
aliyun:
accessKeyId: "your-aliyun-access-key-id"
accessKeySecret: "your-aliyun-access-key-secret"
endpoint: "oss-cn-hangzhou.aliyuncs.com"
bucket: "your-oss-bucket"
pay:
wxPay:
appId: "your-wechat-app-id"
mchId: "your-merchant-id"
mchSerialNo: "your-merchant-serial-no"
apiV3Key: "your-api-v3-key"
privateKey: "your-private-key"
appSecret: "your-app-secret"
notifyUrl: "https://yourdomain.com/pay/notify"
Custom Configuration
Thunder supports user-defined configuration fields beyond the built-in ones. You can add any custom fields to config.yml and access them directly without modifying the framework code.
config.yml:
# Built-in configurations
server:
port: 8080
# Custom configurations
myapp:
timeout: 30
endpoint: "https://api.example.com"
enabled: true
tags:
- "tag1"
- "tag2"
Access custom configuration values:
import "github.com/mszlu521/thunder/config"
// Direct value access (supports dot-separated keys)
timeout := config.GetInt("myapp.timeout") // 30
endpoint := config.GetString("myapp.endpoint") // "https://api.example.com"
enabled := config.GetBool("myapp.enabled") // true
tags := config.GetStringSlice("myapp.tags") // ["tag1", "tag2"]
// Check if a key exists
if config.IsSet("myapp.timeout") {
// Key exists
}
// Get map configuration
settings := config.GetStringMap("myapp")
// settings = map[string]any{"timeout": 30, "endpoint": "...", ...}
Unmarshal to struct:
type MyAppConfig struct {
Timeout int `mapstructure:"timeout"`
Endpoint string `mapstructure:"endpoint"`
Enabled bool `mapstructure:"enabled"`
Tags []string `mapstructure:"tags"`
}
var myCfg MyAppConfig
err := config.UnmarshalKey("myapp", &myCfg)
if err != nil {
// Handle error
}
// myCfg.Timeout = 30, myCfg.Endpoint = "https://api.example.com", ...
Available custom configuration APIs:
| Method |
Description |
config.GetString(key) |
Get string value |
config.GetInt(key) |
Get integer value |
config.GetBool(key) |
Get boolean value |
config.GetFloat64(key) |
Get float64 value |
config.GetStringSlice(key) |
Get string slice |
config.GetStringMap(key) |
Get map[string]any |
config.GetStringMapString(key) |
Get map[string]string |
config.GetDuration(key) |
Get time.Duration |
config.IsSet(key) |
Check if key exists |
config.UnmarshalKey(key, &val) |
Unmarshal specific key to struct |
config.Unmarshal(&val) |
Unmarshal entire config to struct |
config.GetViper() |
Get the raw viper instance for advanced usage |
Cloud Storage
Qiniu Cloud
import "github.com/mszlu521/thunder/upload"
// Initialize Qiniu upload manager
qiniuManager, err := upload.InitQiniuUpload("region-id", "bucket", "access-key", "secret-key")
if err != nil {
// Handle error
}
// Upload file
err = qiniuManager.Upload(context.Background(), "bucket-name", fileReader, "path/to/file")
if err != nil {
// Handle error
}
// Get public URL
url := qiniuManager.GetPublicURL("your-domain.com", "path/to/file")
Alibaba Cloud OSS
import "github.com/mszlu521/thunder/upload"
// Initialize Alibaba Cloud OSS upload manager
ossManager, err := upload.InitAliyunOSSUpload("access-key-id", "access-key-secret", "endpoint", "bucket-name")
if err != nil {
// Handle error
}
// Check if service is available
if ossManager.IsAvailable() {
// Upload file
err := ossManager.Upload(context.Background(), fileReader, "path/to/file")
if err != nil {
// Handle error
}
}
// Get object URL
url := ossManager.GetObjectURL("endpoint", "bucket-name", "path/to/file")
// Generate signed URL (valid for 3600 seconds)
signedURL, err := ossManager.GetSignedURL("path/to/file", 3600)
Authentication
Thunder provides JWT-based authentication middleware:
import "github.com/mszlu521/thunder/tools/jwt"
// Generate token
token, err := jwt.GenToken("user-id", "username", 24*time.Hour)
if err != nil {
// Handle error
}
// Parse token
claims, err := jwt.ParseToken(tokenString)
if err != nil {
// Handle error
}
Configure authentication in your config.yml:
auth:
isAuth: true
ignores:
- "/api/v1/auth/**" # Public authentication endpoints
- "/health" # Health check endpoint
needLogins:
- "/api/v1/user/**" # User-specific endpoints
Payment Integration
Thunder integrates with WeChat Pay for various payment scenarios:
import "github.com/mszlu521/thunder/pay/wxPay"
// Native payment
payBody := &wxPay.PayBody{
Description: "Product Description",
OutTradeNo: "order-number",
TimeExpire: "2025-12-31T10:00:00+08:00",
Amount: 100, // Amount in cents
ClientIp: "127.0.0.1",
}
codeUrl, err := wxPay.Native(context.Background(), payBody)
if err != nil {
// Handle error
}
// JSAPI payment
jsapiParams, err := wxPay.JsApi(context.Background(), payBody)
if err != nil {
// Handle error
}
// H5 payment
h5Url, err := wxPay.H5Pay(context.Background(), payBody)
if err != nil {
// Handle error
}
Event System
Thunder includes a simple event system for decoupling components:
import "github.com/mszlu521/thunder/event"
// Register event handler
event.Register("user.registered", func(e event.Event) (any, error) {
// Handle user registration event
userData := e.Data.(map[string]interface{})
// Process user data
return "success", nil
})
// Trigger event
result, err := event.Trigger("user.registered", map[string]interface{}{
"userId": 123,
"email": "user@example.com",
})
Database Access
Thunder uses GORM for database operations with PostgreSQL and MySQL support:
import (
"github.com/mszlu521/thunder/database"
"github.com/mszlu521/thunder/config"
)
// Initialize PostgreSQL
pgConfig := config.GetConfig().DB.Postgres
database.InitPostgres(pgConfig)
// Get database instance
db := database.GetPostgresDB().GormDB
// Perform database operations
var users []User
db.Find(&users)
Contributing
We welcome contributions to Thunder! Please follow these steps:
- Fork the repository
- Create a new branch (
git checkout -b feature/your-feature)
- Make your changes
- Commit your changes (
git commit -am 'Add some feature')
- Push to the branch (
git push origin feature/your-feature)
- Create a new Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgements
- Gin - HTTP web framework
- GORM - ORM library for Go
- Viper - Configuration solution
- Go-Redis - Redis client for Go
- Go-Pay - Payment library