LoginSignup
3
0

More than 1 year has passed since last update.

Nuxt3 server/api で、fetchして得た画像をレスポンスする

Last updated at Posted at 2022-09-02

めちゃくちゃハマってしまった。解決したので残しておく

前提条件

  • Nuxt .. v3.0.0-rc.6
  • nitropack .. v0.4.12
  • h3 .. v0.7.13
  • ohmyfetch .. v0.4.18

# 結論

以下のようにかけばOKだった

server/api/image/[imageId].get.ts
import { send } from 'h3'

export default defineEventHandler(async (event) => {
  const { imageId } = event.context['params']

  const blob: Blob = await $fetch(`/external/api/images/${imageId}`, {
    method: 'get',
    responseType: 'blob'
  })

  await send(event, Buffer.from(Buffer.from(await blob.arrayBuffer())), blob.type)
})

勘所

$fetch は responseType によって返却する型が変わる

nuxt3 の server api にて、 $fetch は ohmyfetch のラップ関数となっている

nuxt によって型が上書きされてしまっているので、把握しづらかったが、

ohmyfetch 側の型定義を見てみると,

ohmyfetch:v0.4.18

interface ResponseMap {
    blob: Blob;
    text: string;
    arrayBuffer: ArrayBuffer;
}
declare type ResponseType = keyof ResponseMap | 'json';
declare type MappedType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType;

// ...

interface $Fetch {
    <T = any, R extends ResponseType = 'json'>(request: FetchRequest, opts?: FetchOptions<R>): Promise<MappedType<R, T>>;
    raw<T = any, R extends ResponseType = 'json'>(request: FetchRequest, opts?: FetchOptions<R>): Promise<FetchResponse<MappedType<R, T>>>;
    create(defaults: FetchOptions): $Fetch;
}

となっており、

つまり、 responseTypeblob, text, arrayBuffer なら、
それぞれ Blob, string, Arraybuffer が返却するデータの型になるのがわかる。

return せず send する

defineEventHandler の引数に指定した関数の返り値は、 nitro サーバ側で h3 モジュールの send を呼んでいる。

また、既に send 済みであれば、それをレスポンスデータとして扱ってくれる。

そのため、 レスポンスデータを return せずに、 直接 send すればよかった。

ちなみに、 nitro サーバのロジックを見た感じ、 text と json 以外のレスポンスデータを return するケースが想定されていなかった

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