はじめに
この記事は Goodpatch Advent Calendar 2019 の3日目です.
サービス開発でかかせないテストですが、テストデータの登録は数が多いと結構手間がかかったりします。
この記事では、Node.jsでテストデータを自動登録しようとしたときに詰ったポイントと、その解決の紹介をします。
やりたかったこと
Node.jsのスクリプトでローカル上の画像ファイルをmulitpart/form-data
で送信したかったので、
フロントエンドと同じaxiosを使おうとしました。
結論
最終的に動いたコードはこちらです。
const fs = require('fs')
const axios = require('axios')
const FormData = require('form-data')
const uploadImage = async ({ auth_token, imageFilePath }) => {
const form = new FormData()
const file = fs.createReadStream(imageFilePath)
form.append('image_file', file)
const config = {
headers: {
'X-AUTH-Token': auth_token,
'X-API-Token': env.API_TOKEN,
...form.getHeaders(), // ← ← ← ← ここ!!
},
}
const result = await axios.post(env.API_BASE_URL + 'api/v1/images', form, config)
}
経緯
目的
テスト用の大量のデータをフロント経由で準備するのが面倒だったので、API経由でデータを一括登録するためにNode.jsでスクリプトを作ろうとしました。
最初のコード
const fs = require('fs')
const axios = require('axios')
const FormData = require('form-data')
const uploadImage = async ({ auth_token, imageFile }) => {
const form = new FormData()
const file = fs.createReadStream(imageFile)
form.append('image_type')
form.append('image_file', file)
const config = {
headers: {
'content-type': 'multipart/form-data',
'X-AUTH-Token': auth_token,
'X-API-Token': API_TOKEN,
},
}
const result await axios.post(env.API_BASE_URL + 'api/v1/images', form, config)
}
エラー
{
"status": 500,
"statusText": "Internal Server Error"
}
なるほどわからん
どつぼにはまりました(1時間)
違いの比較
ちゃんと送信できているフロントエンドと比較するとRequest Headersがなんか違いました
Node.jsのヘッダー
{
"Content-Type": "mutlipart/form-data"
}
ブラウザが送信しているヘッダー
{
"content-type": "multipart/form-data; boundary=----WebKitFormBoundaryYtLvDL7BwH9NCRJja"
}
content-type
消してみた
自前で付けている 'content-type': 'multipart/form-data'
消してみましたが駄目。
Request が multipart/form-data
になってないことによるエラーが発生。
{
"status": 400
}
{
"Content-Type": "application/x-www-form-urlencoded"
}
調べたら情報あった
node.js axios FormData
でググったらバッチリでました。ありがたや。
要するに
FormData
が自身の送信用headerを、getHeaders関数で生成してくれるので、それ使えやオラァ!ということです。
headers: {
'X-AUTH-Token': auth_token,
'X-API-Token': env.API_TOKEN,
...form.getHeaders(), // ← ← ← ← ここ!!
},
結論
同一コードでフロント上では問題なかったので混乱しました
最初からググって調べようね(教訓)