Open Search の Go クライアントは、認証、リクエスト署名、および Open Search サービスとの HTTP 通信を処理します。このクライアントを使用して、認証情報を設定し、クライアントを初期化したうえで、認証済みのリクエストを送信します。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
Open Search が有効化された Alibaba Cloud アカウント
認証に使用する AccessKey ID および AccessKey Secret
クライアントのインストール
プロジェクトに必要なモジュールを追加します。
go get github.com/alibabacloud-go/opensearch-util/service
go get github.com/alibabacloud-go/tea-utils/service
go get github.com/alibabacloud-go/tea/tea
go get github.com/aliyun/credentials-go/credentialsクライアントの設定
設定項目
| 項目 | 型 | 説明 |
|---|---|---|
Endpoint | *string | サービスのエンドポイント。デフォルト値は opensearch-cn-hangzhou.aliyuncs.com です。 |
Protocol | *string | HTTP プロトコル。デフォルト値は HTTP です。 |
Type | *string | 認証情報の種類。デフォルト値は access_key です。 |
AccessKeyId | *string | ご利用の AccessKey ID。 |
AccessKeySecret | *string | ご利用の AccessKey Secret。 |
SecurityToken | *string | 一時的なセキュリティトークン。オプション項目であり、セキュリティトークンサービス (STS) の認証情報を使用する場合に指定します。 |
UserAgent | *string | クライアントに割り当てる User Agent 文字列。 |
クライアントの初期化
Config 構造体を NewClient に渡します。AccessKey ID および AccessKey Secret は、ソースコード内にハードコーディングせず、環境変数に格納してください。
your-module/client を、ご利用のローカルクライアントパッケージのインポートパスに置き換えてください。
package main
import (
"fmt"
"os"
client "your-module/client"
util "github.com/alibabacloud-go/tea-utils/service"
"github.com/alibabacloud-go/tea/tea"
)
func main() {
// 認証情報を環境変数から読み込みます — ソースコード内にシークレットをハードコーディングしないでください。
cfg := &client.Config{
Endpoint: tea.String("opensearch-cn-hangzhou.aliyuncs.com"),
Protocol: tea.String("HTTP"),
AccessKeyId: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
AccessKeySecret: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
}
c, err := client.NewClient(cfg)
if err != nil {
fmt.Println("クライアントの初期化に失敗しました:", err)
return
}
_ = c
}リクエストの送信
Request メソッドを、以下のパラメーターを指定して呼び出します。
| パラメーター | 型 | 説明 |
|---|---|---|
method | *string | HTTP メソッド(例:GET、POST)。 |
pathname | *string | リクエストパス(例:/v3/openapi/apps/<app-name>/search)。 |
query | map[string]interface{} | URL クエリパラメーター。指定しない場合は nil を渡します。 |
headers | map[string]*string | 追加のリクエストヘッダー。デフォルト値を使用する場合は nil を渡します。 |
body | interface{} | リクエスト本文。本文がないリクエストの場合は nil を渡します。 |
runtime | *util.RuntimeOptions | タイムアウト、プロキシ、リトライ、SSL 設定。 |
クライアントは、すべてのリクエストに対して自動的に Date、Authorization、X-Opensearch-Nonce、および user-agent ヘッダーを設定します。本文が存在する場合は、さらに Content-Type: application/json および Content-MD5 も設定します。
ランタイムオプションの設定
RuntimeOptions は接続動作を制御します。オプションが明示的に設定されていない場合、クライアントは以下のデフォルト値を使用します。
| オプション | デフォルト値 | 説明 |
|---|---|---|
MaxAttempts | 3 | 最大リトライ回数。 |
BackoffPolicy | no | リトライ間のバックオフ戦略。 |
BackoffPeriod | 1 | バックオフ期間(秒単位)。 |
runtime := &util.RuntimeOptions{
ReadTimeout: tea.Int(5000),
ConnectTimeout: tea.Int(3000),
Autoretry: tea.Bool(true),
MaxAttempts: tea.Int(5),
}
result, err := c.Request(
tea.String("GET"),
tea.String("/v3/openapi/apps/<app-name>/search"),
map[string]interface{}{"query": "example search"},
nil,
nil,
runtime,
)エラーの処理
クライアントは、HTTP 4xx および 5xx 応答に対して tea.SDKError を返します。このエラーには状態コード、状態メッセージ、および生のレスポンスボディが含まれます。
result, err := c.Request(...)
if err != nil {
if sdkErr, ok := err.(*tea.SDKError); ok {
fmt.Println("状態コード:", sdkErr.Code)
fmt.Println("メッセージ:", sdkErr.Message)
fmt.Println("レスポンスボディ:", sdkErr.Data)
}
return
}
fmt.Println("応答:", result["body"])client.Credential が設定されていない場合、GetAccessKeyId および GetAccessKeySecret はエラーを発生させずに nil を返します。リクエストを送信する前に、必ず認証情報を正しく設定してください。
完全なクライアントコード
以下は、完全な自動生成 Go クライアントです。このファイルは手動で編集しないでください。
// このファイルは自動生成されています。手動での編集は行わないでください。よろしくお願いいたします。
/**
*
*/
package client
import (
opensearchutil "github.com/alibabacloud-go/opensearch-util/service"
util "github.com/alibabacloud-go/tea-utils/service"
"github.com/alibabacloud-go/tea/tea"
credential "github.com/aliyun/credentials-go/credentials"
)
type Config struct {
Endpoint *string `json:"endpoint,omitempty" xml:"endpoint,omitempty"`
Protocol *string `json:"protocol,omitempty" xml:"protocol,omitempty"`
Type *string `json:"type,omitempty" xml:"type,omitempty"`
SecurityToken *string `json:"securityToken,omitempty" xml:"securityToken,omitempty"`
AccessKeyId *string `json:"accessKeyId,omitempty" xml:"accessKeyId,omitempty"`
AccessKeySecret *string `json:"accessKeySecret,omitempty" xml:"accessKeySecret,omitempty"`
UserAgent *string `json:"userAgent,omitempty" xml:"userAgent,omitempty"`
}
func (s Config) String() string {
return tea.Prettify(s)
}
func (s Config) GoString() string {
return s.String()
}
func (s *Config) SetEndpoint(v string) *Config {
s.Endpoint = &v
return s
}
func (s *Config) SetProtocol(v string) *Config {
s.Protocol = &v
return s
}
func (s *Config) SetType(v string) *Config {
s.Type = &v
return s
}
func (s *Config) SetSecurityToken(v string) *Config {
s.SecurityToken = &v
return s
}
func (s *Config) SetAccessKeyId(v string) *Config {
s.AccessKeyId = &v
return s
}
func (s *Config) SetAccessKeySecret(v string) *Config {
s.AccessKeySecret = &v
return s
}
func (s *Config) SetUserAgent(v string) *Config {
s.UserAgent = &v
return s
}
type Client struct {
Endpoint *string
Protocol *string
UserAgent *string
Credential credential.Credential
}
func NewClient(config *Config) (*Client, error) {
client := new(Client)
err := client.Init(config)
return client, err
}
func (client *Client) Init(config *Config) (_err error) {
if tea.BoolValue(util.IsUnset(tea.ToMap(config))) {
_err = tea.NewSDKError(map[string]interface{}{
"name": "ParameterMissing",
"message": "'config' can not be unset",
})
return _err
}
if tea.BoolValue(util.Empty(config.Type)) {
config.Type = tea.String("access_key")
}
credentialConfig := &credential.Config{
AccessKeyId: config.AccessKeyId,
Type: config.Type,
AccessKeySecret: config.AccessKeySecret,
SecurityToken: config.SecurityToken,
}
client.Credential, _err = credential.NewCredential(credentialConfig)
if _err != nil {
return _err
}
client.Endpoint = config.Endpoint
client.Protocol = config.Protocol
client.UserAgent = config.UserAgent
return nil
}
func (client *Client) Request(method *string, pathname *string, query map[string]interface{}, headers map[string]*string, body interface{}, runtime *util.RuntimeOptions) (_result map[string]interface{}, _err error) {
_err = tea.Validate(runtime)
if _err != nil {
return _result, _err
}
_runtime := map[string]interface{}{
"timeouted": "retry",
"readTimeout": tea.IntValue(runtime.ReadTimeout),
"connectTimeout": tea.IntValue(runtime.ConnectTimeout),
"httpProxy": tea.StringValue(runtime.HttpProxy),
"httpsProxy": tea.StringValue(runtime.HttpsProxy),
"noProxy": tea.StringValue(runtime.NoProxy),
"maxIdleConns": tea.IntValue(runtime.MaxIdleConns),
"retry": map[string]interface{}{
"retryable": tea.BoolValue(runtime.Autoretry),
"maxAttempts": tea.IntValue(util.DefaultNumber(runtime.MaxAttempts, tea.Int(3))),
},
"backoff": map[string]interface{}{
"policy": tea.StringValue(util.DefaultString(runtime.BackoffPolicy, tea.String("no"))),
"period": tea.IntValue(util.DefaultNumber(runtime.BackoffPeriod, tea.Int(1))),
},
"ignoreSSL": tea.BoolValue(runtime.IgnoreSSL),
}
_resp := make(map[string]interface{})
for _retryTimes := 0; tea.BoolValue(tea.AllowRetry(_runtime["retry"], tea.Int(_retryTimes))); _retryTimes++ {
if _retryTimes > 0 {
_backoffTime := tea.GetBackoffTime(_runtime["backoff"], tea.Int(_retryTimes))
if tea.IntValue(_backoffTime) > 0 {
tea.Sleep(_backoffTime)
}
}
_resp, _err = func() (map[string]interface{}, error) {
request_ := tea.NewRequest()
accesskeyId, _err := client.GetAccessKeyId()
if _err != nil {
return _result, _err
}
accessKeySecret, _err := client.GetAccessKeySecret()
if _err != nil {
return _result, _err
}
request_.Protocol = util.DefaultString(client.Protocol, tea.String("HTTP"))
request_.Method = method
request_.Pathname = pathname
request_.Headers = tea.Merge(map[string]*string{
"user-agent": client.GetUserAgent(),
"Date": opensearchutil.GetDate(),
"host": util.DefaultString(client.Endpoint, tea.String("opensearch-cn-hangzhou.aliyuncs.com")),
"X-Opensearch-Nonce": util.GetNonce(),
}, headers)
if !tea.BoolValue(util.IsUnset(query)) {
request_.Query = util.StringifyMapValue(query)
}
if !tea.BoolValue(util.IsUnset(body)) {
reqBody := util.ToJSONString(body)
request_.Headers["Content-MD5"] = opensearchutil.GetContentMD5(reqBody)
request_.Headers["Content-Type"] = tea.String("application/json")
request_.Body = tea.ToReader(reqBody)
}
request_.Headers["Authorization"] = opensearchutil.GetSignature(request_, accesskeyId, accessKeySecret)
response_, _err := tea.DoRequest(request_, _runtime)
if _err != nil {
return _result, _err
}
objStr, _err := util.ReadAsString(response_.Body)
if _err != nil {
return _result, _err
}
if tea.BoolValue(util.Is4xx(response_.StatusCode)) || tea.BoolValue(util.Is5xx(response_.StatusCode)) {
_err = tea.NewSDKError(map[string]interface{}{
"message": tea.StringValue(response_.StatusMessage),
"data": tea.StringValue(objStr),
"code": tea.IntValue(response_.StatusCode),
})
return _result, _err
}
obj := util.ParseJSON(objStr)
res := util.AssertAsMap(obj)
_result = make(map[string]interface{})
_err = tea.Convert(map[string]interface{}{
"body": res,
"headers": response_.Headers,
}, &_result)
return _result, _err
}()
if !tea.BoolValue(tea.Retryable(_err)) {
break
}
}
return _resp, _err
}
func (client *Client) SetUserAgent(userAgent *string) {
client.UserAgent = userAgent
}
func (client *Client) AppendUserAgent(userAgent *string) {
client.UserAgent = tea.String(tea.StringValue(client.UserAgent) + " " + tea.StringValue(userAgent))
}
func (client *Client) GetUserAgent() (_result *string) {
userAgent := util.GetUserAgent(client.UserAgent)
_result = userAgent
return _result
}
func (client *Client) GetAccessKeyId() (_result *string, _err error) {
if tea.BoolValue(util.IsUnset(client.Credential)) {
return _result, _err
}
accessKeyId, _err := client.Credential.GetAccessKeyId()
if _err != nil {
return _result, _err
}
_result = accessKeyId
return _result, _err
}
func (client *Client) GetAccessKeySecret() (_result *string, _err error) {
if tea.BoolValue(util.IsUnset(client.Credential)) {
return _result, _err
}
secret, _err := client.Credential.GetAccessKeySecret()
if _err != nil {
return _result, _err
}
_result = secret
return _result, _err
}次のステップ
OpenSearch API リファレンス — エンドポイントおよびリクエストパラメーターの完全な一覧
STS を使用した認証情報の管理 — 長期的な AccessKey ペアの代わりに一時的なセキュリティトークンを使用