golangのparseライブラリで別サーバに向ける方法
我らがParse.comさんが本格的にサービス終了されました。それにより前に作ったinstall数集計golangアプリが動作しなくなりました。
今回の環境ではOSSのparse-serverへの移行を成功させているので、回避策としては単純なもので、向き先サーバを変えるだけだったけどろくなドキュメントがなくて大変だったので書いときます。
結論
まず結論です。最初のParse Clientの作成部分は以下のようになっています。
// Client インストール数問い合わせのクライアント type Client struct { parseClient parse.Client } // NewClient Client生成 func NewClient(applicationID string, restAPIKey string) *Client { return &Client{ parseClient: parse.Client{ Credentials: parse.RestAPIKey{ ApplicationID: applicationID, RestAPIKey: restAPIKey, }, }, } } client := parseclient.NewClient(defaultApplicationID, defaultRestAPIKey)
それをこうすれば他の実装を変えなくてもいいです。
// Client インストール数問い合わせのクライアント type Client struct { parseClient parse.Client } // NewClient Client生成 func NewClient(applicationID string, restAPIKey string) *Client { return &Client{ parseClient: parse.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }, Credentials: parse.RestAPIKey{ ApplicationID: applicationID, RestAPIKey: restAPIKey, }, BaseURL: &url.URL{ Scheme: "https", Host: "parse.server.example.com", Path: "", }, }, } } client := parseclient.NewClient(defaultApplicationID, defaultRestAPIKey)
Transport
についてですが、今回建てたparse-sever側のSSL証明書をLet’s encryptにしていましてその証明書に対応しておらず認証失敗となるので、SSLの確認を回避することでとりあえずの回避となっています。これはちゃんとした鍵を置くとかすれば消してもいいでしょう(未検証)。
ソースレベルのお話
https://github.com/facebookgo/parse/blob/master/parse.go
アクセス先のサーバを決めているのは、この https://github.com/facebookgo/parse/blob/master/parse.go#L198 RoundTrip関数
func (c *Client) RoundTrip(req *http.Request) (*http.Response, error) { req.Proto = "HTTP/1.1" req.ProtoMajor = 1 req.ProtoMinor = 1 if req.URL == nil { if c.BaseURL == nil { req.URL = &defaultBaseURL } else { req.URL = c.BaseURL } } else { if !req.URL.IsAbs() { if c.BaseURL == nil { req.URL = defaultBaseURL.ResolveReference(req.URL) } else { req.URL = c.BaseURL.ResolveReference(req.URL) } } } if req.Host == "" { req.Host = req.URL.Host } if req.Header == nil { req.Header = make(http.Header) } var userAgent string if c.UserAgent == "" { userAgent = defaultUserAgent } else { userAgent = c.UserAgent } req.Header.Add(userAgentHeader, userAgent) if c.Credentials != nil { if err := c.Credentials.Modify(req); err != nil { return nil, err } } res, err := c.transport().RoundTrip(req) if err != nil { return res, err } if res.StatusCode > 399 || res.StatusCode < 200 { body, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { return res, err } if len(body) > 0 { var apiErr Error if json.Unmarshal(body, &apiErr) == nil { return res, &apiErr } } return res, &RawError{ StatusCode: res.StatusCode, Body: body, } } return res, nil }
最初の部分だけ見れば良い
if req.URL == nil { if c.BaseURL == nil { req.URL = &defaultBaseURL } else { req.URL = c.BaseURL } } else { if !req.URL.IsAbs() { if c.BaseURL == nil { req.URL = defaultBaseURL.ResolveReference(req.URL) } else { req.URL = c.BaseURL.ResolveReference(req.URL) } } }
req.URL
は Get
、 Post
などを呼び出す際に渡した http.Request
なので基本的にはnilになるはず。
でc
ことclientのBaseURL
の存在を見ています。
defaultBaseURL
は
defaultBaseURL = url.URL{ Scheme: "https", Host: "api.parse.com", Path: "/1/", }
こうなっているので同じような構造のものをクライアントに渡せば良いことがわかります。
まとめ
自前のparse-serverではlimitに制限がないのでガンガンAPI Callできていいですね。