Golangのネットワーク関連のライブラリを自分用にざっとメモ。
HTTPリクエストを飛ばす
簡単な方法
// リクエスト
resp, _ := http.Get("http://example.com")
// そのリスポンスをprint
defer resp.Body.close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(endpoint)
難しい方法
// request structの作成
req, _ := http.NewRequest(
"Post",
"https://test",
bytes.NewBuffer([]byte("request body"),
)
// そのheaderを指定
req.Header.Add("Content-Type", "application/json")
// クライアントを初期化
var client *http.Client = &http.Client{}
// そこからリクエストを飛ばす
resp, _ := client.Do(req)
// そのリスポンスをprint
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
エンドポイントURLをいじる
base, _ := url.Parse("https://test/mypage/")
reference, _ := url.Parse("myPicture?a=1&b=2")
endpoint := base.ResolveReference(reference).String() // URLを結合する
// クエリパラメタの確認
req, _ := http.NewRequest("GET", endpoint)
fmt.Println(q:= req.URL.Query()) // map
fmt.Println(q.Encode()) //クエリ形式の文字列
MarshalとUnmarshal
- Marshalは構造体→JSON文字列のバイト配列
- UnmarshalはJSON文字列のバイト配列→構造体
type Person struct {
Name string `json:"name"` // Marshal時のkey名をnameに
Age int `json:"age,string"` // Marshal時valueがstringに
Friends int `json:omitempty` // Marshal時valueがempty(0)だと無視される
password string `json:-` // Marshal時無視される
}
func main() {
b := []byte{`{"name":"John", "age":25, "nickname": "Johnny"}`}
var p Person
// byte文字列をPerson構造体へMarshalする (属性名はCaseInsensitive)
if err := json.Unmarshal(b, &p); err!= nil {
fmt.Println(err)
}
// Person構造体をbyte文字列へUnmarshalする
v, err := json.Marshal(p)
fmt.Println(string(v))
}
- Person構造体のカスタム(アン)マーシャルを定義。Person構造体に以下のメソッドが存在すると、
json.Marshal(Person p)
やjson.Unmarshal(b, &p)
が呼び出された際、以下が使われる。
// カスタムマーシャル
func (p Persion) MarshalJSON() ([]byte, error) {
// nameだけをマーシャル
v, err := json.Marshal(&struct{
Name string
}{
Name: "Mr." + p.Name,
}
return v, err
}
// カスタムアンマーシャル
func (p Person) UnMarshalJSON(b []byte) error {
// まずPerson2という構造体を定義し、Person2でアンマーシャル
type Person2 struct {
Name string
}
var p2 Person2
err := json.Unmarshal(b, &p2)
// それを使いpに放り込む
p.Name = "Mr. " + p2.Name
return err
}
HMAC(Hash-based Message Authentication Code)
HMACの仕組み
-
事前に
APIKey
とSecretKey
(秘密鍵=PrivateKeyではない!!!)を発行し、その両方をクライアントサイドに保存する -
ブラウザからサーバへ以下を送信する
APIKey
バイト配列のデータ
-
HMAC
= SecretKeyを用いたハッシュ関数を利用して、2のデータを暗号化したもの。なお、HeaderのSignatureには、この暗号化で使用したハッシュ関数の種類を収納する。 -
用いたハッシュ関数の種類
(SHA-1、MD5など)
- サーバサイドでは以下の手順でデータが改竄されていないことを確認する
- APIKeyに対応するSecretKeyを取り出す
- HMACをそのSecretKeyでdecryptし、それが「データ」と一致するか確かめる
Golangで実装
// クライアントサイド
func main() {
const apiKey = "api_key"
const apiSecret = "api_secret"
data = []byte("data")
h := hmac.New(sha.New, []byte(apiSecret))
h.Write(data)
sign := hex.EncodeToString(h.Sum(nil))
// これをハッシュ関数サーバへ送る
}
// サーバサイド
func Server() {
// 受け取ったapiKeyとHMACで...
apiSecret := DB[apiKey]
h := hmac.New(sha256.New, []byte(apiSecret))
h.Write(data)
expectedMAC = hex.EncodeToString(h.Sum(nil))
// これが受信したデータと一致するか確認
}