♻️ refactor(elasticsearch): 改用轻量 REST 客户端

- 使用标准库 HTTP 客户端实现 ES ping、索引、mapping 和查询请求

- 保留代理、TLS、超时和 BasicAuth 配置能力

- 移除 go-elasticsearch SDK 及间接依赖,降低 dev 构建下载风险

- 更新 Elasticsearch 后端单测适配 REST 客户端
This commit is contained in:
Syngnat
2026-06-02 15:30:32 +08:00
parent 05d1bc22c6
commit 864ad8a371
5 changed files with 128 additions and 104 deletions

9
go.mod
View File

@@ -8,7 +8,6 @@ require (
github.com/ClickHouse/clickhouse-go/v2 v2.43.0
github.com/caretdev/go-irisnative v0.2.1
github.com/duckdb/duckdb-go/v2 v2.5.5
github.com/elastic/go-elasticsearch/v8 v8.19.6
github.com/go-sql-driver/mysql v1.9.3
github.com/google/uuid v1.6.0
github.com/highgo/pq-sm3 v0.0.0
@@ -30,11 +29,9 @@ require (
)
require (
github.com/elastic/elastic-transport-go/v8 v8.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel/metric v1.39.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
require (

19
go.sum
View File

@@ -38,6 +38,7 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -64,19 +65,10 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM=
github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU=
github.com/elastic/elastic-transport-go/v8 v8.9.0 h1:KeT/2P54F0xS0S8Y3Pf+tFDg4HmBgReQMB+BMz8dDAs=
github.com/elastic/elastic-transport-go/v8 v8.9.0/go.mod h1:ssMTvNS2hwf7CaiGsRRsx4gQHFZ/jS/DkLcISxekWzc=
github.com/elastic/go-elasticsearch/v8 v8.19.6 h1:4qa7ecJkr5rLsoHKIVGbaqcFt2o57CnOHQJi9Pts/rk=
github.com/elastic/go-elasticsearch/v8 v8.19.6/go.mod h1:jeWebApE1oFEW/hKZqx/IRYmP/aa2+WMJkOfk+AduSI=
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg=
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
@@ -135,6 +127,7 @@ github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxh
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -193,6 +186,7 @@ github.com/pierrec/lz4/v4 v4.1.25 h1:kocOqRffaIbU5djlIBr7Wh+cx82C0vtFb0fOurZHqD0
github.com/pierrec/lz4/v4 v4.1.25/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -210,6 +204,7 @@ github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTK
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
@@ -281,14 +276,8 @@ go.mongodb.org/mongo-driver v1.17.9 h1:IexDdCuuNJ3BHrELgBlyaH9p60JXAvdzWR128q+U5
go.mongodb.org/mongo-driver v1.17.9/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ=
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=

View File

@@ -15,9 +15,6 @@ import (
"GoNavi-Wails/internal/connection"
proxytunnel "GoNavi-Wails/internal/proxy"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
)
const defaultEsPort = 9200
@@ -116,17 +113,31 @@ func esSSLAttemptLabel(config connection.ConnectionConfig, fallback bool) string
return "明文"
}
type esHTTPClientConfig struct {
BaseURL string
Username string
Password string
HTTPClient *http.Client
}
type esRESTClient struct {
baseURL string
username string
password string
httpClient *http.Client
}
// buildESClientConfig 从连接配置构建 ES 客户端配置。
func buildESClientConfig(config connection.ConnectionConfig) elasticsearch.Config {
func buildESClientConfig(config connection.ConnectionConfig) esHTTPClientConfig {
scheme := "http"
if config.UseSSL {
scheme = "https"
}
cfg := elasticsearch.Config{
Addresses: []string{
fmt.Sprintf("%s://%s:%d", scheme, config.Host, config.Port),
},
transport := http.DefaultTransport.(*http.Transport).Clone()
cfg := esHTTPClientConfig{
BaseURL: fmt.Sprintf("%s://%s:%d", scheme, config.Host, config.Port),
Username: strings.TrimSpace(config.User),
Password: config.Password,
}
@@ -134,36 +145,85 @@ func buildESClientConfig(config connection.ConnectionConfig) elasticsearch.Confi
// TLS 配置
tlsConfig, _ := resolveGenericTLSConfig(config)
if tlsConfig != nil {
cfg.Transport = &http.Transport{
TLSClientConfig: tlsConfig,
}
transport.TLSClientConfig = tlsConfig
}
// 代理支持
if config.UseProxy {
transport, ok := cfg.Transport.(*http.Transport)
if !ok {
transport = http.DefaultTransport.(*http.Transport).Clone()
}
proxyCfg := config.Proxy
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
return proxytunnel.DialContext(ctx, proxyCfg, network, addr)
}
cfg.Transport = transport
}
// 超时设置
timeout := getConnectTimeout(config)
if cfg.Transport == nil {
cfg.Transport = http.DefaultTransport.(*http.Transport).Clone()
}
if transport, ok := cfg.Transport.(*http.Transport); ok {
transport.ResponseHeaderTimeout = timeout
}
transport.ResponseHeaderTimeout = timeout
cfg.HTTPClient = &http.Client{Transport: transport}
return cfg
}
func newESRESTClient(config esHTTPClientConfig) (*esRESTClient, error) {
baseURL := strings.TrimRight(strings.TrimSpace(config.BaseURL), "/")
if baseURL == "" {
return nil, fmt.Errorf("Elasticsearch 地址不能为空")
}
if _, err := url.ParseRequestURI(baseURL); err != nil {
return nil, fmt.Errorf("Elasticsearch 地址无效:%w", err)
}
httpClient := config.HTTPClient
if httpClient == nil {
httpClient = http.DefaultClient
}
return &esRESTClient{
baseURL: baseURL,
username: strings.TrimSpace(config.Username),
password: config.Password,
httpClient: httpClient,
}, nil
}
func (c *esRESTClient) do(ctx context.Context, method string, path string, query url.Values, body io.Reader) (*http.Response, error) {
if c == nil || c.httpClient == nil {
return nil, fmt.Errorf("连接未打开")
}
requestURL := c.baseURL + path
if len(query) > 0 {
requestURL += "?" + query.Encode()
}
req, err := http.NewRequestWithContext(ctx, method, requestURL, body)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/json")
if body != nil {
req.Header.Set("Content-Type", "application/json")
}
if c.username != "" || c.password != "" {
req.SetBasicAuth(c.username, c.password)
}
return c.httpClient.Do(req)
}
func esPathSegment(value string) string {
if value == "*" {
return "*"
}
return url.PathEscape(value)
}
func esResponseIsError(res *http.Response) bool {
return res == nil || res.StatusCode >= http.StatusBadRequest
}
func esResponseStatus(res *http.Response) string {
if res == nil {
return ""
}
return res.Status
}
// ---- 查询响应解析 ----
// esIndexInfo 用于解析 Cat Indices JSON 响应。
@@ -196,11 +256,7 @@ func (e *ElasticsearchDB) esQueryWithDSL(ctx context.Context, dsl string) ([]map
indexName = "*"
}
res, err := e.client.Search(
e.client.Search.WithContext(ctx),
e.client.Search.WithIndex(indexName),
e.client.Search.WithBody(strings.NewReader(dsl)),
)
res, err := e.client.do(ctx, http.MethodPost, "/"+esPathSegment(indexName)+"/_search", nil, strings.NewReader(dsl))
if err != nil {
return nil, nil, fmt.Errorf("Elasticsearch DSL 查询失败:%w", err)
}
@@ -218,11 +274,7 @@ func (e *ElasticsearchDB) esQueryWithString(ctx context.Context, queryStr string
dsl := fmt.Sprintf(`{"query":{"query_string":{"query":"%s"}}}`, strings.ReplaceAll(queryStr, `"`, `\"`))
res, err := e.client.Search(
e.client.Search.WithContext(ctx),
e.client.Search.WithIndex(indexName),
e.client.Search.WithBody(strings.NewReader(dsl)),
)
res, err := e.client.do(ctx, http.MethodPost, "/"+esPathSegment(indexName)+"/_search", nil, strings.NewReader(dsl))
if err != nil {
return nil, nil, fmt.Errorf("Elasticsearch 查询失败:%w", err)
}
@@ -232,8 +284,8 @@ func (e *ElasticsearchDB) esQueryWithString(ctx context.Context, queryStr string
}
// parseSearchResponse 解析 ES _search 响应为标准行格式。
func (e *ElasticsearchDB) parseSearchResponse(res *esapi.Response) ([]map[string]interface{}, []string, error) {
if res.IsError() {
func (e *ElasticsearchDB) parseSearchResponse(res *http.Response) ([]map[string]interface{}, []string, error) {
if esResponseIsError(res) {
body, _ := io.ReadAll(res.Body)
return nil, nil, fmt.Errorf("Elasticsearch 查询错误:%s", string(body))
}
@@ -277,17 +329,14 @@ func (e *ElasticsearchDB) esFetchIndexMapping(indexName string) (map[string]inte
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
res, err := e.client.Indices.GetMapping(
e.client.Indices.GetMapping.WithContext(ctx),
e.client.Indices.GetMapping.WithIndex(indexName),
)
res, err := e.client.do(ctx, http.MethodGet, "/"+esPathSegment(indexName)+"/_mapping", nil, nil)
if err != nil {
return nil, fmt.Errorf("获取索引 mapping 失败:%w", err)
}
defer res.Body.Close()
if res.IsError() {
return nil, fmt.Errorf("获取索引 mapping 失败:%s", res.Status())
if esResponseIsError(res) {
return nil, fmt.Errorf("获取索引 mapping 失败:%s", esResponseStatus(res))
}
body, err := io.ReadAll(res.Body)

View File

@@ -8,6 +8,8 @@ import (
"fmt"
"io"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
@@ -15,8 +17,6 @@ import (
"GoNavi-Wails/internal/connection"
"GoNavi-Wails/internal/logger"
"GoNavi-Wails/internal/ssh"
"github.com/elastic/go-elasticsearch/v8"
)
const (
@@ -26,7 +26,7 @@ const (
// ElasticsearchDB 实现 Database 接口,提供 Elasticsearch 数据源连接能力。
type ElasticsearchDB struct {
client *elasticsearch.Client
client *esRESTClient
database string // 默认索引名
pingTimeout time.Duration
forwarder *ssh.LocalForwarder
@@ -85,7 +85,7 @@ func (e *ElasticsearchDB) Connect(config connection.ConnectionConfig) error {
idx+1, len(attempts), sslLabel, attempt.Host, attempt.Port)
esCfg := buildESClientConfig(attempt)
client, err := elasticsearch.NewClient(esCfg)
client, err := newESRESTClient(esCfg)
if err != nil {
logger.Warnf("Elasticsearch 创建客户端失败:%d/%d 模式=%s 错误=%v", idx+1, len(attempts), sslLabel, err)
lastErr = err
@@ -137,14 +137,14 @@ func (e *ElasticsearchDB) Ping() error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
res, err := e.client.Ping(e.client.Ping.WithContext(ctx))
res, err := e.client.do(ctx, http.MethodHead, "/", nil, nil)
if err != nil {
return err
}
defer res.Body.Close()
if res.IsError() {
return fmt.Errorf("Elasticsearch Ping 失败:%s", res.Status())
if esResponseIsError(res) {
return fmt.Errorf("Elasticsearch Ping 失败:%s", esResponseStatus(res))
}
return nil
}
@@ -183,18 +183,17 @@ func (e *ElasticsearchDB) GetDatabases() ([]string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
res, err := e.client.Cat.Indices(
e.client.Cat.Indices.WithContext(ctx),
e.client.Cat.Indices.WithFormat("json"),
e.client.Cat.Indices.WithH("index"),
)
query := url.Values{}
query.Set("format", "json")
query.Set("h", "index")
res, err := e.client.do(ctx, http.MethodGet, "/_cat/indices", query, nil)
if err != nil {
return nil, fmt.Errorf("获取索引列表失败:%w", err)
}
defer res.Body.Close()
if res.IsError() {
return nil, fmt.Errorf("获取索引列表失败:%s", res.Status())
if esResponseIsError(res) {
return nil, fmt.Errorf("获取索引列表失败:%s", esResponseStatus(res))
}
var indices []struct {
@@ -240,17 +239,14 @@ func (e *ElasticsearchDB) GetCreateStatement(dbName, tableName string) (string,
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
res, err := e.client.Indices.Get(
[]string{indexName},
e.client.Indices.Get.WithContext(ctx),
)
res, err := e.client.do(ctx, http.MethodGet, "/"+esPathSegment(indexName), nil, nil)
if err != nil {
return "", fmt.Errorf("获取索引定义失败:%w", err)
}
defer res.Body.Close()
if res.IsError() {
return "", fmt.Errorf("获取索引定义失败:%s", res.Status())
if esResponseIsError(res) {
return "", fmt.Errorf("获取索引定义失败:%s", esResponseStatus(res))
}
body, err := io.ReadAll(res.Body)
@@ -322,19 +318,17 @@ func (e *ElasticsearchDB) GetIndexes(dbName, tableName string) ([]connection.Ind
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
res, err := e.client.Cat.Indices(
e.client.Cat.Indices.WithContext(ctx),
e.client.Cat.Indices.WithIndex(indexName),
e.client.Cat.Indices.WithFormat("json"),
e.client.Cat.Indices.WithH("index", "health", "status", "docs.count", "store.size"),
)
query := url.Values{}
query.Set("format", "json")
query.Set("h", "index,health,status,docs.count,store.size")
res, err := e.client.do(ctx, http.MethodGet, "/_cat/indices/"+esPathSegment(indexName), query, nil)
if err != nil {
return nil, fmt.Errorf("获取索引信息失败:%w", err)
}
defer res.Body.Close()
if res.IsError() {
return nil, fmt.Errorf("获取索引信息失败:%s", res.Status())
if esResponseIsError(res) {
return nil, fmt.Errorf("获取索引信息失败:%s", esResponseStatus(res))
}
var info []esIndexInfo

View File

@@ -11,8 +11,6 @@ import (
"testing"
"GoNavi-Wails/internal/connection"
"github.com/elastic/go-elasticsearch/v8"
)
// ---- 测试辅助函数 ----
@@ -29,13 +27,10 @@ func newMockESServer(t *testing.T, handler http.HandlerFunc) *httptest.Server {
return server
}
// newTestESClient 创建连接到测试服务器的 ES 客户端。
func newTestESClient(t *testing.T, serverURL string) *elasticsearch.Client {
// newTestESClient 创建连接到测试服务器的 ES REST 客户端。
func newTestESClient(t *testing.T, serverURL string) *esRESTClient {
t.Helper()
cfg := elasticsearch.Config{
Addresses: []string{serverURL},
}
client, err := elasticsearch.NewClient(cfg)
client, err := newESRESTClient(esHTTPClientConfig{BaseURL: serverURL})
if err != nil {
t.Fatalf("创建测试 ES 客户端失败: %v", err)
}
@@ -292,7 +287,7 @@ func TestElasticsearchQueryDSL(t *testing.T) {
t.Run("指定索引的 DSL 查询", func(t *testing.T) {
server := newMockESServer(t, func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/_search") {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{
"hits": {
"total": {"value": 1},
@@ -339,7 +334,7 @@ func TestElasticsearchQueryDSL(t *testing.T) {
server := newMockESServer(t, func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/_search") {
capturedPath = r.URL.Path
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"hits":{"total":{"value":0},"hits":[]}}`))
return
}
@@ -379,7 +374,7 @@ func TestElasticsearchQueryString(t *testing.T) {
buf := make([]byte, r.ContentLength)
_, _ = r.Body.Read(buf)
capturedBody = string(buf)
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{
"hits": {
"total": {"value": 2},
@@ -895,8 +890,8 @@ func TestBuildESClientConfig(t *testing.T) {
Port: 9200,
User: "elastic",
})
if len(cfg.Addresses) != 1 || cfg.Addresses[0] != "http://localhost:9200" {
t.Fatalf("HTTP 地址期望 http://localhost:9200实际%v", cfg.Addresses)
if cfg.BaseURL != "http://localhost:9200" {
t.Fatalf("HTTP 地址期望 http://localhost:9200实际%v", cfg.BaseURL)
}
if cfg.Username != "elastic" {
t.Fatalf("用户名期望 elastic实际%q", cfg.Username)
@@ -909,8 +904,8 @@ func TestBuildESClientConfig(t *testing.T) {
Port: 9200,
UseSSL: true,
})
if len(cfg.Addresses) != 1 || cfg.Addresses[0] != "https://es.example.com:9200" {
t.Fatalf("HTTPS 地址期望 https://es.example.com:9200实际%v", cfg.Addresses)
if cfg.BaseURL != "https://es.example.com:9200" {
t.Fatalf("HTTPS 地址期望 https://es.example.com:9200实际%v", cfg.BaseURL)
}
})
}