Node.js 標準モジュールhttps でWebAPIへGETリクエスト
はじめまして、マッキーと申します。先日、ある企業のコーディングテストを受けたのですが、そこで純粋なアルゴリズムだけでなく、APIを利用した課題が出題されることがあることを知りました。
JSONデータはJavascript(Nodejs)で扱うのが簡単であると自分は感じるのですが、axiosやrequestのような外部モジュールはnodejsのバージョンにも気を配る必要があります。そのためコーディングテストのような環境ではバージョンを意識せず使える標準モジュールであるhttpsを使いたいと感じました。
この記事でわかること
httpsを使った外部のAPIへのGETリクエストの投げ方
シンプルなGETリクエスト
まずは以下にコードを示します。下のコードでは、ポケモンに関する情報を取得できるPokeAPIに向けてGETリクエストを投げています。
const https = require("node:https");
// require("node:https") はnodejsの標準パッケージであることを強調
// require("https")でもOK
https.get("https://pokeapi.co/api/v2/pokemon/pikachu", (res) => {
console.log(`ステータスコード: ${res.statusCode}`);
let body = "";
// データが分割されたカタマリ(chunk)を受信する度に以下の関数が実行される
res.on("data", (chunk) => {
body += chunk;
});
// 全てのchunkが受信されたら以下の関数が実行される
res.on("end", () => {
// bodyは文字列なのでオブジェクトにパースする
const data = JSON.parse(body);
console.log("ピカチュウの情報");
console.log(
`タイプ: ${data.types.map((type) => type.type.name).join(", ")}`
);
console.log(`体重: ${data.weight}`);
});
});
実行すると以下のような結果が得られます。
ステータスコード: 200
ピカチュウの情報
タイプ: electric
体重: 60
ピカチュウはでんきタイプ(electoric)ですから問題なく情報が取得できていそうです!
https.get(url, [callback])のように引数に与えるとurl引数に与えたURLにGETリクエストをし、通信に成功するとresオブジェクトがcallback関数に与えられます。
ネットワークではデータは分割された単位(チャンク)に分けられて送受信されるのですが、このチャンクを受信するたびres.on("data", [callback]) が発火します(ドキュメント)。
axiosはこのチャンクによる分割を意識しなくて済むよう振る舞ってくれています。
そして全てのチャンクを受信するとres.on("end", [callback]) が発火するので基本的にはメインのロジックはres.onに書くことになると思います。(axiosの.then(res => {...}) に対応します。)
クエリパラメータの使用
クエリパラメータを使用して絞り込みされたレスポンスが欲しい時があると思います。
先程はhttps.get(url, [callback])のurl引数に文字列を与えましたが、url引数は文字列のみならずURLオブジェクトを受け取ることもできます。URLオブジェクトとはhttpsと同じくnodejsの標準モジュールであるURLによって提供され、URLの操作を容易にしてくれます。
以下のコードでは様々なダミーデータを返してくれるJSONPlaceholderというAPIのSNSの投稿データのようなダミーを返してくれるエンドポイントにリクエストしており、その際に特定のidを持つ投稿のみを返すようクエリパラメータを付与しています。
const https = require("https");
const { URL } = require("url");
const baseUrl = "https://jsonplaceholder.typicode.com/posts";
// URLオブジェクトを作成
// URLオブジェクトはURLを操作するための便利なクラス
const url = new URL(baseUrl);
let postIds = [1, 3, 9];
for (postId of postIds) {
// URLにクエリパラメータを追加
// https://jsonplaceholder.typicode.com/posts?id=1&id=3&id=9 ってなる
url.searchParams.append("id", postId);
}
// リクエストを送る
https.get(url, (res) => {
let data = "";
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () => {
console.log("Response:", data);
});
});
作成したURLオブジェクトに対して、searchParams.append(key, value) というメソッドを呼ぶとURLの末尾にkey=valueというようにクエリパラメータを追加してくれます。このように自分でURLの末尾にクエリパラメータを付与していくよりもURLモジュールを活用するほうが簡単であるように感じられると思います。
コードを実行すると以下のような結果が得られ、確かに指定したidを持つ投稿の情報が返却されたことが確認できます。
Response: [
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"userId": 1,
"id": 3,
"title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
"body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
},
{
"userId": 1,
"id": 9,
"title": "nesciunt iure omnis dolorem tempora et accusantium",
"body": "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
}
]
HTTPヘッダの設定
ここまではhttps.get関数の引数はurlとコールバック関数のみであるように書いてきましたが、実際にはもう一つ、optionsという引数を指定できます。
https.get(url, [options], [callback])の形式において、optionsに指定されたキーを持ったオブジェクトを渡すとより詳細にリクエストを制御できます。
以下のコードでは様々なモックサーバーを提供してくれるhttbin のヘッダ情報をそのまま返却してくれるエンドポイントへGETリクエストを送信します。
const https = require("https");
const { URL } = require("url");
const url = new URL("https://httpbin.org/headers");
const options = {
// headersに[key: value]の形式でヘッダ情報を記載する
// headersの他にもいろいろなオプションを指定できる
headers: {
"User-Agent": "Node.js",
Accept: "application/json",
},
};
https.get(url, options, (res) => {
let data = "";
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () => {
console.log("Response:", data);
});
});
実行結果は以下のようになり、指定したヘッダ情報に加え、ホスト情報とトレースIDが返却されています。
Response: {
"headers": {
"Accept": "application/json",
"Host": "httpbin.org",
"User-Agent": "Node.js",
"X-Amzn-Trace-Id": "Root=1-6807920f-1e92c44456b19b1b270148d9"
}
}
掲載したコードはココからダウンロードできます。
参考
- httpモジュールのドキュメント(https://nodejs.org/api/http.html)
- httpsモジュールのドキュメント(https://nodejs.org/api/https.html)
- URLモジュールのドキュメント(https://nodejs.org/docs/latest-v14.x/api/url.html)