Files
Wormhole/internal/api/openapi.go
T
rose_cat707 612d68f56f feat: Wormhole 内网穿透与反向代理网关
Go + Vue 管理台,SQLite 持久化;支持隧道/域名穿透、域名转发插件链、访客认证、
IP 规则、API Key、Docker 单镜像部署;配置通过 Web 系统设置管理,无需 YAML 文件。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 12:15:02 +08:00

452 lines
19 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package api
// OpenAPI 3.0 spec for Wormhole external API (authenticate with X-API-Key header).
const openAPISpec = `{
"openapi": "3.0.3",
"info": {
"title": "Wormhole API",
"version": "1.0.0",
"description": "使用 X-API-Key 请求头或 Bearer JWT 访问。Base URL: http://host:8529/api。域名转发接口需管理员权限。"
},
"servers": [{ "url": "/api" }],
"components": {
"securitySchemes": {
"ApiKeyAuth": { "type": "apiKey", "in": "header", "name": "X-API-Key" },
"BearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
},
"schemas": {
"Error": {
"type": "object",
"properties": {
"error": { "type": "string", "description": "错误信息" }
}
},
"Ok": {
"type": "object",
"properties": {
"ok": { "type": "boolean", "example": true }
}
},
"PagedDomainForwards": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": { "$ref": "#/components/schemas/DomainForward" }
},
"total": { "type": "integer", "description": "总条数" }
}
},
"DomainForward": {
"type": "object",
"description": "域名转发规则(服务端直连,无需 Agent)",
"properties": {
"id": { "type": "integer", "readOnly": true },
"source_host": { "type": "string", "description": "源域名,支持通配如 *.example.com", "example": "old.example.com" },
"source_location": { "type": "string", "default": "/", "description": "路径前缀", "example": "/" },
"source_scheme": { "type": "string", "enum": ["all", "http", "https"], "default": "all" },
"mode": { "type": "string", "enum": ["redirect", "proxy"], "description": "redirect=跳转,proxy=反向代理" },
"target_url": { "type": "string", "format": "uri", "description": "目标 URL,需含协议与主机", "example": "https://new.example.com" },
"redirect_mode": { "type": "string", "enum": ["preserve", "fixed"], "default": "preserve", "description": "跳转模式:保留路径或固定地址" },
"redirect_code": { "type": "integer", "enum": [301, 302], "default": 302 },
"proxy_type": {
"type": "string",
"enum": ["http", "http_proxy", "socks5"],
"default": "http",
"description": "http=直连,http_proxy=经 HTTP 代理出站,socks5=经 SOCKS5 出站"
},
"http_proxy_addr": { "type": "string", "description": "HTTP 代理地址,proxy_type=http_proxy 时必填", "example": "127.0.0.1:8080" },
"http_proxy_user": { "type": "string", "description": "HTTP 代理用户名(可选)" },
"socks5_addr": { "type": "string", "description": "SOCKS5 地址,proxy_type=socks5 时必填", "example": "127.0.0.1:1080" },
"socks5_user": { "type": "string", "description": "SOCKS5 用户名(可选)" },
"preserve_host": { "type": "boolean", "default": false, "description": "反代时是否将源域名作为 Host 发给上游" },
"plugins": {
"type": "array",
"description": "反代插件链,按数组顺序执行;redirect 模式忽略",
"items": { "$ref": "#/components/schemas/ForwardPluginEntry" }
},
"status": { "type": "boolean", "default": true },
"created_at": { "type": "string", "format": "date-time", "readOnly": true },
"updated_at": { "type": "string", "format": "date-time", "readOnly": true }
},
"required": ["source_host", "mode", "target_url"]
},
"DomainForwardInput": {
"allOf": [
{ "$ref": "#/components/schemas/DomainForward" },
{
"type": "object",
"properties": {
"http_proxy_pass": { "type": "string", "writeOnly": true, "description": "HTTP 代理密码;更新时留空表示不修改" },
"socks5_pass": { "type": "string", "writeOnly": true, "description": "SOCKS5 密码;更新时留空表示不修改" }
}
}
]
},
"ForwardPluginEntry": {
"type": "object",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"enum": ["sub_filter", "inject_js", "cookie_domain", "response_cache"],
"description": "插件类型"
},
"enabled": { "type": "boolean", "default": true },
"config": {
"description": "插件配置,结构随 type 变化",
"oneOf": [
{ "$ref": "#/components/schemas/SubFilterPluginConfig" },
{ "$ref": "#/components/schemas/InjectJSPluginConfig" },
{ "$ref": "#/components/schemas/CookieDomainPluginConfig" },
{ "$ref": "#/components/schemas/ResponseCachePluginConfig" }
]
}
}
},
"SubFilterPluginConfig": {
"type": "object",
"description": "type=sub_filter:按 MIME 对响应体做字符串替换",
"properties": {
"filters": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["from"],
"properties": {
"from": { "type": "string" },
"to": { "type": "string" }
}
}
},
"types": {
"type": "array",
"items": { "type": "string" },
"default": ["text/html"],
"example": ["text/html", "text/css"]
}
},
"required": ["filters"]
},
"InjectJSPluginConfig": {
"type": "object",
"description": "type=inject_js:在 HTML </body> 前注入脚本",
"properties": {
"script": { "type": "string", "example": "<script></script>" }
},
"required": ["script"]
},
"CookieDomainPluginConfig": {
"type": "object",
"description": "type=cookie_domain:改写 Set-Cookie 的 Domain",
"properties": {
"from": { "type": "string", "example": ".old.com" },
"to": { "type": "string", "example": ".new.com" }
},
"required": ["from", "to"]
},
"ResponseCachePluginConfig": {
"type": "object",
"description": "type=response_cache:缓存上游原始 GET 响应(不含 Set-Cookie",
"properties": {
"max_mb": { "type": "integer", "minimum": 0, "description": "缓存容量 MB0 表示禁用", "example": 50 },
"ttl_sec": { "type": "integer", "minimum": 1, "description": "TTL 秒,max_mb>0 时默认 300", "example": 300 }
}
},
"ForwardPluginTypes": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": { "$ref": "#/components/schemas/ForwardPluginTypeMeta" }
}
}
},
"ForwardPluginTypeMeta": {
"type": "object",
"properties": {
"type": { "type": "string" },
"label": { "type": "string" },
"description": { "type": "string" },
"config_schema": { "type": "object", "additionalProperties": true },
"default_config": { "type": "object", "additionalProperties": true }
}
}
},
"responses": {
"BadRequest": {
"description": "请求参数无效",
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
},
"Forbidden": {
"description": "权限不足(需管理员)",
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
},
"NotFound": {
"description": "资源不存在",
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
},
"Conflict": {
"description": "路由冲突",
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
}
}
},
"security": [{ "ApiKeyAuth": [] }, { "BearerAuth": [] }],
"paths": {
"/clients": {
"get": {
"summary": "列出客户端及在线状态",
"responses": { "200": { "description": "OK" } }
}
},
"/tunnels": {
"get": {
"summary": "分页查询隧道",
"parameters": [
{ "name": "page", "in": "query", "schema": { "type": "integer" } },
{ "name": "page_size", "in": "query", "schema": { "type": "integer" } },
{ "name": "q", "in": "query", "schema": { "type": "string" } }
],
"responses": { "200": { "description": "OK" } }
},
"post": { "summary": "创建隧道", "responses": { "200": { "description": "OK" } } }
},
"/tunnels/{id}": {
"put": { "summary": "更新隧道", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } },
"delete": { "summary": "删除隧道", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } }
},
"/tunnels/{id}/start": { "post": { "summary": "启动隧道", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } },
"/tunnels/{id}/stop": { "post": { "summary": "停止隧道", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } },
"/tunnels/{id}/pause": { "post": { "summary": "暂停隧道", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } },
"/tunnels/{id}/resume": { "post": { "summary": "恢复隧道", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } },
"/hosts": {
"get": {
"summary": "分页查询域名",
"parameters": [
{ "name": "page", "in": "query", "schema": { "type": "integer" } },
{ "name": "page_size", "in": "query", "schema": { "type": "integer" } },
{ "name": "q", "in": "query", "schema": { "type": "string" } }
],
"responses": { "200": { "description": "OK" } }
},
"post": { "summary": "创建域名", "responses": { "200": { "description": "OK" } } }
},
"/hosts/{id}": {
"put": { "summary": "更新域名", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } },
"delete": { "summary": "删除域名", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } }
},
"/hosts/{id}/pause": { "post": { "summary": "暂停域名", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } },
"/hosts/{id}/resume": { "post": { "summary": "恢复域名", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } },
"/domain-forwards": {
"get": {
"summary": "分页查询域名转发",
"description": "需管理员权限",
"parameters": [
{ "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
{ "name": "page_size", "in": "query", "schema": { "type": "integer", "default": 20 } },
{ "name": "q", "in": "query", "schema": { "type": "string" }, "description": "搜索源域名、目标 URL" }
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/PagedDomainForwards" }
}
}
},
"403": { "$ref": "#/components/responses/Forbidden" }
}
},
"post": {
"summary": "创建域名转发",
"description": "需管理员权限。proxy 模式下可配置 plugins 插件链。",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/DomainForwardInput" },
"examples": {
"redirect": {
"summary": "302 跳转",
"value": {
"source_host": "old.example.com",
"source_location": "/",
"mode": "redirect",
"target_url": "https://new.example.com",
"redirect_mode": "preserve",
"redirect_code": 302,
"status": true
}
},
"proxy_with_plugins": {
"summary": "反代 + 插件链 + HTTP 代理出站",
"value": {
"source_host": "proxy.example.com",
"source_location": "/",
"source_scheme": "all",
"mode": "proxy",
"target_url": "https://backend.internal",
"proxy_type": "http_proxy",
"http_proxy_addr": "127.0.0.1:8080",
"http_proxy_user": "user",
"http_proxy_pass": "secret",
"preserve_host": false,
"plugins": [
{
"type": "response_cache",
"enabled": true,
"config": { "max_mb": 50, "ttl_sec": 300 }
},
{
"type": "sub_filter",
"enabled": true,
"config": {
"filters": [{ "from": "old.internal", "to": "proxy.example.com" }],
"types": ["text/html"]
}
},
{
"type": "inject_js",
"enabled": true,
"config": { "script": "<script>console.log(1)</script>" }
},
{
"type": "cookie_domain",
"enabled": true,
"config": { "from": ".internal", "to": ".example.com" }
}
],
"status": true
}
}
}
}
}
},
"responses": {
"200": {
"description": "创建成功",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/DomainForward" }
}
}
},
"400": { "$ref": "#/components/responses/BadRequest" },
"403": { "$ref": "#/components/responses/Forbidden" },
"409": { "$ref": "#/components/responses/Conflict" }
}
}
},
"/domain-forwards/{id}": {
"put": {
"summary": "更新域名转发",
"description": "需管理员权限。http_proxy_pass / socks5_pass 留空时不修改原密码。",
"parameters": [
{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/DomainForwardInput" }
}
}
},
"responses": {
"200": {
"description": "更新成功",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/DomainForward" }
}
}
},
"400": { "$ref": "#/components/responses/BadRequest" },
"403": { "$ref": "#/components/responses/Forbidden" },
"404": { "$ref": "#/components/responses/NotFound" },
"409": { "$ref": "#/components/responses/Conflict" }
}
},
"delete": {
"summary": "删除域名转发",
"parameters": [
{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
],
"responses": {
"200": {
"description": "删除成功",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Ok" }
}
}
},
"403": { "$ref": "#/components/responses/Forbidden" },
"404": { "$ref": "#/components/responses/NotFound" }
}
}
},
"/domain-forwards/{id}/pause": {
"post": {
"summary": "暂停域名转发",
"parameters": [
{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Ok" }
}
}
},
"403": { "$ref": "#/components/responses/Forbidden" },
"404": { "$ref": "#/components/responses/NotFound" }
}
}
},
"/domain-forwards/{id}/resume": {
"post": {
"summary": "恢复域名转发",
"parameters": [
{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Ok" }
}
}
},
"403": { "$ref": "#/components/responses/Forbidden" },
"404": { "$ref": "#/components/responses/NotFound" }
}
}
},
"/forward-plugin-types": {
"get": {
"summary": "获取域名转发插件类型元数据",
"description": "返回可用插件的 type、label、config_schema、default_config,供前端或 API 客户端动态构建配置。",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ForwardPluginTypes" }
}
}
},
"403": { "$ref": "#/components/responses/Forbidden" }
}
}
}
}
}`