Nuxt3で$fetchにbodyいれてGETするとエラーになる挙動をみる
Nuxt3で$fetchにbodyいれてGETするとエラーになる挙動をみる
こんにちは、合同会社Stegの@keigoです。
今回は、Nuxt3にて、$fetch
やuseFetch
にてAPIを叩く時、bodyいれてGETするとエラーになる件について書いていきます。
例えば$fetch
でbody含むgetしようとすると、以下のようなエラーメッセージになるかと思います。
Uncaught (in promise) FetchError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body. (/api/hoge)
つまり、GETではbody指定できないよ〜ということですね。
解決策
クエリパラメータなどにするか、POSTにしましょう。 取得が目的なら、getのままでクエリパラメータがよきです。
実装をみていく
cURLやpostmanなどでGET指定でbodyを含めたことがあったので、あれ?だめなんだ?になりました。
気になったので実装を見にいきました。
useFetch
Nuxt3でのuseFetchは、useAsyncDataと$fetch
をwrapしたものです。
$fetchって?
nuxtのコードを読みに行くと、
import { $fetch } from 'ofetch'
という記述がありました。つまり、$fetch
というのは、unjs/ofetchっぽいですね。
今回の記事でのGETでbodyが対応していないというのは、ofetchのほうに書いてありそうです。
unjs/ofetchの実装みる
fetch.tsにて、以下のようなコードがありました。(記事執筆時点)
if (
context.options.body &&
isPayloadMethod(context.options.method) &&
isJSONSerializable(context.options.body)
) {
// Automatically JSON stringify request bodies, when not already a string.
context.options.body =
typeof context.options.body === "string"
? context.options.body
: JSON.stringify(context.options.body);
// Set Content-Type and Accept headers to application/json by default
// for JSON serializable request bodies.
context.options.headers = new Headers(context.options.headers);
if (!context.options.headers.has("content-type")) {
context.options.headers.set("content-type", "application/json");
}
if (!context.options.headers.has("accept")) {
context.options.headers.set("accept", "application/json");
}
}
context.options.body
でbodyがありつつ、isPayloadMethod(context.options.method)
という関数がtrueを返すかどうかが今回のポイントになりそうです。
isPayloadMethod
を見に行くと、
const payloadMethods = new Set(
Object.freeze(["PATCH", "POST", "PUT", "DELETE"])
);
export function isPayloadMethod(method = "GET") {
return payloadMethods.has(method.toUpperCase());
}
こうなってました。完全にGETが省かれてますね。
ここらへんの実装から、$fetch
でGETにbodyいれるとエラー返すんだな〜と理解できました。