Closed9

denoでkyを使ってみる

kawarimidollkawarimidoll

Fetchとの違いは

  • HTTPメソッドを{method:"POST"}のようにオプションで指定するのではなくky.post()のようにメソッドとして指定できる
  • bodyに合わせたContent-Typeヘッダーを自動的につけてくれる
  • response.json()をメソッドチェーンで書ける
  • その他便利なメソッドが定義されていたりいろんなオプションを使えたりする

LINE通知したときのmain.tsを書き換えてみる

main.ts
+ import { ky } from "./deps.ts";
import { LINE_ACCESS_TOKEN } from "./env.ts";
import { Logger } from "./logger.ts";
const url = "https://notify-api.line.me/api/notify";

const body = new URLSearchParams({
  message: "hello from ky!",
});

- const res = await fetch(url, {
-   method: "POST",
+ const json = await ky.post(url, {
  headers: {
    Authorization: `Bearer ${LINE_ACCESS_TOKEN}`,
-    "Content-Type": "application/x-www-form-urlencoded",
  },
  body,
- });
+ }).json();

- const json = await res.json()
Logger.info(json);

修正前と同様に疎通できた

kawarimidollkawarimidoll

感想

  • 今回はURLSearchParamsで送る必要があったのでそこまで大きく行数を減らせたわけではない
  • でもcontent-typeを書かなくて良くなるのは楽、視覚的ストレスが減少する
  • 今後は使っていこう
kawarimidollkawarimidoll
  • なんでURLSearchParamsにしているの?
    • LINEの仕様上、Content-Typemultipart/form-dataまたはapplication/x-www-form-urlencodedで送信する必要がある
    • READMEのtipsに記載のある通り、
    • bodyの型がFormDataならmultipart/form-dataが、型がapplication/x-www-form-urlencodedならURLSearchParamsが、Content-Typeに自動的に設定される
  • kyって何?

It's just a random short npm package name I managed to get. It does, however, have a meaning in Japanese:

A form of text-able slang, KY is an abbreviation for 空気読めない (kuuki yomenai), which literally translates into “cannot read the air.” It's a phrase applied to someone who misses the implied meaning.

「npmパッケージ用に適当な短い名前をつけたんだけど、日本語では『空気読めない』の略なんだ」

kawarimidollkawarimidoll

…と思ったけどこのZennのAPI自体が閉鎖されているみたい?残念

kawarimidollkawarimidoll

tweet-with-iftttならもっと簡単にできる

tweet_with_ifttt.ts
import { ky } from "./deps.ts";
const url = "https://maker.ifttt.com/trigger/send_tweet/with/key/";

const sendTweet = async (params: { message: string; key: string }) => {
  const { message, key } = params;

  try {
    return await ky.post(`${url}${key}`, { json: { value1: message } }).text();
  } catch (error) {
    return await error.response.text();
  }
};

export { sendTweet };
import { sendTweet } from "./tweet_with_ifttt.ts";
import { IFTTT_WEBHOOK_KEY } from "./env.ts";
import { Logger } from "./logger.ts";

const json = await sendTweet({
  message: "Denoからツイート",
  key: IFTTT_WEBHOOK_KEY,
});

Logger.info(json);

IFTTTのレスポンスは返り値をtext()で展開する必要があることに注意

また、エラーハンドリングはこちらのissueで
https://github.com/sindresorhus/ky/issues/107#issuecomment-476048453

kawarimidollkawarimidoll

IFTTTのWebhook URLはエンドポイントの末尾にキーが付加される形なので${url}${key}のように書いている
prefixUrlを使うと文字列連結をしなくて良くなる
動きは同じだがよりクリーンな見た目になる印象

tweet_with_ifttt.ts
import { ky } from "./deps.ts";
- const url = "https://maker.ifttt.com/trigger/send_tweet/with/key/";
+ const prefixUrl = "https://maker.ifttt.com/trigger/send_tweet/with/key/";

const sendTweet = async (params: { message: string; key: string }) => {
  const { message, key } = params;

  try {
-    return await ky.post(`${url}${key}`, { json: { value1: message } }).text();
+    return await ky.post(key, { prefixUrl, json: { value1: message } }).text();
   } catch (error) {
    return await error.response.text();
  }
};

export { sendTweet };

これはなかなか極楽要求みを感じる

このスクラップは2021/06/22にクローズされました