From 63983dbd607d09eb35bbac4b7e1d360b2ee03ba1 Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Sat, 30 May 2026 19:02:57 +0800 Subject: [PATCH] feat: register enhanced http capabilities to jsmod --- CHANGELOG.md | 4 ++ go.mod | 1 + go.sum | 2 + js_export.go | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 js_export.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 904a7c9..e8ff668 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## v1.3.3 (2026-05-30) +- **新增**: 注册到 `jsmod`。 +- **优化 (JSMOD)**: 提供 `timeout(ms)` 支持动态超时控制,封装 `jsResult` 以屏蔽敏感的 `Save()` 方法,支持 `form()` 和 `multipart()` 数据标记。 + ## v1.0.10 (2026-05-09) - **CI/CD 对齐**: - 修复测试用例由于默认绑定泛地址导致的 `connection refused` 错误,显式绑定本地测试服务器至 `127.0.0.1`,提高 macOS 与多网卡环境下的测试稳定性。 diff --git a/go.mod b/go.mod index e3ad51f..7d6be45 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( apigo.cc/go/cast v1.3.3 apigo.cc/go/encoding v1.3.1 apigo.cc/go/file v1.3.2 + apigo.cc/go/jsmod v1.0.0 apigo.cc/go/log v1.3.4 apigo.cc/go/rand v1.3.1 golang.org/x/net v0.54.0 diff --git a/go.sum b/go.sum index cf126c8..68bf047 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ apigo.cc/go/file v1.3.2 h1:pu4oiDyiqgj3/eykfnJf+/6+A9v/Z0b3ClP5XK+lwG4= apigo.cc/go/file v1.3.2/go.mod h1:vci4h0Pz94mV6dkniQkuyBYERVYeq7/LX4jJVuCg9hs= 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.0 h1:lVQMq0tCno4kbHlQ3j5wzsm+v24J+bznIoHxpton0pE= +apigo.cc/go/jsmod v1.0.0/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..c58d8cc --- /dev/null +++ b/js_export.go @@ -0,0 +1,102 @@ +package http + +import ( + "time" + + "apigo.cc/go/jsmod" +) + +func init() { + jsmod.Register("http", map[string]any{ + // Static requests with default timeout (30s) + "get": func(url string, headers ...string) *jsResult { + return wrapResult(Get(url, headers...)) + }, + "post": func(url string, data any, headers ...string) *jsResult { + return wrapResult(Post(url, data, headers...)) + }, + "put": func(url string, data any, headers ...string) *jsResult { + return wrapResult(Put(url, data, headers...)) + }, + "delete": func(url string, data any, headers ...string) *jsResult { + return wrapResult(Delete(url, data, headers...)) + }, + + // Timeout control + "timeout": func(ms int) *jsClient { + return &jsClient{c: NewClient(time.Duration(ms) * time.Millisecond)} + }, + + // Data markers + "form": func(data map[string]string) Form { + return Form(data) + }, + "multipart": func(data map[string]any) Multipart { + return Multipart(data) + }, + + // Global Headers + "setGlobalHeader": DefaultClient.SetGlobalHeader, + "getGlobalHeader": DefaultClient.GetGlobalHeader, + }) +} + +// jsClient wraps the internal Client to provide a JS-friendly interface +type jsClient struct { + c *Client +} + +func (jc *jsClient) Get(url string, headers ...string) *jsResult { + return wrapResult(jc.c.Get(url, headers...)) +} + +func (jc *jsClient) Post(url string, data any, headers ...string) *jsResult { + return wrapResult(jc.c.Post(url, data, headers...)) +} + +func (jc *jsClient) Put(url string, data any, headers ...string) *jsResult { + return wrapResult(jc.c.Put(url, data, headers...)) +} + +func (jc *jsClient) Delete(url string, data any, headers ...string) *jsResult { + return wrapResult(jc.c.Delete(url, data, headers...)) +} + +// jsResult wraps *Result to hide sensitive methods like Save() +type jsResult struct { + r *Result +} + +func wrapResult(r *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 "" +}