Node.jsにおけるFetch APIを使用したHTTPリクエスト

このガイドでは、Node.jsでFetch APIを使用してHTTPリクエストを送信する方法を学びます。
3 分読
Fetch API in NodeJS

Fetch APIは、Node.jsにおいてHTTPリクエストを実行しローカルリソースを取得するための、新たに公式サポートされた方法です。これにより、プロジェクト内で外部HTTPクライアント依存関係を必要としなくなります。必要なのはNode Fetch APIの使用方法を学ぶことだけであり、それがこのガイドの主題です。

ここでは以下の内容を確認できます:

  • Fetch APIとは
  • Node Fetch API の基本操作
  • Node.jsでFetch APIを用いたHTTPリクエストの実行
  • 追加オプションと機能

さっそく見ていきましょう!

Fetch APIとは?

Fetch APIは、ローカルまたはネットワーク経由でリソースを取得するためのJavaScriptインターフェースです。具体的には、非同期HTTPリクエストを容易に行うためのグローバル関数fetch()を提供します。この同じメソッドはローカルファイルの取得にも使用できます。JavaScript Fetch APIは、従来のXMLHttpRequest APIに代わる柔軟な代替手段です。

fetch()メソッドはRequestオブジェクトとResponseオブジェクトに基づいています。必須引数は1つだけで、取得したいリソースのローカルパスまたはURLを指定します。さらに、CORS、HTTPヘッダー、キャッシュ設定などのオプションも受け付けます。非同期メソッドとして、fetch()はサーバーが生成したレスポンスを解決するPromiseを返します。これはResponseオブジェクトで表され、そのコンテンツボディにアクセスしてパースするためのいくつかのメソッドを公開しています。

基本的な Fetch API の呼び出しは次のようになります:

fetch("https://httpbin.io/ip", {

  // オプション設定...

}).then((response) => response.json())

  .then((data) => {

    // JSONレスポンス本文を出力

    console.log(data) // { "origin": "<YOUR_IP_ADDRESS>" }
  })

// または、同等のasync/await構文を好む場合は以下のように記述可能:

const response = await fetch("https://httpbin.io/ip", {

  // オプション設定...

})

// JSONレスポンス本文を出力

console.log(await response.json()) // { "origin": "<YOUR_IP_ADDRESS>" }

Node Fetch API 入門

Fetch APIは長年主要ブラウザでサポートされてきました。しかし、標準のNode.jsライブラリに組み込まれたのは2022年4月リリース版18.0.0以降です。具体的には、Node Fetch APIはundiciの実装に基づいています。

Node.js 18以前では、実験的機能として有効化するか、別の人気Fetch API実装であるnode-fetch npmライブラリを利用してfetch()を使用できました。現在fetch()は公式Node.js標準ライブラリの一部となったため、インポートせずに直接コードで使用可能です。以下の構文でfetch()メソッドを呼び出すだけです:

fetch(url, options)

