0
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?

Nest.jsで「UnsupportedMediaTypeError: unsupported charset "ASCII"」の対策

Posted at

問題の発生方法

タイトルの通り文字コードをasciiで指定したリクエストを受けた際に発生したので、調査したところ以下のリクエストヘッダーでPOSTリクエストしたところ再現することができました

Content-Type: application/json charset=ascii

例外発生箇所

エラー発生時のスタックトレースでbody-parserであることは理解していたのですが、実際にどのような処理が行われているのか確認したところ、以下の通りでした。

    // assert charset per RFC 7159 sec 8.1
    var charset = getCharset(req) || 'utf-8'
    if (charset.substr(0, 4) !== 'utf-') {
      debug('invalid charset')
      next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
        charset: charset,
        type: 'charset.unsupported'
      }))
      return
    }

ちなみに、ソースコードにはRFC7159と記載されていますが確認したところ既に廃止されて、RFC8259に置き換わっていました。
ざっくり内容を見たけど、JSONは基本的にutf-8を使用する必要があるため、ライブラリでエラーにしてそうです。(基本的にと書いたのは以前は指定なかった感じなので)

対策方法

Nest.jsの例外フィルターにhttp-errorsパッケージのHttpErrorクラスを追加してハンドリングするようにします。

import { Catch, ExceptionFilter, ArgumentsHost, HttpException } from '@nestjs/common'
import { HttpError } from 'http-errors' // http-errorsの例外クラスをインポート

@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp()
    const response = ctx.getResponse()
    const request = ctx.getRequest()

    let status: number
    let message: string

    if (exception instanceof HttpException) {
      // Nest.jsのHttpExceptionをハンドリング
      status = exception.getStatus()
      message = exception.getResponse() as string | object
    } else if (exception instanceof HttpError) {
      // http-errorsのHttpErrorをハンドリング
      status = exception.statusCode || 500
      message = exception.message
    } else {
      // その他の例外をハンドリング
      status = 500
      message = 'Internal Server Error'
    }

    // (ここから先は省略) 
    // 監視用のログ出力、エラーレスポンス返却など
  }
}

限定的に対策するなら、UnsupportedMediaTypeクラスでハンドリングするのもありです

import { HttpError } from 'http-errors' 
// ↓に書き換え
import { UnsupportedMediaType } from "http-errors"

最後に

この問題はNest.jsというよりjsonデータを受け付ける際にbody-parserからの例外をハンドリングできていない場合に発生するので、Expressを利用している場合も発生すると考えられます。

本来、こんな通信をしてくることは無いと思うので対応は必須ではありませんが、ログ監視を考えると正しくハンドリングしておいた方が良いので、関わっているプロジェクトでも心当たりあれば再現確認&対策検討をしてみてください。

参考サイト

0
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
0
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?