urllib.request で十分に通信ができてしまうので、requestsわざわざ使う必要もないかなーと思って(実際Lambdaにあげようとしているのでライブラリは少ないほうが助かる)、oauth_signatureを自作していたのですが、まあ結構辛かったので、メモです。
コード辺
本当に大変だった。概念的には下記みたいな感じ。リクエスト部分はまた今度。
ACCESS_POINT = (
"https://blog.hatena.ne.jp/MireiMixin/namonakimichi.hatenablog.com/atom/entry"
)
class MethodType(Flag):
GET = auto()
POST = auto()
PUT = auto()
DELETE = auto()
WITH_BODY = POST | PUT | DELETE
METHOD_TYPE_STRING = {
MethodType.GET: "GET",
MethodType.POST: "POST",
MethodType.PUT: "PUT",
MethodType.DELETE: "DELETE",
}
RequestParams = NewType("RequestParams", Union[str, int])
RequestDict = NewType("RequestDict", Dict[str, RequestParams])
def load_access_keys() -> Dict[str, str]:
keys = ("consumer_key", "consumer_secret_key", "token_key", "token_secret_key")
return {key: os.getenv(key.upper()) for key in keys}
def create_auth_signature(url, method, baseparam, consumer_keys):
signature = dict(baseparam)
signature = "&".join(
"{0}={1}".format(quote(key, "~"), quote(signature[key], "~"))
for key in sorted(signature)
)
signature = (
"{0}&{1}".format(
quote(consumer_keys["consumer_secret_key"], "~"),
quote(consumer_keys["token_secret_key"], "~"),
),
"{0}&{1}&{2}".format(
quote(METHOD_TYPE_STRING[method].upper()),
quote(url, "~"),
quote(signature, "~"),
),
)
key_utf, text_utf = [s.encode("utf-8") for s in signature]
signature = hmac.new(key_utf, text_utf, hashlib.sha1)
signature = binascii.b2a_base64(signature.digest())[:-1].decode("utf-8")
return signature
def create_oauth_header(url, method):
consumer_keys = load_access_keys()
baseparam = {
"oauth_token": consumer_keys["token_key"],
"oauth_consumer_key": consumer_keys["consumer_key"],
"oauth_signature_method": "HMAC-SHA1",
"oauth_timestamp": str(int(time.time())),
"oauth_nonce": str(random.getrandbits(64)),
"oauth_version": "1.0",
}
oauth_signature = create_auth_signature(url, method, baseparam, consumer_keys)
header = dict(baseparam)
header.update({"oauth_signature": oauth_signature})
header = ",".join(
"{0}={1}".format(quote(k, "~"), quote(header[k], "~")) for k in sorted(header)
)
return {
"Authorization": "OAuth {0}".format(header),
"Content-Type": "application/xml; charset=utf-8",
}
def auth_request(url, method, body):
header = create_oauth_header(url, method)
return request(
url=url,
headers=RequestDict(header),
with_encode=True,
body=RequestDict(body),
)
参考にしたページ
まとめ
リクエスト部分はまた今度で。。。はてなブログAPIを叩くためのAWS LambdaをServerless Frameworkで建てる、みたいな記事を書く予定。
二回もやりたくないかなこれは・・・ 最終的にはRequestsの中身をかなり読んで、それを参考に実装しました。Python3の実装がその辺に転がっていなかったのも結構辛かったです。
とりあえずもう少し上は整理される予定ですが、一旦記事にしとかないとどういうロジックだったか忘れるのでブログにメモだけ残しておきます。