From 5051f455d6315911cc2f1be6e0e50b4cae2ff116 Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Sun, 31 May 2026 01:02:02 +0800 Subject: [PATCH] feat(jsmod): register discover to jsmod v1.3.2 --- CHANGELOG.md | 8 ++++ go.mod | 1 + go.sum | 2 + js_export.go | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 js_export.go diff --git a/CHANGELOG.md b/CHANGELOG.md index d04de89..2c020b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # CHANGELOG +## v1.3.3 (2026-05-31) +- **新增**: 深度集成 `jsmod`。 + - 提供 `get`, `post`, `put`, `delete`, `head`, `do`, `open` 等微服务调用能力。 + - 提供 `from(r)` 支持微服务间的链路透传 (Context Propagation)。 + - 导出微服务相关的 `header` 常量。 +- **安全增强**: 封装 `jsResult` 以屏蔽敏感的 `Save()` 方法,确保微服务响应处理符合沙箱规范。 +- **管控**: 定义 `setNode`, `setLoadBalancer`, `setRoute`, `addExternalApp` 为 `unsafe` 方法。 + ## v1.0.10 (2026-05-09) - **API Redesign (Elegant API)**: - 引入包级泛型便捷调用:`Get[T]`, `Post[T]`, `Put[T]`, `Delete[T]`。 diff --git a/go.mod b/go.mod index c1a0218..74d5c67 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( apigo.cc/go/cast v1.3.3 apigo.cc/go/http v1.3.2 apigo.cc/go/id v1.3.1 + apigo.cc/go/jsmod v1.0.1 apigo.cc/go/log v1.3.4 apigo.cc/go/redis v1.3.2 apigo.cc/go/safe v1.3.1 diff --git a/go.sum b/go.sum index d3d1156..2ea8de5 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ apigo.cc/go/http v1.3.2 h1:0Or5KfoIq4+yeWKYusYPV8XLPw8XuzJMeaFv7dZViLI= apigo.cc/go/http v1.3.2/go.mod h1:Q9R7Ors0Fz2A6Mxg0dykO2PjCzdAHRRXreOUMjMOLwA= apigo.cc/go/id v1.3.1 h1:pkqi6VeWyQoHuIu0Zbx/RRxIAdM61Js0j6cY1M9XVCk= apigo.cc/go/id v1.3.1/go.mod h1:P2/vl3tyW3US+ayOFSMoPIOCulNLBngNYPhXJC/Z7J4= +apigo.cc/go/jsmod v1.0.1 h1:vaz3cMQi75UVoALLfyV/Trs8iP/Nh28yN57IvBFpPGk= +apigo.cc/go/jsmod v1.0.1/go.mod h1:bmyeZtOAP/j5am+YRnaiM89smysK24K7ebk0koFtsSw= apigo.cc/go/log v1.3.4 h1:UT8Neb9r4QjjbCFbTzw+ZeTxd+DmdmR5gNExeR4Cj+g= apigo.cc/go/log v1.3.4/go.mod h1:/Q/2r51xWSsrS4QN5U9jLiTw8n6qNC8kG9nuVHweY20= apigo.cc/go/rand v1.3.1 h1:7FvsI6PtQ5XrWER0dTiLVo0p7GIxRidT/TBKhVy93j8= diff --git a/js_export.go b/js_export.go new file mode 100644 index 0000000..3c5d8f3 --- /dev/null +++ b/js_export.go @@ -0,0 +1,117 @@ +package discover + +import ( + "net/http" + + gohttp "apigo.cc/go/http" + "apigo.cc/go/jsmod" +) + +func init() { + jsmod.Register("discover", map[string]any{ + // RPC 调用 (默认实例) + "get": func(app, path string, headers ...string) *jsResult { + return wrapResult(Get(app, path, headers...)) + }, + "post": func(app, path string, data any, headers ...string) *jsResult { + return wrapResult(Post(app, path, data, headers...)) + }, + "put": func(app, path string, data any, headers ...string) *jsResult { + return wrapResult(DefaultDiscoverer.Put(app, path, data, headers...)) + }, + "delete": func(app, path string, data any, headers ...string) *jsResult { + return wrapResult(DefaultDiscoverer.Delete(app, path, data, headers...)) + }, + "head": func(app, path string, headers ...string) *jsResult { + return wrapResult(DefaultDiscoverer.Head(app, path, headers...)) + }, + "do": func(method, app, path string, data any, headers ...string) *jsResult { + return wrapResult(DefaultDiscoverer.Do(method, app, path, data, headers...)) + }, + "open": func(app, path string, headers ...string) any { + return DefaultDiscoverer.Open(app, path, headers...) + }, + + // 链路透传 + "from": func(r *http.Request) *jsCaller { + return &jsCaller{c: DefaultDiscoverer.From(r)} + }, + + // 状态获取 + "getAppNodes": func(app string) map[string]*NodeInfo { + return DefaultDiscoverer.GetAppNodes(app) + }, + + // Header 常量 + "headerFromApp": HeaderFromApp, + "headerFromNode": HeaderFromNode, + "headerClientIP": HeaderClientIP, + "headerForwardedFor": HeaderForwardedFor, + "headerUserID": HeaderUserID, + "headerDeviceID": HeaderDeviceID, + "headerClientAppName": HeaderClientAppName, + "headerClientAppVersion": HeaderClientAppVersion, + "headerSessionID": HeaderSessionID, + "headerRequestID": HeaderRequestID, + "headerHost": HeaderHost, + "headerScheme": HeaderScheme, + "headerUserAgent": HeaderUserAgent, + }, "setNode", "setLoadBalancer", "setRoute", "addExternalApp") +} + +// jsResult 包装 *gohttp.Result 以隐藏 Save() 等危险方法 +type jsResult struct { + r *gohttp.Result +} + +func wrapResult(r *gohttp.Result) *jsResult { + return &jsResult{r: r} +} + +func (jr *jsResult) String() string { return jr.r.String() } +func (jr *jsResult) Bytes() []byte { return jr.r.Bytes() } +func (jr *jsResult) Map() map[string]any { + return jr.r.Map() +} +func (jr *jsResult) Slice() []any { + return jr.r.Slice() +} +func (jr *jsResult) Status() int { + if jr.r.Response != nil { + return jr.r.Response.StatusCode + } + return 0 +} +func (jr *jsResult) Error() string { + if jr.r.Error != nil { + return jr.r.Error.Error() + } + return "" +} + +// jsCaller 包装 *Caller 以确保返回包装后的结果 +type jsCaller struct { + c *Caller +} + +func (jc *jsCaller) Get(app, path string, headers ...string) *jsResult { + return wrapResult(jc.c.Get(app, path, headers...)) +} +func (jc *jsCaller) Post(app, path string, data any, headers ...string) *jsResult { + return wrapResult(jc.c.Post(app, path, data, headers...)) +} +func (jc *jsCaller) Put(app, path string, data any, headers ...string) *jsResult { + return wrapResult(jc.c.Put(app, path, data, headers...)) +} +func (jc *jsCaller) Delete(app, path string, data any, headers ...string) *jsResult { + return wrapResult(jc.c.Delete(app, path, data, headers...)) +} +func (jc *jsCaller) Head(app, path string, headers ...string) *jsResult { + return wrapResult(jc.c.Head(app, path, headers...)) +} +func (jc *jsCaller) Do(method, app, path string, data any, headers ...string) *jsResult { + return wrapResult(jc.c.Do(method, app, path, data, headers...)) +} +func (jc *jsCaller) Open(app, path string, headers ...string) any { + return jc.c.Open(app, path, headers...) +}