やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

APIクライアントのフレームワークについて考えてみた

クライアント自動生成ができないなら、F/Wはどうか。

前回まで

http://ytyaru.hatenablog.com/entry/2017/10/20/000000

WebAPIクライアントの自動作成がしたかったが、以下の理由でむずかしい。

  • 無料WebAPIは大抵REST設計でできている
  • RESTは仕様が曖昧すぎて定形処理化するのが難しい(共通化、自動化できない)

今回

WebAPIクライアント用フレームワークなら作れないか。

HTTP要求

  • URL作成
  • HttpMethod特定
  • Header作成
  • Parameter作成
  • 認証方法特定
    • 認証データ作成

解決すべきこと。

  • どんなAPIがあるか
  • そのAPIにはどんなパラメータが必要か
  • パラメータ値のバリデーション
  • POSTのbody値のバリデーション

HTTP応答

  • HTTP通信エラー時の処理
  • 返却値のデータ型の特定
  • 返却値のエンコード/デコード

考えてみる

HTTP応答のほうが簡単そう。

すでにGitHubAPIで実装した。

http://ytyaru.hatenablog.com/entry/2017/10/19/000000

self.__SplitContentType(r)
if None is self.__mime_type:
    return r.text
elif 'application/json' == self.__mime_type:
    return r.json()
elif self.re_content_type_raw.match(self.__mime_type):
    return r.content
else:
    raise Exception('対象外のContent-Typeです。: ' + self.__mime_type)

GitHubAPIv3では、HTTPヘッダのContent-Typeによって応答の型を判定できる。

しかし、GitHubAPI以外のサービスではそうでないかもしれない。独自の値かもしれないし、Content-Typeでないかもしれないし、ヘッダを使わないかもしれない。

WebAPIの実装側次第である。そこで、フレームワークにして共通化できないか考えてみる。

def GetResponseData(r):
    return r.text

以下の点が気になる。

上記のようにする。実装は、そのAPIとバージョンごとに

def __SplitContentType(self, r):
    if not('Content-Type' in r.headers) or (None is r.headers['Content-Type']) or ('' == r.headers['Content-Type']):
        self.__mime_type = None
        self.__char_set = None
    else:
        self.__mime_type, self.__char_set = r.headers['Content-Type'].split(';')
        if None is not self.__mime_type:
            self.__mime_type = self.__mime_type.strip()
        if None is not self.__char_set:
            # 'charset='を大小文字に関わらず削除する
            self.__char_set = re.sub(self.re_charset, '', self.__char_set).strip()
    print('MimeType: {0}'.format(self.__mime_type))
    print('CharSet: {0}'.format(self.__char_set))