背景
GASで画像を投稿する際、私が確認できたサイトで、OAuth1ライブラリを使用している物は全て画像をbase64エンコードしてアップロードしています。
それはOAuth1ライブラリを用いてmultipart/form-data
で投稿しようとすると認証エラーが発生するからです。
しかしmultipart/form-data
で投稿したほうが通信量も少なければbase64エンコードする時間も節約できるので出来ればmultipart/form-data
で投稿がしたい。
そこで、なぜOAuth1ライブラリを使用すると、multipart/form-data
で投稿が出来ないのか調査しました。
原因
GASのUrlFetchApp.fetchはcontentTypeの指定が無いかつpayloadにBlobインスタンスが含まれていると自動でmultipart/form-data
フォーマットしてくれる優れものです。
が、原因はこの「contentTypeの指定が無い」の部分にあります。
OAuth1ライブラリのfetch部分の実装を見ると以下のようなコードがあります。(419行目と446行目)
if (params.payload && (!params.contentType ||
params.contentType == 'application/x-www-form-urlencoded')) {
//続く
これすなわちcontentTypeの指定が無い場合とcontentTypeがapplication/x-www-form-urlencoded
の場合の処理が同じということです。
payloadにBlobインスタンスがある場合もcontentTypeの指定が無ければapplication/x-www-form-urlencoded
と同様に処理がされて、payloadはapplication/x-www-form-urlencoded
にフォーマットがされます。
つまり、ユーザーがmultipart/form-data
でPOSTしようと思ってcontentTypeを空にしても、実際はapplication/x-www-form-urlencoded
でPOSTがされて、エラーが発生するという訳です。
対処法
OAuth1ライブラリを少し改良します。
distファイルのOAuth1.gsが統合ファイル(多分)なのでそれをGASにコピペしてください。
方法1.contentTypeが空の場合はそのままスルーさせる
貼り付けたファイルの536,563行目を以下のようにします。
-if (params.payload && (!params.contentType ||
- params.contentType == 'application/x-www-form-urlencoded'))
+if (params.payload && params.contentType == 'application/x-www-form-urlencoded')
以下のようにしてPOSTします。
service.fetch("https://upload.twitter.com/1.1/media/upload.json",{
method:"post",
payload:{
media:<Blob>
}
})
しかし、application/x-www-form-urlencoded
の場合もcontentTypeの指定が必須になるので、そこは注意してください。
方法2.contentTypeがmultipart/form-data指定の時はcontentTypeを空にする
ライブラリにはスルーさせて、UrlFetchAppにフォーマットを任せたいので、UrlFetchApp.fetchの直前にcontentTypeが特定のワードだった時にcontentTypeを削除するようにします。
params.escaping = false;
}
+ if(params.contentType==="multipart/form-data")
+ delete params.contentType
return UrlFetchApp.fetch(url, params);
以下のようにしてPOSTします
service.fetch("https://upload.twitter.com/1.1/media/upload.json",{
method:"post",
payload:{
media:<Blob>
},
contentType:"multipart/form-data"
})
こっちの場合はapplication/x-www-form-urlencoded
の場合は従来通りにcontentTypeを省略できます。
最後に
Google様のライブラリが原因なんて思ってもいませんでした。
案外疑ってみるものですね。