初始化
This commit is contained in:
@@ -1,103 +0,0 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"bj_power_workstation/internal/mes"
|
||||
)
|
||||
|
||||
// taskCurrentHandler 代理 MES GET /api/internal/station/task?dockCode=。
|
||||
// 响应体原样透传(MES 已按 {code,message,data} 封装,这里不再二次包装,避免双重嵌套);
|
||||
// MES 不可达时返回 502 JSON 错误。
|
||||
func taskCurrentHandler(mesc *mes.Client) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
dockCode := strings.TrimSpace(r.URL.Query().Get("dockCode"))
|
||||
if dockCode == "" {
|
||||
fail(w, http.StatusBadRequest, "缺少 dockCode 参数")
|
||||
return
|
||||
}
|
||||
|
||||
body, _, err := mesc.Get("/api/internal/station/task", url.Values{"dockCode": {dockCode}})
|
||||
if err != nil {
|
||||
fail(w, http.StatusBadGateway, "MES 服务不可达:"+errString(err))
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(body)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 工艺 PDF 直通代理 ----------
|
||||
//
|
||||
// 二选一说明:本工程采用「本地无鉴权前缀 /pdfopen/<name>」方案——iframe/img/window.open
|
||||
// 无法方便地携带 Authorization 头,因此对 /pdfopen/ 路径免 JWT 并解析路径参数作为文件名,
|
||||
// 内部仍走 MES /api/internal/files/<name>(内部 API 由 X-API-TOKEN 保护)。
|
||||
// 同时保留需登录态的 GET /api/pdf?name=<file> 供程序化调用。
|
||||
// 两端点均把文件流原样转发并透传 Content-Type/Content-Disposition,不套 {code,message,data}。
|
||||
|
||||
// pdfQueryHandler GET /api/pdf?name=<file>(需登录)
|
||||
func pdfQueryHandler(mesc *mes.Client) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
forwardFile(w, mesc, strings.TrimSpace(r.URL.Query().Get("name")))
|
||||
}
|
||||
}
|
||||
|
||||
// pdfOpenHandler GET /pdfopen/<name>(免鉴权,供 iframe 直链)
|
||||
func pdfOpenHandler(mesc *mes.Client) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// go-zero 路由参数也可用 PathVar,此处直接解析 URL 以减少对外部 API 的依赖
|
||||
raw := strings.TrimPrefix(r.URL.EscapedPath(), "/pdfopen/")
|
||||
name, err := url.PathUnescape(raw)
|
||||
if err != nil {
|
||||
fail(w, http.StatusBadRequest, "非法文件名")
|
||||
return
|
||||
}
|
||||
forwardFile(w, mesc, name)
|
||||
}
|
||||
}
|
||||
|
||||
// forwardFile 校验单段文件名后拉取 MES 文件流并原样转发。
|
||||
func forwardFile(w http.ResponseWriter, mesc *mes.Client, name string) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
fail(w, http.StatusBadRequest, "缺少文件名")
|
||||
return
|
||||
}
|
||||
if strings.ContainsAny(name, `/\`) || name == "." || name == ".." || strings.Contains(name, "..") {
|
||||
fail(w, http.StatusBadRequest, "非法文件名")
|
||||
return
|
||||
}
|
||||
|
||||
body, header, err := mesc.Get("/api/internal/files/"+url.PathEscape(name), nil)
|
||||
if err != nil {
|
||||
fail(w, http.StatusBadGateway, "工艺文件获取失败:"+errString(err))
|
||||
return
|
||||
}
|
||||
|
||||
ct := header.Get("Content-Type")
|
||||
if ct == "" {
|
||||
ct = "application/pdf"
|
||||
}
|
||||
w.Header().Set("Content-Type", ct)
|
||||
if cd := header.Get("Content-Disposition"); cd != "" {
|
||||
w.Header().Set("Content-Disposition", cd)
|
||||
}
|
||||
w.Header().Set("X-Original-Filename", strconv.Quote(name))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(body)
|
||||
}
|
||||
|
||||
// errString 压缩错误信息长度便于前端展示。
|
||||
func errString(err error) string {
|
||||
s := strings.TrimSpace(err.Error())
|
||||
s = strings.ReplaceAll(s, "\n", " ")
|
||||
const maxLen = 180
|
||||
if len(s) > maxLen {
|
||||
return s[:maxLen] + "..."
|
||||
}
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user