はじめに
サーバー側はNode.jsのhttpモジュールやfetch、ブラウザ側はwindow.fetchやaxios。プロジェクトの実行環境が変わるたびにHTTPクライアントの書き方も変わって、地味にストレスを感じたことはないでしょうか。
Superagentは、この「環境によって書き方が変わる」問題に、2011年の登場からずっと同じ答えを出し続けているライブラリです。.get()や.send()をチェーンでつなぐfluentなAPIは、Node.jsでもブラウザでも同一。しかもExpressの作者としても知られるTJ Holowaychuk氏が生み出し、現在はForward Emailのチームが引き継いで開発を続けています。
とはいえ、読むより触った方が早いと思います。クエリパラメータを書き換えるだけでリクエスト結果がその場で変わるので、先に挙動を見たい方はこちらからどうぞ。
Superagentとは
Superagentは、HTTPリクエストをメソッドチェーンで組み立てられる、ブラウザ・Node.js両対応のHTTPクライアントライブラリです。npmの週間ダウンロード数は数百万規模を維持しており、axiosやfetchと並ぶ選択肢として今も現役で使われています。
主な特徴
- fluentなチェーンAPI -
superagent.get(url).query({}).set({}).send({})のように、リクエストの組み立てを直感的に連結できる - ブラウザとNode.jsで共通のAPI - サーバー側はNode.jsの
http/https、ブラウザ側はXHRを内部で使い分けつつ、呼び出し側のコードは変える必要がない - Promise / async-await対応 -
.then()だけでなくawaitでもそのまま使える - プラグイン機構 -
.use()でリクエストへの処理を差し込める。認証ヘッダーの付与やロギングなどを共通化しやすい - 多彩なオプション - タイムアウト、自動リトライ、multipart/form-dataでのファイルアップロードなどを標準でサポート
インストール
npm・yarn・pnpmのいずれでも導入できます。
npm install superagent
yarn add superagent
pnpm add superagent
Superagentのサンプルを動かす
以下は、Superagentのsuperagent.get()と.query()を使ってJSONPlaceholder(ダミーAPI)からTODOを取得するサンプルです。入力欄のIDを書き換えて実行ボタンを押すと、.query({})で組み立てたクエリパラメータの内容がそのままリクエストに反映され、結果が画面に表示されます。
要点だけを抜き出すと、次のようになります。
import superagent from 'superagent'
const res = await superagent
.get('https://jsonplaceholder.typicode.com/todos')
.query({ id: 1 }) // ?id=1 が付与される
.set('Accept', 'application/json')
console.log(res.body) // レスポンスボディはres.bodyでJSONとして取得できる
実際に動かせるものが下です。
IDを999のような存在しない値に変えると、Superagentが空配列のレスポンスをそのまま返してくることが確認できます。.query()に渡すオブジェクトのキーを増やせば、複数条件のクエリパラメータも同様に組み立てられます。
基本的な使い方
もっともシンプルな形は、superagent.get(url)をawaitで受け取るだけです。
import superagent from 'superagent'
// GETリクエスト
const res = await superagent.get('https://jsonplaceholder.typicode.com/todos/1')
console.log(res.status) // 200
console.log(res.body) // { userId: 1, id: 1, title: '...', completed: false }
// ヘッダーの付与
await superagent
.get('https://jsonplaceholder.typicode.com/todos/1')
.set('Authorization', 'Bearer TOKEN')
.set('Accept', 'application/json')
// POSTリクエストとJSON送信
await superagent
.post('https://jsonplaceholder.typicode.com/posts')
.send({ title: 'foo', body: 'bar', userId: 1 })
.set('Content-Type', 'application/json')
.send()にオブジェクトを渡すと、Content-Typeが未指定でもSuperagentが自動的にJSONとして直列化してくれます。エラー時はtry/catchでerr.responseからステータスやボディを参照できます。
実践的なユースケース
クエリパラメータによる検索・フィルタリング
一覧系のAPIでは、キーワードやページ番号などの条件をクエリパラメータとして付け替えることがよくあります。Superagentの.query()はオブジェクトを渡すだけで、キーの追加・削除がそのままURLに反映されるのが利点です。
以下は、キーワードを入力するとJSONPlaceholderの投稿一覧を.query({ userId })で絞り込むサンプルです。
userIdを空にすると全件、存在しない番号にすると0件になる挙動から、.query()に渡した値がそのままAPI側のフィルタ条件になっていることが分かります。
POSTリクエストとJSONボディの送信
フォームの入力内容をAPIに送信する場面では、.send()でボディを組み立てます。SuperagentはContent-Typeをペイロードの型から推測するため、オブジェクトを渡すだけでJSON送信になります。
タイトルを空にして送信してみてください。JSONPlaceholderはモックAPIのためエラーにはなりませんが、レスポンスのtitleフィールドが空文字のまま返ってくることから、.send()で渡したオブジェクトがそのままリクエストボディになっていることが確認できます。
タイムアウトとリトライ設定
外部APIは常に速く応答するとは限りません。Superagentは.timeout()で待ち時間の上限を、.retry()で失敗時の再試行回数を宣言的に指定できます。
タイムアウト値を極端に短く(例: 1ms)してみると、.retry(2)で指定した回数だけ再試行したうえでerr.timeoutが発生する様子が確認できます。本番運用では、外部APIの応答が不安定な箇所にこのパターンを組み込むことで、リトライ処理を自前で書かずに済みます。
まとめ
Superagentは、fluentなチェーンAPIとブラウザ・Node.js共通の書き方を軸に、10年以上にわたって現役であり続けているHTTPクライアントです。.query()によるパラメータ組み立て、.send()によるボディ送信、.timeout()/.retry()による信頼性向上まで、HTTP通信でよく使う機能が一通り揃っています。
axiosやfetchに慣れている方も、実行環境をまたいで同じコードを書きたい場面では選択肢に入れてみてください。まずは手元のプロジェクトで、GETリクエスト1本から試してみるのがおすすめです。
