2026-07-21 16:35:46 +08:00
2026-05-27 08:18:36 +08:00
2026-05-28 17:04:29 +08:00
2026-05-28 17:04:29 +08:00
2026-05-22 08:05:05 +08:00
2026-05-22 08:05:05 +08:00
2026-05-27 08:18:36 +08:00
2026-07-21 16:35:46 +08:00
2026-05-22 08:42:27 +08:00

xk-hy-forward-go

内网双通道转发:外网 xk-hy-transit-go 只访问本服务,由本机转发至浙江省政务云(59.202.52.129)。

架构

监听路径 转发目标 用途
POST /province/supervise/data SUPERVISE_TARGET_URL(28212) 加密后的监管业务 JSON
POST /mng/file/auth/upload FILE_TARGET_URL(28211) 处方 PDF multipart 上传
GET /health 本地 健康检查
GET /t 本地 政务云测试页(读 file api-logs、连通测试、回放、导出 ApiPost)
GET /t/prescription 本地 处方业务记录(PDF / 在线处方 / 处方核销,支持详情与单条重试)

转发规则:

  • URL:由环境变量固定(Scheme/Host/Path),不使用客户端 URL。
  • Body:原样透传。
  • Header:仅白名单内的业务头透传到政务云;User-Agent、Cookie、X-Forwarded-*、X-Forward-Token 等不会带上游。
  • 监管白名单含 requestBody、X-Ca-Signature 等(与 transit hy.BuildUpload 一致)。

环境配置

cp .env.example .env
# 编辑 .env 后,建议在项目根目录启动(见下方「启动与 .env 加载」)

启动与 .env 加载

程序启动时会按以下顺序查找并加载 第一个存在的 .env 文件:

  1. 当前工作目录(os.Getwd())
  2. 可执行文件所在目录
  3. 可执行文件上级目录

加载成功时控制台会输出:[forward] 已加载 /path/to/.env。若未找到任何 .env,会提示使用环境变量或代码默认值。

注意:

  • 请使用 # 作为注释(不要用 ;,godotenv 不会把 ; 行当作注释)。
  • 从 IDE / 服务方式启动时,请把 Working Directory 设为 xk-hy-forward-go 项目根,或把 .env 放在 exe 同目录。
  • 核对启动日志中的 forward_enabled=、supervise=、file= 是否为你在 .env 里配置的项。
变量 默认 说明
LISTEN_ADDR :16001 监听地址(建议绑内网 IP)
SUPERVISE_TARGET_URL 政务云 28212 监管业务上报
FILE_TARGET_URL 政务云 28211 处方 PDF 上传
TARGET_URL (兼容) 未设 SUPERVISE_TARGET_URL 时生效
ALLOW_IPS 空 逗号分隔来源 IP;生产建议填 transit 出口 IP
FORWARD_SHARED_SECRET 空 非空时要求请求头 X-Forward-Token 一致(与 transit .env 同值)
ENABLE_FORWARD true 是否真正转发到政务云;false/0/no 时进入回显模式(见下)
LOG_DIR 空 日志根目录;默认 {程序目录}/../log/forward/

回显模式(ENABLE_FORWARD=false)

不请求政务云上游,按与真实转发相同规则(固定目标 URL + Header 白名单 + 原样 Body)组装出站内容,以 JSON 返回给 xk-hy-transit-go,便于联调核对将要发出的报文。

响应示例:

{
  "dry_run": true,
  "kind": "supervise",
  "target_url": "https://59.202.52.129:28212/province/supervise/data",
  "method": "POST",
  "headers": { "Content-Type": ["application/json"], "X-Ca-Signature": ["..."] },
  "body": "明文(监管 JSON 且 UTF-8 有效时)",
  "body_base64": "始终提供,可还原 multipart/二进制"
}
  • headers:过滤后将要转发的请求头。
  • body:明文;kind=file 或 multipart 时为空,请用 body_base64。
  • 启动日志含 forward_enabled=false;应用日志行为 dry_run | target=... | body_len=N。

本地排查示例:

ENABLE_FORWARD=false
ALLOW_IPS=

运行

