3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

fetch()でもaxios.get()でも解決しないリダイレクトループに遭遇した話

Posted at

最近個人開発しているアプリでは、@remix-run/nodefetch()を使って特定のURLのメタ情報を取得するようにしていました。

あるとき、https://engineerteam.note.jp/n/nb49d32f5bedeに対してfetch()を呼び出す機会がありました。

const response = await fetch(url);

ところが、これを呼び出してみたところPremature closeというエラーが発生してしまいました。

/workspaces/example-app/node_modules/@remix-run/web-fetch/src/fetch.js:342
    const error = Object.assign(new Error('Premature close'), {
                                ^
Error: Premature close
    at TLSSocket.onSocketClose (/workspaces/example-app/node_modules/@remix-run/web-fetch/src/fetch.js:342:33)
    at TLSSocket.emit (node:events:525:35)
    at node:net:301:12
    at TCP.done (node:_tls_wrap:588:7)

色々オプションを設定してみましたが、エラーの発生を防ぐことはできませんでした。

const response = await fetch(url, {
  method: "GET",
  redirect: "follow",
  follow: 10,
});

調べてみても、同じような問題に引っ掛かっている人がいないため、なかなか答えを見つけられませんでした。
そこで、これはfetch()特有の問題なのかと思い、試しにaxiosを使ってみることにしました。

import axios from 'axios'
...
const res = await axios.get(url)

今度はより詳細なエラーが発生しました。
内容を確認してみると、リダイレクトの回数が多すぎるということがわかりました。
おそらく、fetch()でもこの問題が発生しているためPremature closeというエラーが発生していたのだと思います。

Error [ERR_FR_TOO_MANY_REDIRECTS]: Maximum number of redirects exceeded
    at Function.AxiosError.from (/workspaces/example-app/node_modules/axios/lib/core/AxiosError.js:89:14)
    at RedirectableRequest.handleRequestError (/workspaces/example-app/node_modules/axios/lib/adapters/http.js:577:25)
    at RedirectableRequest.emit (node:events:513:28)
    at RedirectableRequest._processResponse (/workspaces/example-app/node_modules/follow-redirects/index.js:371:10)
    at NodeClientRequest.RedirectableRequest._onNativeResponse (/workspaces/example-app/node_modules/follow-redirects/index.js:62:10)

より詳細なエラーの内容がわかったので、これをもとに色々調べてみると、こちらの投稿を見つけました。

投稿者の方が抱えていた問題の原因は、サーバー側によるクッキーを使ったステートの検証によるリダイレクトのループの発生のようです。
つまり、リクエスト先のサーバー側で、本来ならクエリーとして渡すべき情報をクッキーによって管理しているため、そのデータの有無により永遠にリダイレクトされるといった問題のようです。

つまり、ここで必要なのはCookie Jarの機能ということになります。

Cookie Jarとは、簡単にいうと、特定のウェブサイトのクッキーを保存・管理するためのコンテナ機能のことです。
この機能がNode.jsで動作するaxiosfetch()ではデフォルトでサポートされていないため、何も設定しない状態でリクエストを送っても先ほどのようなエラーが発生してしまいます。

そこで、この問題を解決するためにaxios-cookiejar-supportというライブラリを使うことにしました。

今回、axiosを使うにあたってレスポンスとして文字列ではなくArrayBufferとしてデータを取得する必要があるため、responseType: "arraybuffer"を指定しています。

const jar = new CookieJar();
const client = wrapper(axios.create({ jar }));
const result = await client.get(url, {
  maxRedirects: 10,
  responseType: "arraybuffer",
});

実行した結果、無事エラーがでることなくレスポンスを取得することに成功しました。

リダイレクトループにハマってから原因を特定するまでに結構な時間を要してしまいました。
そもそも、何が原因でPremature closeエラーが発生しているのかわからなかったためです。
みなさまも、同じような問題に遭遇した際は、クッキーの問題かどうかを考えてみると良いかもしれません。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?