Files
scriptforge/DESIGN.md
zhilv 10a200b96c
Some checks failed
Release / build-and-release (push) Failing after 1m31s
初始提交: ScriptForge 脚本快速转运行链接服务
- Go 后端 (Gin + GORM + SQLite) 提供 API 和纯文本脚本服务
- Vite + React + TypeScript + Tailwind 前端
- 单二进制部署 (Go embed 前端静态文件)
- Gitea Actions CI/CD: 打标签自动构建多平台 Release
- 支持 bash/zsh/sh/fish/python3/node/ruby/php 8种运行环境

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 23:48:19 +08:00

6.6 KiB
Raw Blame History

ScriptForge 设计文档

概述

脚本快速转运行链接服务。用户粘贴脚本内容,选择运行环境,生成一个短链。在终端执行 curl URL | <runtime> 即可运行脚本。

  • 前端Next.js (App Router + Tailwind CSS + TypeScript)
  • 后端Go (Gin + GORM + SQLite)
  • 部署Go embed 前端静态文件,单二进制部署
  • CI/CDGitea Actions

核心流程

  1. 用户打开首页 /
  2. 粘贴脚本内容(上限 16KB
  3. 选择运行环境bash / zsh / sh / fish / python3 / node / ruby / php
  4. 选择过期时间1小时 / 24小时 / 7天 / 30天
  5. 提交 → 后端存入 SQLite → 返回短链 ID
  6. 页面展示生成的命令:curl https://example.com/raw/xK8mPq | bash
  7. 用户可以复制命令到终端执行

API 设计

POST /api/scripts — 创建脚本

请求体:

{
  "content": "#!/bin/bash\necho hello",
  "runtime": "bash",
  "expires_in": "24h"
}

响应:

{
  "id": "xK8mPq",
  "admin_token": "dGhpcyBpcyBhIHRva2Vu",
  "url": "https://example.com/raw/xK8mPq",
  "command": "curl https://example.com/raw/xK8mPq | bash",
  "runtime": "bash",
  "expires_at": "2026-05-29T16:27:00Z"
}

GET /api/scripts/:id — 获取脚本元数据

响应:

{
  "id": "xK8mPq",
  "runtime": "bash",
  "content_length": 25,
  "created_at": "2026-05-28T16:27:00Z",
  "expires_at": "2026-05-29T16:27:00Z",
  "expired": false
}

注意:此接口不返回脚本原始内容(内容通过 /raw/:id 获取),避免前端二次暴露。

GET /raw/:id — 获取脚本纯文本内容

  • 响应头 Content-Type: 根据 runtime 设置对应 MIME见运行时配置表
  • 响应头 Content-Disposition: attachment; filename="script.<ext>"(根据 runtime 设置扩展名)
  • 响应体:脚本纯文本内容
  • 如脚本已过期,返回 404

DELETE /api/scripts/:id?token=xxx — 删除脚本

  • 需要 admin_token 参数
  • 成功返回 204

数据模型

type Script struct {
    ID          string    `gorm:"primaryKey;size:8"`
    Content     string    `gorm:"type:text;not null"`
    Runtime     string    `gorm:"size:16;not null;index"`
    AdminToken  string    `gorm:"size:64;not null"`
    ExpiresAt   time.Time `gorm:"not null;index"`
    CreatedAt   time.Time `gorm:"not null"`
}

运行时配置

Runtime 扩展名 MIME 类型 命令模板
bash .sh text/x-shellscript curl {url} | bash
zsh .zsh text/x-shellscript curl {url} | zsh
sh .sh text/x-shellscript curl {url} | sh
fish .fish text/x-shellscript curl {url} | fish
python3 .py text/x-python curl {url} | python3
node .js text/javascript curl {url} | node
ruby .rb text/x-ruby curl {url} | ruby
php .php text/x-php curl {url} | php

运行环境列表在 Go 后端定义为常量数组,用于校验请求中的 runtime 字段。

过期策略

  • 用户保存时选择1小时 / 24小时 / 7天 / 30天
  • 后端定时任务(每分钟扫描一次),删除过期记录
  • 过期后 /raw/:id 返回 404详情页标记为已过期

限流策略

  • 创建接口10 次/分钟/IP
  • 其他接口60 次/分钟/IP
  • 请求体上限17KB

安全设计

  • 完全公开,无需注册/登录
  • 创建时返回 admin_token(随机 64 位字符串),持有者可删除脚本
  • 无内容过滤,靠过期机制和限流控制风险
  • 编辑功能:无(admin_token 仅用于删除,不能改内容。设计上 script 是一次性的,编辑会带来版本管理等复杂问题)

前端路由

路由 页面 说明
/ 首页 粘贴脚本 + 选择运行环境/过期时间 + 提交 + 结果展示
/s/[id] 脚本详情页 展示脚本内容语法高亮、元数据、curl 命令卡片
/s/[id]/delete 删除确认页 输入 admin_token 确认删除

项目目录结构

scriptforge/
├── frontend/                  # Next.js 项目
│   ├── src/
│   │   ├── app/
│   │   │   ├── page.tsx           # 首页
│   │   │   ├── layout.tsx         # 根布局
│   │   │   └── s/[id]/
│   │   │       ├── page.tsx       # 脚本详情页
│   │   │       └── delete/
│   │   │           └── page.tsx   # 删除确认页
│   │   ├── components/
│   │   │   ├── ScriptForm.tsx     # 脚本提交表单
│   │   │   ├── ResultCard.tsx     # 结果展示卡(含复制按钮)
│   │   │   ├── ScriptViewer.tsx   # 脚本内容展示(语法高亮)
│   │   │   └── CommandCard.tsx    # curl 命令展示卡
│   │   └── lib/
│   │       └── api.ts            # API 调用封装
│   ├── package.json
│   └── next.config.js
├── backend/                   # Go 项目
│   ├── cmd/
│   │   └── server/
│   │       └── main.go            # 入口
│   ├── internal/
│   │   ├── handler/
│   │   │   ├── script.go          # 脚本 CRUD handlers
│   │   │   └── raw.go             # 原始内容 handler
│   │   ├── model/
│   │   │   └── script.go          # GORM model
│   │   ├── service/
│   │   │   └── script.go          # 业务逻辑
│   │   ├── middleware/
│   │   │   └── ratelimit.go       # 限流中间件
│   │   └── config/
│   │       └── runtime.go         # 运行时配置列表
│   ├── go.mod
│   └── go.sum
├── .gitea/
│   └── workflows/
│       └── deploy.yml             # Gitea Actions 部署流程
├── Makefile                    # 统一构建命令
├── DESIGN.md                   # 本设计文档
└── README.md

CI/CD 部署流程Gitea Actions

  1. 触发条件push 到 main 分支
  2. 构建步骤:
    • cd frontend && npm ci && npm run build → 输出 out/
    • cd backend && cp -r ../frontend/out ./internal/embed && go build -o server ./cmd/server
  3. 部署步骤:
    • scp 二进制到服务器
    • ssh 执行 systemctl restart scriptforge

后续可扩展方向

  • 大模型集成:根据脚本内容自动推荐运行环境
  • 更多运行时dockerfile、powershell、deno、bun 等
  • 脚本版本管理(不基于 admin_token需要真正的用户系统
  • 统计数据:脚本执行次数、来源 IP 等(需要跟踪 curl 请求)
  • WebSocket 实时执行输出流