url は必須で、以下を含めることができます:

  • ローカルリソースへのパス(例: movies.json)
  • リモートエンドポイントまたはリソースのURL(例: https://httpbin.io/ip または https://example.com/movies.json)

options はオプションのオブジェクトで、以下のオプションフィールドを受け付けます:

  • method: リクエストのHTTPメソッド。「GET」、「POST」、「PUT」、「PATCH」、「DELETE」など。デフォルトは「GET」。
  • headers: リクエストに追加するHTTPヘッダーを含むヘッダーオブジェクトまたはオブジェクトリテラル。デフォルトではヘッダーは設定されません。
  • body: リクエストの本文として使用するデータを含むオブジェクト。GETおよびHEADリクエストには本文を含められないことに注意してください。
  • mode: リクエストに使用するモード(例: “cors”、”no-cors”、”same-origin”、”navigate”、”websocket”)。デフォルトは cors に設定されています。
  • credentials: ブラウザが認証情報を送信するかどうかを指定します。次の文字列のいずれかである必要があります: “omit”、”same-origin”、または “include”。
  • redirect: HTTP リダイレクト応答の処理方法を決定します。「follow」、「error」、または「manual」のいずれかです。デフォルトでは「follow」に設定されています。
  • referrer: リクエストのリファラーを含む文字列。デフォルトでは空文字列です。
  • referrerPolicy: リクエストに使用するリファラーポリシーを指定します。
  • signal: AbortController インターフェースを介してリクエストを中止できる AbortSignal オブジェクトのインスタンス。
  • priority: 現在の Fetch リクエストを、同じタイプの他のリクエストに対して優先させる優先度を指定する文字列。値は “high”、”low”、”auto” を取ります。デフォルトは “auto” です。

詳細は公式ドキュメントのfetch() パラメータセクションを参照してください。

以下はオプションオブジェクトを使用したNode.jsのFetchリクエストの例です:

const response = await fetch("https://your-domain.com/api/v1/users", {

  method: "POST",

  credentials: "include",

  headers: {

    "Content-Type": "application/json",

  },

  body: JSON.stringify({

  username: "jane-doe",

  email: "[email protected]",

  role: "superuser",

  age: 23,

  birthplace: "New York",

}),

})

ボディデータはContent-Typeヘッダーと一致させる必要があることに注意してください。

Node.jsでFetch APIを使用したHTTPリクエストの実行

最も一般的なHTTPメソッドの実用的なリクエスト例で、Node Fetch APIの実動を見てみましょう。

GET

Fetch API を使用して GET リクエストを実行する方法は次のとおりです:

const response = await fetch("https://your-domain.com/your-endpoint")

ご覧の通り、たった1行のコードで実現できます。これはfetch()がデフォルトでGETリクエストを実行するためです。

レスポンスの内容には以下のメソッドでアクセスできます:

  • response.text(): レスポンス本文をテキストとして解決する Promise を返します。
  • response.json(): JSON形式のレスポンスをパースしたオブジェクトを返すPromiseを解決します。
  • response.blob():レスポンス本文をBlobオブジェクトとして解決するPromiseを返します。
  • response.arrayBuffer():レスポンス本文をArrayBufferインスタンスとして解決するPromiseを返します。
  • response.formData(): レスポンスボディをFormDataオブジェクトとして解決するPromiseを返します。

したがって、完全な例のコードは次のようになります:

const response = await fetch("https://httpbin.io/ip")

const jsonResponseContent = await response.json() // { "origin": "<YOUR_IP_ADDRESS>" }

const origin = jsonResponseContent.origin // <YOUR_IP_ADDRESS>

サーバーから返されるレスポンスが JSON 形式でない場合、response.json() は SyntaxError で失敗します。

POST

Node Fetch API を使用した POST リクエストの実行は数行で完了します:

const formData = new FormData()

formData.append("username", "serena-smith")

formData.append("email", "[email protected]")

const response = await fetch("https://example.com/api/v1/users", {

  method: "POST",

  body: formData,

})

fetch()でPOSTリクエストを送信する鍵は、bodyオプションでサーバーに送信するデータを指定することです。これはJSON、FormData、テキストなど複数の形式で可能です。FormDataオブジェクトを送信する場合、Content-Typeヘッダーを指定する必要はありません。それ以外の場合は必須です。

PUT

Fetch API での PUT リクエストの実行は POST と同様です:

const response = await fetch("https://example.com/api/v1/users", {

  method: "PUT",

  credentials: "include",

  headers: {

    "Content-Type": "application/json",

  },

  body: JSON.stringify({

    username: "john-doe",

    email: "[email protected]",

    role: "regular-user",

    age: 47,

    birthplace: "Chicago",

  }),

})

唯一の違いは、メソッド設定で「PUT」を指定する必要がある点です。同様に、「PATCH」に設定することでPATCHリクエストを送信できます。

DELETE

fetch() を使用した HTTP DELETE リクエストの例です:

const response = await fetch("https://example.com/api/v1/users/45", {

  method: "DELETE",

})

ここでも重要なのは正しいHTTPメソッドを設定することです。Fetch APIの実装が他の処理を自動的に行います。

追加オプションと機能

一般的なシナリオでのfetch()の使用方法を理解したところで、Node Fetch APIの高度なオプションを探求する準備が整いました。

ヘッダーの設定

fetch() では、オプションオブジェクトの headers フィールドを通じてリクエストの HTTP ヘッダーをカスタマイズできます。具体的には、headers は Headers オブジェクトまたは特定の文字列値を持つオブジェクトリテラルを受け入れます。

fetch()リクエストでContent-TypeとUser-Agentヘッダーを設定したい場合、以下のようにHeadersオブジェクトを使用できます:

const customHeaders = new Headers()

customHeaders.append("Content-Type", "application/json")

customHeaders.append("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36")

const response = fetch("https://your-domain.com/your-endpoint", {

  headers: customHeaders,

  // その他のオプション...

})

あるいは、オブジェクトリテラルで同等の設定が可能です:

const response = fetch("https://your-domain.com/your-endpoint", {

  headers: {

    "Content-Type": "application/json",

    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",

  },

  // その他のオプション...

})

この構文はよりコンパクトで読みやすくなっています。

ヘッダーの読み取り

サーバーがレスポンスに設定したHTTPヘッダーを読み取りたい場合、以下のようにアクセスできます:

const response = await fetch("https://your-domain.com/your-endpoint", {

  // オプション設定...

})

// "Content-Type" レスポンスヘッダーへのアクセス

const responseHeaders = response.headers

const responseContentType = response.headers.get("Content-Type")

response.headersフィールドはHeadersオブジェクトを返し、get()メソッドで特定のヘッダーにアクセスできます。

Node Fetch API のエラー処理

Node.js の Fetch API 呼び出しが失敗する理由は 2 つだけです:

  • AbortError 例外: AbortController によってリクエストが意図的に中止された場合。
  • TypeError 例外: 無効なヘッダー名、無効な URL、一般的なネットワークエラーなど、複数の原因で発生します。詳細な原因はドキュメントを参照してください。

重要なのは、Fetch API では 4xx または 5xx のレスポンスは成功したリクエストと見なされることです。つまり、サーバーがエラーレスポンスを返しても JavaScript エラーは発生しません。この動作の理由は、fetch() がリクエストを実行し、サーバーがレスポンスを返したためです。概念的には、ネットワークの観点からエラーとは見なせません。結局のところ、リクエストは正常に終了したのです。

これは、サーバーから返されたデータを処理する前に、常にレスポンスの成功を確認すべきことを意味します。そのためには、以下のエラー処理ロジックを実装できます:

try {

  const response = await fetch("https://your-domain.com/your-endpoint", {

    // オプションの設定...

  })

  if (response.ok) {

    // サーバーから返されたデータを使用...

    // 例:

    // await response.json()

  } else {

    // 4xxおよび5xxエラーを処理...

  }

} catch (error) {

  console.error("フェッチエラー:", error.message);

  // ネットワークエラーやアボートエラーを処理...

}

Responseのokプロパティは、リクエストが成功した場合にのみtrueを返すことに注意してください。

Fetchリクエストの中止

Fetch APIは、AbortController APIを通じて既に開始されたリクエストの中止をサポートしています。

進行中の fetch() リクエストを停止するには、まず以下のようにシグナルオブジェクトを生成します:

const controller = new AbortController()

const signal = controller.signal

// 次に、リクエストのオプションオブジェクトで指定します:

const response = await fetch("https://your-domain.com/your-endpoint", {

  signal: signal,

  // その他の設定...

})

これで、以下の指示を呼び出すと、リクエストは AbortError によって中断されます:

controller.abort()

サーバーが既にリクエストを受信している可能性がある点に注意してください。この場合、サーバーはリクエストを実行しますが、Node.js はそのレスポンスを無視します。

おめでとうございます!これでNode.js Fetch APIの達人です!

まとめ

この記事では、Fetch API の概要と Node.js での使用方法を学びました。具体的には、fetch() の基本から始め、その高度なオプションや機能について掘り下げました。このような強力な HTTP クライアントを使えば、オンラインデータの取得が簡単になります。例えば、当社のSERP APIエンドポイントを呼び出して SERP API のデータスクレイピングを開始することも可能です。

Node.jsでのスクレイピングについてさらに学びたいですか?Node.jsによるウェブスクレイピングガイドをお読みください。