remove discover

add dao
many updates
This commit is contained in:
Star 2024-05-27 16:54:59 +08:00
parent b6bb3098bc
commit 6b1b9d8c6a
10 changed files with 82 additions and 252 deletions

View File

@ -1,7 +1,6 @@
import db from "apigo.cloud/git/apigo/plugins/db"
import redis from "apigo.cloud/git/apigo/plugins/redis"
import logger from "logger"
import console from "console";
/*{{$dao := . -}}*/
class DBConnector {

View File

@ -1,132 +0,0 @@
package discover
import (
"apigo.cloud/git/apigo/plugin"
"github.com/ssgo/discover"
"github.com/ssgo/httpclient"
"github.com/ssgo/log"
"github.com/ssgo/u"
"net/http"
"strings"
)
type DiscoverApp struct {
app string
token string
caller *discover.Caller
logger *log.Logger
globalHeaders map[string]string
}
func init() {
plugin.Register(plugin.Plugin{
Id: "apigo.cloud/git/apigo/plugins/discover",
Name: "服务发现",
Objects: map[string]interface{}{
"fetch": GetDiscoverApp,
},
})
}
// GetDiscoverApp 获得一个服务发现的客户端,如果在配置(server>calls)中指定了AccessToken、超时时间或者HTTP协议(如:iZg753bnsBxTOqHjaeEdt2szvov95eLq34G6jiHBoeE=:1:s:60s)会自动在获得的客户端中设置好
// GetDiscoverApp app 需要访问的服务名称
// GetDiscoverApp return 服务发现客户端对象支持的方法get、post、put、delete、head、setGlobalHeaders
func GetDiscoverApp(app string, ctx *plugin.Context) *DiscoverApp {
logger := ctx.GetInject("*log.Logger").(*log.Logger)
var request *http.Request
if request1, ok := ctx.GetInject("*http.Request").(*http.Request); ok {
request = request1
}
return &DiscoverApp{
app: app,
logger: logger,
caller: discover.NewCaller(request, logger),
globalHeaders: map[string]string{},
}
}
// SetGlobalHeaders 设置固定的HTTP头部信息在每个请求中都加入这些HTTP头
// * SetGlobalHeaders 传入一个Key-Value对象的HTTP头信息
func (dApp *DiscoverApp) SetGlobalHeaders(headers map[string]string) {
dApp.globalHeaders = headers
}
// Get 发送GET请求
// * path /开头的请求路径调用时会自动加上负载均衡到的目标节点的URL前缀发送HTTP请求
// * headers 传入一个Key-Value对象的HTTP头信息如果不指定头信息这个参数可以省略不传
// * return 返回结果对象如果返回值是JSON格式将自动转化为对象否则将字符串放在.result中如发生错误将抛出异常返回的对象中还包括headers、statusCode、statusMessage
func (dApp *DiscoverApp) Get(path string, headers *map[string]string) (map[string]interface{}, error) {
return makeResult(dApp.logger, dApp.caller.Get(dApp.app, fixHTTPPath(path), dApp.makeHeaderArray(headers)...))
}
// Post 发送POST请求
// * data 可以传入任意类型如果不是字符串或二进制数组时会自动添加application/json头数据将以json格式发送
func (dApp *DiscoverApp) Post(path string, data *map[string]interface{}, headers *map[string]string) (map[string]interface{}, error) {
return makeResult(dApp.logger, dApp.caller.Post(dApp.app, fixHTTPPath(path), data, dApp.makeHeaderArray(headers)...))
}
// Put 发送PUT请求
func (dApp *DiscoverApp) Put(path string, data *map[string]interface{}, headers *map[string]string) (map[string]interface{}, error) {
return makeResult(dApp.logger, dApp.caller.Put(dApp.app, fixHTTPPath(path), data, dApp.makeHeaderArray(headers)...))
}
// Delete 发送DELETE请求
func (dApp *DiscoverApp) Delete(path string, data *map[string]interface{}, headers *map[string]string) (map[string]interface{}, error) {
return makeResult(dApp.logger, dApp.caller.Delete(dApp.app, fixHTTPPath(path), data, dApp.makeHeaderArray(headers)...))
}
// Head 发送HEAD请求
func (dApp *DiscoverApp) Head(path string, headers *map[string]string) (map[string]interface{}, error) {
return makeResult(dApp.logger, dApp.caller.Head(dApp.app, fixHTTPPath(path), dApp.makeHeaderArray(headers)...))
}
func (dApp *DiscoverApp) makeHeaderArray(in *map[string]string) []string {
out := make([]string, 0)
if dApp.globalHeaders != nil {
for k, v := range dApp.globalHeaders {
out = append(out, k, v)
}
}
if in != nil {
for k, v := range *in {
out = append(out, k, v)
}
}
return out
}
func fixHTTPPath(path string) string {
if !strings.HasPrefix(path, "/") {
return "/" + path
}
return path
}
func makeResult(logger *log.Logger, result *httpclient.Result) (map[string]interface{}, error) {
r := map[string]interface{}{}
if result.Error != nil {
logger.Error(result.Error.Error())
return nil, result.Error
}
if result.Response != nil {
headers := map[string]string{}
for k, v := range result.Response.Header {
if len(v) == 1 {
headers[k] = v[0]
} else {
headers[k] = strings.Join(v, " ")
}
}
r["headers"] = headers
r["statusCode"] = result.Response.StatusCode
r["statusMessage"] = result.Response.Status
if strings.Contains(result.Response.Header.Get("Content-Type"), "application/json") {
u.UnJson(result.String(), &r)
} else {
r["result"] = result.String()
}
}
return r, nil
}

15
go.mod
View File

@ -8,12 +8,11 @@ require (
github.com/emmansun/gmsm v0.21.1
github.com/gorilla/websocket v1.5.1
github.com/obscuren/ecies v0.0.0-20150213224233-7c0f4a9b18d9
github.com/ssgo/db v1.7.3
github.com/ssgo/discover v1.7.3
github.com/ssgo/httpclient v1.7.3
github.com/ssgo/log v1.7.3
github.com/ssgo/redis v1.7.3
github.com/ssgo/u v1.7.3
github.com/ssgo/db v1.7.5
github.com/ssgo/httpclient v1.7.5
github.com/ssgo/log v1.7.5
github.com/ssgo/redis v1.7.5
github.com/ssgo/u v1.7.5
github.com/tdewolff/parse/v2 v2.7.12
gopkg.in/yaml.v3 v3.0.1
)
@ -22,8 +21,8 @@ require (
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/gomodule/redigo v1.8.8 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/ssgo/config v1.7.3 // indirect
github.com/ssgo/standard v1.7.3 // indirect
github.com/ssgo/config v1.7.5 // indirect
github.com/ssgo/standard v1.7.5 // indirect
github.com/stretchr/testify v1.8.1 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect

View File

@ -2,6 +2,7 @@ package http
import (
"apigo.cloud/git/apigo/plugin"
"errors"
"github.com/gorilla/websocket"
"github.com/ssgo/httpclient"
"github.com/ssgo/log"
@ -62,55 +63,51 @@ func (c *Client) SetGlobalHeaders(headers map[string]string) {
// * url 以http://或https://开头的URL地址如果设置了baseURL可以只提供path部分
// * headers 传入一个Key-Value对象的HTTP头信息如果不指定头信息这个参数可以省略不传
// * return 返回结果对象如果返回值是JSON格式将自动转化为对象否则将字符串放在.result中如发生错误将抛出异常返回的对象中还包括headers、statusCode、statusMessage
func (c *Client) Get(ctx *plugin.Context, url string, headers *map[string]string) (map[string]interface{}, error) {
func (c *Client) Get(ctx *plugin.Context, url string, headers *map[string]string) (*Result, error) {
logger := ctx.GetInject("*log.Logger").(*log.Logger)
return makeResult(logger, c.pool.Get(c.makeURL(url), c.makeHeaderArray(headers)...))
}
// Post 发送POST请求
// * body 可以传入任意类型如果不是字符串或二进制数组时会自动添加application/json头数据将以json格式发送
func (c *Client) Post(ctx *plugin.Context, url string, body interface{}, headers *map[string]string) (map[string]interface{}, error) {
func (c *Client) Post(ctx *plugin.Context, url string, body interface{}, headers *map[string]string) (*Result, error) {
logger := ctx.GetInject("*log.Logger").(*log.Logger)
return makeResult(logger, c.pool.Post(c.makeURL(url), body, c.makeHeaderArray(headers)...))
}
// Put 发送PUT请求
func (c *Client) Put(ctx *plugin.Context, url string, body interface{}, headers *map[string]string) (map[string]interface{}, error) {
func (c *Client) Put(ctx *plugin.Context, url string, body interface{}, headers *map[string]string) (*Result, error) {
logger := ctx.GetInject("*log.Logger").(*log.Logger)
return makeResult(logger, c.pool.Put(c.makeURL(url), body, c.makeHeaderArray(headers)...))
}
// Delete 发送DELETE请求
func (c *Client) Delete(ctx *plugin.Context, url string, body interface{}, headers *map[string]string) (map[string]interface{}, error) {
func (c *Client) Delete(ctx *plugin.Context, url string, body interface{}, headers *map[string]string) (*Result, error) {
logger := ctx.GetInject("*log.Logger").(*log.Logger)
return makeResult(logger, c.pool.Delete(c.makeURL(url), body, c.makeHeaderArray(headers)...))
}
// Head 发送HEAD请求
func (c *Client) Head(ctx *plugin.Context, url string, headers *map[string]string) (map[string]interface{}, error) {
func (c *Client) Head(ctx *plugin.Context, url string, headers *map[string]string) (*Result, error) {
logger := ctx.GetInject("*log.Logger").(*log.Logger)
return makeResult(logger, c.pool.Head(c.makeURL(url), c.makeHeaderArray(headers)...))
}
// Do 发送请求
// * method 请求方法GET、POST等
func (c *Client) Do(ctx *plugin.Context, method string, url string, body interface{}, headers *map[string]string) (map[string]interface{}, error) {
func (c *Client) Do(ctx *plugin.Context, method string, url string, body interface{}, headers *map[string]string) (*Result, error) {
logger := ctx.GetInject("*log.Logger").(*log.Logger)
return makeResult(logger, c.pool.Do(method, c.makeURL(url), body, c.makeHeaderArray(headers)...))
}
// ManualDo 手动处理请求需要自行从返回结果中读取数据可实现SSE客户端
// ManualDo return 应答的对象(需手动读取数据并关闭请求)
func (c *Client) ManualDo(ctx *plugin.Context, method string, url string, body interface{}, headers *map[string]string) (*Reader, error) {
func (c *Client) ManualDo(ctx *plugin.Context, method string, url string, body interface{}, headers *map[string]string) (*ManualResult, error) {
logger := ctx.GetInject("*log.Logger").(*log.Logger)
result := c.pool.ManualDo(method, url, body, c.makeHeaderArray(headers)...)
err, outHeaders, statusCode, _ := _makeResult(logger, result)
return &Reader{
Error: err,
Headers: outHeaders,
StatusCode: statusCode,
response: result.Response,
logger: logger,
r1, _ := makeResult(logger, result)
return &ManualResult{
Result: *r1,
}, result.Error
}
@ -132,23 +129,15 @@ func (c *Client) Open(ctx *plugin.Context, url string, headers *map[string]strin
}
}
func makeResult(logger *log.Logger, result *httpclient.Result) (map[string]interface{}, error) {
func makeResult(logger *log.Logger, result *httpclient.Result) (*Result, error) {
err, headers, statusCode, output := _makeResult(logger, result)
if v, ok := output.(map[string]interface{}); ok {
if err != "" {
v["error"] = err
}
v["headers"] = headers
v["statusCode"] = statusCode
return v, result.Error
} else {
return map[string]interface{}{
"error": err,
"headers": headers,
"statusCode": statusCode,
"result": output,
}, result.Error
}
return &Result{
result: result,
Error: err,
StatusCode: statusCode,
Headers: headers,
Data: output,
}, result.Error
}
func _makeResult(logger *log.Logger, result *httpclient.Result) (err string, headers map[string]string, statusCode int, output interface{}) {
@ -169,8 +158,7 @@ func _makeResult(logger *log.Logger, result *httpclient.Result) (err string, hea
statusCode = result.Response.StatusCode
if strings.Contains(result.Response.Header.Get("Content-Type"), "application/json") {
output = map[string]interface{}{}
u.UnJson(result.String(), &output)
output = u.UnJson(result.String(), nil)
} else {
output = result.String()
}
@ -348,29 +336,57 @@ func (ws *WS) EnableCompression() {
ws.conn.EnableWriteCompression(true)
}
type Reader struct {
type Result struct {
result *httpclient.Result
Error string
Headers map[string]string
StatusCode int
response *http.Response
closed bool
logger *log.Logger
Headers map[string]string
Data interface{}
}
func (hr *Reader) Read(n int) (string, error) {
func (r *Result) String() string {
return r.result.String()
}
func (r *Result) Bytes() []byte {
return r.result.Bytes()
}
type ManualResult struct {
Result
closed bool
}
func (r *ManualResult) Save(filename string) error {
if r.closed {
return errors.New("http client reader closed")
}
r.closed = true
return r.result.Save(filename)
}
func (r *ManualResult) Read(n int) (string, error) {
if r.closed {
return "", errors.New("http client reader closed")
}
buf := make([]byte, n)
n1, err := hr.response.Body.Read(buf)
n1, err := r.result.Response.Body.Read(buf)
return string(buf[0:n1]), err
}
func (hr *Reader) ReadBytes(n int) ([]byte, error) {
func (r *ManualResult) ReadBytes(n int) ([]byte, error) {
if r.closed {
return nil, errors.New("http client reader closed")
}
buf := make([]byte, n)
n1, err := hr.response.Body.Read(buf)
n1, err := r.result.Response.Body.Read(buf)
return buf[0:n1], err
}
func (hr *Reader) Close() error {
if hr.closed {
func (r *ManualResult) Close() error {
if r.closed {
return nil
}
hr.closed = true
return hr.response.Body.Close()
r.closed = true
return r.result.Response.Body.Close()
}

View File

@ -1,52 +0,0 @@
package tests
import (
"apigo.cloud/git/apigo/gojs"
_ "apigo.cloud/git/apigo/plugins/discover"
"github.com/ssgo/discover"
"github.com/ssgo/redis"
"github.com/ssgo/s"
"testing"
)
func TestDiscover(t *testing.T) {
rdServer := StartRedis("16378")
defer rdServer.Close()
rd := redis.GetRedis("redis://localhost:16378", nil)
rd.HSET("echo", "localhost:11223", 100)
rd.SET("echo_localhost:11223", "1")
s.Register(0, "/echo", func(in map[string]interface{}) map[string]interface{} {
return in
}, "")
s.Config.Listen = "11223,h2c"
discover.Config.Registry = "redis://localhost:16378"
discover.Config.Calls = map[string]string{"echo": ""}
as := s.AsyncStart()
defer as.Stop()
// discover.Start("") // if not use ssgo/s, manual start discover
rt := gojs.New(nil)
defer rt.Close()
err := rt.Exec(`
import discover from 'apigo.cloud/git/apigo/plugins/discover'
let echoSrv = discover.fetch('echo')
`)
Test(t, "fetch", err == nil, err)
r, err := rt.Run(`
let r = echoSrv.get('/echo?aaa=111')
if(r.aaa !== '111') throw new Error('aaa is '+r.aaa+' not 111')
return true
`)
Test(t, "get", r == true && err == nil, r, err)
r, err = rt.Run(`
let r = echoSrv.post('/echo', {aaa:111})
if(r.aaa !== 111) throw new Error('aaa is '+r.aaa+' not 111')
return true
`)
Test(t, "post", r == true && err == nil, r, err)
}

View File

@ -5,14 +5,12 @@ go 1.22
toolchain go1.22.1
require (
apigo.cloud/git/apigo/gojs v0.0.6
apigo.cloud/git/apigo/gojs v0.0.8
apigo.cloud/git/apigo/plugin v1.0.1
apigo.cloud/git/apigo/plugins v0.0.0
github.com/mattn/go-sqlite3 v1.14.18
github.com/ssgo/discover v1.7.3
github.com/ssgo/redis v1.7.3
github.com/ssgo/s v1.7.3
github.com/ssgo/u v1.7.3
github.com/ssgo/s v1.7.5
github.com/ssgo/u v1.7.5
github.com/tidwall/redcon v1.6.2
)
@ -29,11 +27,13 @@ require (
github.com/obscuren/ecies v0.0.0-20150213224233-7c0f4a9b18d9 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/shirou/gopsutil/v3 v3.22.10 // indirect
github.com/ssgo/config v1.7.3 // indirect
github.com/ssgo/db v1.7.3 // indirect
github.com/ssgo/httpclient v1.7.3 // indirect
github.com/ssgo/log v1.7.3 // indirect
github.com/ssgo/standard v1.7.3 // indirect
github.com/ssgo/config v1.7.5 // indirect
github.com/ssgo/db v1.7.5 // indirect
github.com/ssgo/discover v1.7.5 // indirect
github.com/ssgo/httpclient v1.7.5 // indirect
github.com/ssgo/log v1.7.5 // indirect
github.com/ssgo/redis v1.7.5 // indirect
github.com/ssgo/standard v1.7.5 // indirect
github.com/tdewolff/parse/v2 v2.7.12 // indirect
github.com/tidwall/btree v1.1.0 // indirect
github.com/tidwall/match v1.1.1 // indirect

View File

@ -60,7 +60,7 @@ func TestH2C(t *testing.T) {
import http from "apigo.cloud/git/apigo/plugins/http"
let c = http.newH2C(10)
r = c.post('http://'+server+'/echo', {aaa:111})
if(r.aaa != 111) throw new Error('aaa is '+r.aaa+' not 111')
if(r.data.aaa != 111) throw new Error('aaa is '+r.data.aaa+' not 111')
return true
`)
Test(t, "post for h2c", r == true && err == nil, r, err)

View File

@ -3,6 +3,6 @@ import http from "apigo.cloud/git/apigo/plugins/http"
let serv = startTestServer('10803')
let r = http.get('http://127.0.0.1:10803/echo?aaa=111')
serv.stop()
if(r.aaa !== '111') throw new Error('aaa is '+r.aaa+' not 111')
if(r.data.aaa !== '111') throw new Error('aaa is '+r.data.aaa+' not 111')
return true

View File

@ -3,6 +3,6 @@ import http from "apigo.cloud/git/apigo/plugins/http"
let serv = startTestServer('10803')
let r = http.get('http://127.0.0.1:10803/jump')
serv.stop()
if(r.aaa !== '222') throw new Error('aaa is '+r.aaa+' not 222')
if(r.data.aaa !== '222') throw new Error('aaa is '+r.data.aaa+' not 222')
return true

View File

@ -3,6 +3,6 @@ import http from "apigo.cloud/git/apigo/plugins/http"
let serv = startTestServer('10803')
let r = http.post('http://127.0.0.1:10803/echo', {aaa:111})
serv.stop()
if(r.aaa !== 111) throw new Error('aaa is '+r.aaa+' not 111')
if(r.data.aaa !== 111) throw new Error('aaa is '+r.data.aaa+' not 111')
return true