使用Golang向NCMB发送请求
NCMB提供了针对各种语言的SDK。如果考虑非官方的社区SDK,可能会有十多个选项。
这次我尝试使用Go语言向NCMB发送请求。问题在于签名生成过程,通过将其作为函数进行封装,我们也可以考虑将其进行SDK化。
需要的库
本次使用的库如下:
import (
"fmt"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"net/url"
"sort"
"time"
"encoding/json"
"github.com/go-resty/resty/v2"
"github.com/tidwall/gjson"
)
定数的定义
这是一个基础常数,可用于……
// 定数の定義
const (
ApplicationKey = "YOUR_APPLICATION_KEY"
SignatureMethod = "HmacSHA256"
SignatureVersion = "2"
FQDN = "mbaas.api.nifcloud.com"
ClientKey = "YOUR_CLIENT_KEY"
)
主函数的流程
以下是main函数的代码。虽然本次中的objectId和definePath是空的,但可以在通用的签名生成中使用。
func main() {
t := time.Now()
where := map[string]string{
"testKey": "testValue",
}
bytes, _ := json.Marshal(where)
query := map[string]string{
"where": string(bytes),
}
objectId := ""
definePath := ""
path := getPath("TestClass", objectId, definePath)
signature, _ := createSignature("GET", "TestClass", t, query, objectId, definePath)
// URLを作成
partofUrl := &url.URL{
Scheme: "https",
Host: FQDN,
Path: path,
RawQuery: mapToQuery(query),
}
// Restyクライアントの生成
client := resty.New()
// リクエストの作成と送信
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetHeader("X-NCMB-Application-Key", ApplicationKey).
SetHeader("X-NCMB-Signature", signature).
SetHeader("X-NCMB-Timestamp", t.Format("2006-01-02T15:04:05.999Z0700")).
Get(partofUrl.String())
if err != nil {
fmt.Println(err)
}
// レスポンスの解析
value := gjson.Get(resp.String(), "results")
fmt.Println(value)
}
生成署名的函数。
以下是 createSignature 的内容。有关处理内容,请参考 REST API 参考:生成签名的方法 | 参考 Nifcloud 移动后端。
// 署名を作成する関数
func createSignature(method, className string, time time.Time, queries map[string]string, objectId string, definePath string) (string, error) {
// パスの取得
var path = getPath(className, objectId, definePath)
// baseInfoの定義
baseInfoMap := map[string]string{
"X-NCMB-Application-Key": ApplicationKey,
"SignatureMethod": SignatureMethod,
"SignatureVersion": SignatureVersion,
"X-NCMB-Timestamp": time.Format("2006-01-02T15:04:05.999Z0700"),
}
// クエリが存在する場合は、それをbaseInfoMapに追加
if queries != nil {
for k, v := range queries {
baseInfoMap[k] = url.QueryEscape(v)
}
}
// 自然順序でソート
var keys []string
for k := range baseInfoMap {
keys = append(keys, k)
}
sort.Strings(keys)
// baseInfoの作成
var baseInfo string
for _, k := range keys {
if baseInfo != "" {
baseInfo += "&"
}
baseInfo += k + "=" + baseInfoMap[k]
}
// 署名文字列の作成
signatureString := method + "\n" + FQDN + "\n" + path + "\n" + baseInfo
// HMACエンコーディング
h := hmac.New(sha256.New, []byte(ClientKey))
h.Write([]byte(signatureString))
// Base64エンコーディング
return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
}
其他
另外,还有一些准备好的函数。
// パスを取得する関数
func getPath(className string, objectId string, definePath string) string {
if definePath != "" {
return definePath
} else if objectId != "" {
return fmt.Sprintf("/2013-09-01/classes/%s/%s", className, objectId)
} else {
return fmt.Sprintf("/2013-09-01/classes/%s", className)
}
}
// map型のクエリをstring型に変換する関数
func mapToQuery(queries map[string]string) string {
var query string
for k, v := range queries {
if query != "" {
query += "&"
}
query += k + "=" + url.QueryEscape(v)
}
return query
}
整个代码
可以利用此流程来搜索NCMB的数据存储。虽然不支持数据投稿,但只要将GET改为POST即可实现。
package main
import (
"fmt"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"net/url"
"sort"
"time"
"encoding/json"
"github.com/go-resty/resty/v2"
"github.com/tidwall/gjson"
)
// 定数の定義
const (
ApplicationKey = "YOUR_APPLICATION_KEY"
SignatureMethod = "HmacSHA256"
SignatureVersion = "2"
FQDN = "mbaas.api.nifcloud.com"
ClientKey = "YOUR_CLIENT_KEY"
)
// パスを取得する関数
func getPath(className string, objectId string, definePath string) string {
if definePath != "" {
return definePath
} else if objectId != "" {
return fmt.Sprintf("/2013-09-01/classes/%s/%s", className, objectId)
} else {
return fmt.Sprintf("/2013-09-01/classes/%s", className)
}
}
// map型のクエリをstring型に変換する関数
func mapToQuery(queries map[string]string) string {
var query string
for k, v := range queries {
if query != "" {
query += "&"
}
query += k + "=" + url.QueryEscape(v)
}
return query
}
// 署名を作成する関数
func createSignature(method, className string, time time.Time, queries map[string]string, objectId string, definePath string) (string, error) {
// パスの取得
var path = getPath(className, objectId, definePath)
// baseInfoの定義
baseInfoMap := map[string]string{
"X-NCMB-Application-Key": ApplicationKey,
"SignatureMethod": SignatureMethod,
"SignatureVersion": SignatureVersion,
"X-NCMB-Timestamp": time.Format("2006-01-02T15:04:05.999Z0700"),
}
// クエリが存在する場合は、それをbaseInfoMapに追加
if queries != nil {
for k, v := range queries {
baseInfoMap[k] = url.QueryEscape(v)
}
}
// 自然順序でソート
var keys []string
for k := range baseInfoMap {
keys = append(keys, k)
}
sort.Strings(keys)
// baseInfoの作成
var baseInfo string
for _, k := range keys {
if baseInfo != "" {
baseInfo += "&"
}
baseInfo += k + "=" + baseInfoMap[k]
}
// 署名文字列の作成
signatureString := method + "\n" + FQDN + "\n" + path + "\n" + baseInfo
// HMACエンコーディング
h := hmac.New(sha256.New, []byte(ClientKey))
h.Write([]byte(signatureString))
// Base64エンコーディング
return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
}
func main() {
t := time.Now()
where := map[string]string{
"testKey": "testValue",
}
bytes, _ := json.Marshal(where)
query := map[string]string{
"where": string(bytes),
}
objectId := ""
definePath := ""
path := getPath("TestClass", objectId, definePath)
signature, _ := createSignature("GET", "TestClass", t, query, objectId, definePath)
// URLの一部を作成
partofUrl := &url.URL{
Scheme: "https",
Host: FQDN,
Path: path,
RawQuery: mapToQuery(query),
}
// Restyクライアントの生成
client := resty.New()
// リクエストの作成と送信
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetHeader("X-NCMB-Application-Key", ApplicationKey).
SetHeader("X-NCMB-Signature", signature).
SetHeader("X-NCMB-Timestamp", t.Format("2006-01-02T15:04:05.999Z0700")).
Get(partofUrl.String())
if err != nil {
fmt.Println(err)
}
// レスポンスの解析
value := gjson.Get(resp.String(), "results")
fmt.Println(value)
}
总结
Go语言被广泛应用于Web服务和命令行界面等领域。如果与NCMB集成,可以将其作为保存和获取数据的地方。
请把下面的句子用中文进行同意重述,只需要给出一种选择:
虽然在函数级别上,但请将NCMB与Go语言结合使用时,作为参考。
使用mBaaS,无需进行服务器开发!| NIFCLOUD移动后端