Lambdaで構築されたAPIで返却値が大きいせいでペイロードのデータサイズ制限(6MB以上は制限に引っかかる)に引っかかってしまうとのことで、Lambda側でgzip圧縮されたデータをフロントで解凍する必要が出てきたときに、1~2日くらいハマったので備忘録。
Lambdaのペイロード制限について
API側は言語はPythonでzlibライブラリを使っていたので、フロント側も同じくzlib.jsを使うことに。
いざ、実装!!
以下の記事を参考に実装してみる。
実装中にハマった部分
①Pythonでbase64エンコードされた文字列をJavaScriptでbase64デコードすることがまずできず、はまる。。。
②デコードできるようになったが、、、zlib.jsでungzipできない。。。
Pythonでbase64エンコードされた文字列をJavaScriptでbase64デコードする
1日くらい検索したがなかなか見つけられず、、、ようやく見つけたのが以下、
NG
baseString = 'hogehoge'
encodedString = baseString.encode()
base64encodedString = base64.b64decode(encodedString)
responseString = base64encodedString.decode()
return responseString
//responseから取得したbase64エンコードされた文字列
const base64encodedString = "SGVsbG8sIHdvcmxkIQ==";
const base64decodedString = atob(base64encodedString)
記事によると、Pythonでエンコード時に ascii
指定をしてからbase64エンコードしないととJavaScriptでは正しくデコードできないとのこと。
JavaScriptはそのままで、Python側を変更
OK
baseString = 'hogehoge'
encodedString = baseString.encode('ascii')
base64encodedString = base64.b64decode(encodedString)
responseString = base64encodedString.decode('ascii')
return responseString
zlib.jsでungzipできないのでpako.jsでungzipする
なんで同じzlibなのに、、、試行錯誤の末、ライブラリを pako
変えてみた。
もともと、SessionStorageを格納する際にデータ圧縮するライブラリとしてつかっていたものでGzip解凍ができるとのことでやってみたらうまくいった。
zlibベースの高速なデータ圧縮・解凍ライブラリとのことでライセンスはMITです。
実装
import zlib
baseString = 'hogehoge'
encodedString = baseString.encode('ascii')
compressedData = zlib.compress(encodedString)
base64encodedString = base64.b64decode(compressedData)
responseString = base64encodedString.decode('ascii')
return responseString
const unescapeUnicode = (str: string) => {
return str.replace(/\\u([a-fA-F0-9]{4})/g, function(x, y) {
return String.fromCharCode(parseInt(y, 16))
})
}
const handleUnGzipData = (responseCompressed: string) => {
try {
// base64エンコードされたgzipの文字列をbase64デコード
const gzipedData = atob(responseCompressed)
// 解凍するには文字列をバイナリにする必要があるのでバイナリ変換
const gzipedDataArray = Uint8Array.from(gzipedData, c => c.charCodeAt(0))
// gzip解凍
const ungzipedData = pako.ungzip(gzipedDataArray, { to: 'string' })
// Unicodeエスケープシーケンスで日本語に戻す
const output = unescapeUnicode(ungzipedData)
// 文字列をオブジェクト変換
const responseObject = JSON.parse(output)
return responseObject
} catch (error) {
return ''
}
}
勉強になりました。