cd xk-hy-forward-go
go run main.go
go test ./...

main.go 仅作入口,业务逻辑在 internal/forward 包;go run main.go 会编译入口及其依赖,启动全部路由(/health、监管、文件上传)。等价方式:go run .、go build -o forward.exe .。

Windows 也可双击或执行项目根目录下的 run.bat(内部为 go run main.go)。

IDE 调试:Working Directory 设为项目根,运行文件选 main.go 即可。

政务云测试页 /t

启动后浏览器访问:http://<forward-host>:16001/t(随 forward 进程开放,仅建议内网使用)。

功能:

  • 连通测试:对当前 .env 中 28212 / 28211 目标 URL 发起探测。
  • file 日志:左侧列出 api-logs/**/_file_*.log,点击解析 入站(块1) / 出站(块2) 的 Headers 与 Body(multipart 为 body_base64)。
  • 发送:按出站头/体向政务云回放 POST(不含 X-Forward-Token)。
  • 导出 ApiPost:下载 Postman Collection v2.1 JSON,在 ApiPost 中选择 导入 → Postman 集合。

日志含 X-Authorization 等敏感信息,请勿将导出的集合或 /t 暴露到公网。

处方业务记录 /t/prescription

访问:http://<forward-host>:16001/t/prescription

每次写 api-log 后,若为处方相关业务,会追加一行到 {api-logs}/prescription-audit.jsonl:

bizType 含义
pdf 28211 处方 PDF 上传
recipe 28212 uploadRecipeIndicators 在线处方
verification 28212 uploadRecipeVerificationIndicators 处方核销

页面三栏切换查看记录,支持 详情(api-log 三段 JSON)与 重试(出站块 2 回放政务云,不更新 transit/xk-api 状态)。

历史日志可点 重建索引(POST /t/api/prescription/rebuild)全量扫描 *_file_*.log 与 *_supervise_*.log。

/t/api/logs/detail 与 /t/api/test/send 已支持 supervise 日志 rel 路径。

本地联调 mock 上游时,在 .env 中设置:

SUPERVISE_TARGET_URL=http://127.0.0.1:18001/api/
FILE_TARGET_URL=http://127.0.0.1:18001/api/u

未配置 SUPERVISE_TARGET_URL / FILE_TARGET_URL 时,代码默认指向政务云 59.202.52.129(与 .env.example 一致)。

应用日志

每条转发写入 app-YYYY-MM-DD.log(同时输出控制台),格式:

2026-05-19T22:00:01+08:00 | 192.168.1.20 | supervise | http=200 | 120ms | https://59.202.52.129:28212/...
2026-05-19T22:00:02+08:00 | 192.168.1.20 | supervise | dry_run | target=https://... | body_len=1024 | 3ms

摘要行不含完整 body;明细见下方 API 请求日志。

API 请求日志(api-logs)

每次 HTTP 请求(含 /health、监管、文件上传、403 本地拒绝、dry-run)在程序同级目录写入独立文件:

{程序目录}/api-logs/2026-05-27 14/20260527143015_supervise_a1b2c3d4.log

单文件固定 三段(完整原文,不脱敏):

=== META ===
Time / ClientIP / Path / Kind(supervise|file) / DurationMs / Status

=== 1. 入站请求(transit → forward)===
URL、原始 Headers(含 X-Forward-Token)、Body(multipart/PDF 为 body_len + body_base64)

=== 2. 出站转发(forward → 政务云)===
TargetURL、白名单过滤后 Headers、Body(与入站相同字节)

=== 3. 回复(政务云 → forward → transit)===
UpstreamStatus、UpstreamHeaders、Body;JSON 响应额外输出 BodyJSON(缩进格式化)

排查超时:若 块1+块2 完整、块3 为空且 DurationMs 很大,说明已发往政务云但上游无响应(常见为 28211 网络不通)。

注意:日志含 X-Authorization、X-Forward-Token、业务密文及 PDF,已加入 .gitignore,请勿提交仓库或暴露到外网。

Description
上传
Readme 110 KiB
Languages
Go 76%
JavaScript 12.2%
CSS 6.8%
HTML 5%