アップロードコールバックを設定するには、OSSに送信されるアップロードリクエストに関連するコールバックパラメーターを追加するだけです。 このトピックでは、コールバックを設定する方法について説明します。
使用上の注意
次のリージョンでコールバックを設定できます。中国 (杭州) 、中国 (上海) 、中国 (青島) 、中国 (北京) 、中国 (張家口) 、中国 (フホト) 、中国 (ウランカブ) 、中国 (深セン) 、中国 (河源) 、中国 (広州) 、中国 (成都) 、中国 (香港) 、米国 (シリコンバレー) 、米国 (バージニア) 、日本 (東京) 、シンガポール、オーストラリア (シドニー) 、マレーシア (クアラルンプール) 、インドネシア (ジャカルタ) 、フィリピン (マニラ) 、インド (ムンバイ) 、ドイツ (フランクフルト) 、英国 (ロンドン) 、アラブ首長国連邦 (ドバイ) 。
PutObject、PostObject、およびCompleteMultipartUpload操作のみがコールバックをサポートしています。
コールバックリクエストのデフォルトのタイムアウト時間は5秒です。
コールバック要求が失敗した場合、コールバック要求は再試行されません。
ステップ1: コールバックパラメータを作成する
コールバックパラメーター
callbackパラメーターは、JSON形式の複数のフィールドを含むBase64-encoded文字列です。 コールバックパラメーターを作成するには、OSSがコールバックリクエストを送信するサーバーのURL (callbackUrl) と、コールバックリクエストのコンテンツ (callbackBody) を指定する必要があります。
次の表に、JSON形式のフィールドを示します。
フィールド
必須
説明
callbackUrl
必須
OSSがコールバック要求を送信するサーバーのURL。
オブジェクトをアップロードすると、OSSはPOSTメソッドを使用してコールバック要求をURLに送信します。 リクエストの本文は、callbackBodyフィールドで指定されたコンテンツです。 ほとんどの場合、URLが使用されているサーバーは
HTTP/1.1 200 OK
のレスポンスを返します。 レスポンス本文はJSON形式である必要があり、Content-Lengthレスポンスヘッダーの値は有効で、サイズが3 MB以下である必要があります。コールバックリクエストには、最大5つのURLを指定できます。 URLはセミコロン (;) で区切ります。 OSSは、成功応答が返されるまで、各URLにコールバック要求を送信します。
HTTPS URLがサポートされています。
漢字を正しく処理できるようにするには、コールバックURLをエンコードする必要があります。 たとえば、
http://example.com /Chinese.php?key=value&Chinese name=Chinese value
をhttp://example.com/%E4%B8%AD%E6%96%87.php?key=value&%E4%B8%AD%E6%96%87%E5%90%8D%E7%A7%B0=%E4%B8%AD%E6%96%87%E5%80%BC
にエンコードする必要があります。
callbackHost
任意
コールバック要求のHostヘッダーの値。 値は、ドメイン名またはIPアドレスの形式である必要があります。
このフィールドは、callbackUrlフィールドを設定した場合にのみ有効です。
callbackHostフィールドを設定しない場合、ホスト値はcallbackUrlフィールドのURLから解決され、callbackHostフィールドの値として指定されます。
callbackBody
必須
コールバック要求本文の値。 例:
key =${ object}&etag =${ etag}&my_var =${ x:my_var}
callbackBodyフィールドは、OSSシステムパラメーター、カスタムパラメーター、および定数をサポートします。
PutObjectおよびCompleteMultipart操作では、カスタムパラメーターはcallback-varパラメーターを介して渡されます。
PostObject操作では、変数はフォームフィールドを通過します。
callbackSNI
任意
コールバック要求がクライアントから開始されたときに、OSSがcallbackUrlで指定されたオリジンアドレスにServer Name Indication (SNI) を送信するかどうかを指定します。 OSSがSNIを送信するかどうかは、サーバーの構成とリージョンの要件によって異なります。 SNIは、同じIPアドレスを使用して複数のTLS/SSL証明書をホストするサーバーに推奨されます。 有効な値:
true
false (デフォルト)
説明コールバック要求がUK (ロンドン) リージョンで開始されると、callbackSNI値に関係なくSNIが送信されます。 コールバック要求がUK (ロンドン) リージョン以外のリージョンで開始されると、SNIはcallbackSNI値に基づいて送信されます。
callbackBodyType
任意
コールバック要求のContent-Typeヘッダーの値。 有効な値:
application/x-www-form-urlencoded (デフォルト)
callbackBodyTypeフィールドをapplication/x-www-form-urlencodedに設定した場合、callbackBodyフィールドの変数はURLエンコードされた値に置き換えられます。
application/json
callbackBodyTypeフィールドをapplication/jsonに設定すると、callbackBodyフィールドの変数はJSON形式の値に置き換えられます。
JSONフィールドの例:
例1 (必須フィールドとオプションフィールドを含む)
{ "callbackUrl":"172.16.XX.XX/test.php" 、"callbackHost":"oss-cn-hangzhou.aliyuncs.com" 、"callbackBody":"{\" mimeType\":${ mimeType },\" size\":${ size}}" 、"callbackBodyType":"application/json" }
例2 (必須フィールドのみを含む)
{ "callbackUrl":"172.16.XX.XX:23456/index.html" 、"callbackBody":"bucket =${ bucket}&object =${ object}&etag =${ etag}&size =${ mimeType}&imageInfo.height =${ imageInfo.height}&imageInfo.width ={ imageInfo.width}&imageInfo.width =${ image_x: $}" }
callbackBodyフィールドのシステムパラメーターを設定できます。 下表に、各パラメーターを説明します。
システムパラメーター
説明
バケット
バケットの名前です。
object
オブジェクトのフルパス。The full path of the object.
etag
オブジェクトに対して設定され、要求元に返されるETagフィールド。
size
オブジェクトのサイズ。 サイズは、CompleteMultipartUpload操作を呼び出したときのオブジェクトの合計サイズです。
mimeType
リソースタイプです。 たとえば、JPEG 画像のリソースタイプは、image/jpeg です。
imageInfo.height
画像の高さ。 このパラメータは、画像オブジェクトにのみ適用されます。 他のオブジェクトの場合、このパラメータは空のままです。
imageInfo.width
イメージの幅。 このパラメータは、画像オブジェクトにのみ適用されます。 他のオブジェクトの場合、このパラメータは空のままです。
imageInfo.format
イメージの形式。 例: JPGとPNG。 このパラメータは、画像オブジェクトにのみ適用されます。 他のオブジェクトの場合、このパラメータは空のままです。
crc64
このパラメーターの値は、オブジェクトがアップロードされた後に返されるx-oss-hash-crc64ecmaヘッダーの値と同じです。
contentMd5
このパラメーターの値は、オブジェクトがアップロードされた後に返されるContent-MD5ヘッダーの値と同じです。
重要このパラメーターは、PutObjectまたはPostObject操作を呼び出してオブジェクトをアップロードする場合にのみ必要です。
vpcId
リクエストを開始したクライアントが存在する仮想プライベートクラウド (VPC) のID。 リクエストがVPC経由で開始されない場合、このパラメーターは空のままになります。
clientIp
リクエストを開始したクライアントのIPアドレス。
reqId
開始されたリクエストのID。
operation
PutObjectやPostObjectなど、リクエストの開始に使用されるAPI操作。
カスタマイズパラメーター
callback-var パラメーターを使用してカスタムパラメーターを設定できます。 カスタムパラメーターは、キーと値のペアです。 POSTコールバック要求が開始されると、OSSは前の表のカスタムパラメーターとシステムパラメーターをPOST要求の本文に追加します。 このように、要求者はこれらのパラメータを得ることができる。
カスタムパラメーターは、コールバックパラメーターの作成と同じ方法で作成できます。 カスタムパラメーターをJSON形式で指定します。 JSON文字列は、すべてのカスタムパラメーターのキーと値のペアで構成されます。
重要カスタムパラメーターのキーは
x:
で始まり、小文字である必要があります。 そうしないと、HTTPステータスコード200が返されるかどうかにかかわらず、システムはカスタムパラメーターに有効な値を割り当てることができません。たとえば、
x:var1
とx:var2
という名前の2つのカスタムパラメーターを設定します。 x:var1の値はvalue1であり、x:var2の値はvalue2である。 次のJSON文字列が作成されます。{ "x:var1":"value1" 、"x:var2":"value2" }
手順2: コールバック要求の設定
OSSが送信するリクエストにcallbackパラメーターとcallback-varパラメーターを追加するには、Base64を使用して前の手順で作成したJSON文字列をエンコードし、次のいずれかの方法を使用してリクエストにパラメーターを追加する必要があります。
URLにパラメーターを追加する
URLにパラメーターを追加する場合、callback
パラメーターは必須で、callback-var
パラメーターはオプションです。 リクエストにcallback
またはcallback-var
パラメーターが含まれている場合、署名を計算するときにCanonicalizedResourceのサブリソースとしてcallbackまたはcallback-varパラメーターを使用する必要があります。 詳細については、「CanonicalizedResourceの作成」をご参照ください。
PUT /test.txt?OSSAccessKeyId=LTAI5t7h6SgiLSga ****&署名=vjbyPxybdZaNmGa % 2ByT272YEAiv ****&Expires=1682484377&callback-var=eyJ4Om15X3ZhciI6ImZvci1jYWxsYmFjay10ZXN0 ****&callback=eyJjYWxsYmFja1VybCI6IjEyMS40My4xMTMuODoyMzQ1Ni9pbmRleC5odG1sIiwgICJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mZXRhZz0ke2V0YWd9JnNpemU9JHtzaXplfSZtaW1lVHlwZT0ke21pbWVUeXBlfSZpbWFnZUluZm8uaGVpZ2h0PSR7aW1hZ2VJbmZvLmhlaWdodH0maW1hZ2VJbmZvLndpZHRoPSR7aW1hZ2VJbmZvLndpZHRofSZpbWFnZUluZm8uZm9ybWF0PSR7aW1hZ2VJbmZvLmZvcm1hdH0mbXlfdmFyPSR7eDpteV92YXJ9 **** HTTP/1.1
ホスト: callback-test.oss-cn-hangzhou.aliyuncs.com
日付: 4月26日水2023 03:46:17 GMT
コンテンツ-長さ: 5
Content-Type: text/plain
パラメーターをヘッダーとしてリクエストに追加します。
x-oss-callback
またはx-oss-callback-var
ヘッダーをリクエストに追加します。 署名を計算するために、x-oss-callback-varおよびx-oss-callbackヘッダーがCanonicalizedOSSHeadersに含まれています。 例:
PUT /test.txt HTTP/1.1
ホスト: callback-test.oss-test.aliyun-inc.com
Accept-Encoding: ID
コンテンツ-長さ: 5
x-oss-callback-var: eyJ4Om15X3ZhciI6ImZvci1jYWxsYmFjay10ZXN0 ****
ユーザーエージェント: aliyun-sdk-python/0.4.0 (Linux/2.6.32-220.23.2.ali1089.el5.x86_64/x86_64;2.5.4)
x-oss-callback: eyJjYWxsYmFja1 **** 4x
ホスト: callback-test.oss-test.aliyun-inc.com
期待: 100-続行
日付: 4月26日水2023 03:46:17 GMT
Content-Type: text/plain
承認: OSS mlepou3zr4u ****:5a74vhd4UXpmyuudV14Kaen5 ****
テスト
POSTリクエストの本文のフォームフィールドにパラメーターを追加します。
PostObject操作を呼び出してオブジェクトをアップロードするときに、このメソッドのみを使用してコールバックパラメーターを設定できます。
POSTメソッドを使用してオブジェクトをアップロードするときにコールバックパラメーターを追加する場合は、別のフォームフィールドを使用してコールバックパラメーターを追加します。 例:
-- 9431149156168 Content-Disposition: フォームデータ; name="callback" eyJjYWxsYmFja1VybCI6IjEwLj **** 4xN
各カスタムパラメータは異なるフォームフィールドを使用します。 callback-varパラメーターを既存のフォームフィールドに追加することはできません。 個別のフォームフィールドを使用して、各カスタムパラメーターを追加する必要があります。 カスタムパラメーター用に設定できるJSONフィールドの例:
{ "x:var1":"value1" 、"x:var2":"value2" }
POSTリクエストのフォームフィールドの例:
-- 9431149156168 Content-Disposition: フォームデータ; name="callback" eyJjYWxsYmFja1VybCI6IjEwLj **** 4xN -- 9431149156168 Content-Disposition: form-data; name="x:var1" value1 -- 9431149156168 Content-Disposition: form-data; name="x:var2" value2
ポリシーにコールバック条件を追加できます。 ポリシーにコールバック条件を追加しない場合、アップロードのコールバックパラメーターは検証されません。 例:
{ "expiration": "2021-12-01T12:00:00.000Z" 、 "conditions": [ {"bucket": "johnsmith" }, {"callback": "eyJjYWxsYmFja1V **** 4My"} 、 ["starts-with", "$key", "user/eric/"], ] }
ステップ3: コールバック要求を開始する
オブジェクトをアップロードすると、リクエスト内のcallbackパラメーターとcallback-varパラメーターに指定したコンテンツが、POSTメソッドを使用してアプリケーションサーバーに送信されます。 例:
POST /index.html HTTP/1.0
ホスト: 172.16.XX.XX
接続: 閉じる
コンテンツ-長さ: 181
コンテンツタイプ: application/x-www-form-urlencoded
ユーザーエージェント: http-client/0.0.1
bucket=callback-test&object=test.txt&etag=D8E8FCA2DC0F896FD7CB4CB0031BA249&size=5&mimeType=text % 2Fplain&imageInfo.height=&imageInfo.width=&imageInfo.format=&x:var1=for-callback-test
ステップ4 (オプション): コールバック要求に署名する
リクエストにコールバックパラメーターを設定すると、OSSはPOSTメソッドを使用して、指定されたコールバックURLに基づいてコールバックリクエストをアプリケーションサーバーに送信します。 アプリケーションサーバーによって受信されたコールバック要求がOSSによって開始されたかどうかを確認するには、コールバック要求に署名します。
署名検証はオプションです。 ビジネス要件に基づいて署名検証を実行するかどうかを指定できます。
ステップ1: 署名を生成する
署名の生成方法
OSSはRSA暗号化アルゴリズムを使用してコールバック要求に署名します。
authorization = base64_encode(rsa_sign(private_key, url_decode(path) + query_string + '\n' + body, md5))
説明上記のコードでは、private_keyは秘密鍵、pathはコールバック要求に含まれるリソースパス、query_stringはクエリ文字列、bodyはコールバック要求のメッセージ本文を指定します。
署名を生成する手順
署名するコールバック文字列を取得します。 文字列は、URL、元のクエリ文字列、キャリッジリターン、およびコールバックメッセージ本文をデコードして取得したリソースパスで構成されます。
RSA暗号化アルゴリズムを使用してコールバック文字列に署名し、秘密鍵を使用して署名文字列を暗号化します。 署名に使用されるハッシュ関数はMD5です。
Base64を使用して署名された結果をエンコードし、最終署名を取得します。 次に、コールバック要求のAuthorizationヘッダーに署名を追加します。
例:
POST /index.php?id=1&index=2 HTTP/1.0 ホスト: 172.16.XX.XX 接続: 閉じる コンテンツ-長さ: 18 承認: kKQeGTRccDKyHB3H9vF + xYMSrmhMZj ****/kdD1ktNVgbWEfYTQG0G2SU/RaHBovRCE8OkQDjC3uG33esH2t **** コンテンツタイプ: application/x-www-form-urlencoded ユーザーエージェント: http-client/0.0.1 x-oss-pub-key-url: aHR0cDovL2dvc3NwdWJsaWMuYWxpY2RuLmNvbS9jYWxsYmFja19wdWJfa2V5X3YxLnsr **** bucket=examplebucket
上記のコードでは、pathは
/index.php
に設定され、query_stringは? id=1&index=2
で、本文はbucket=examplebucket
に設定されています。 最終的な署名はkKQeGTRccDKyHB3H9vF xYMSrmhMZjzzl2/kdD1ktNVgbWEfYTQG0G2SU/RaHBovRCE8OkQDjC3uG33esH2t ****
です。
ステップ2: 署名を確認する
署名の検証方法
次のサンプルコードは、アプリケーションサーバーを使用して署名を検証する方法の例を示しています。
Result = rsa_verify(public_key, md5(url_decode(path) + query_string + '\n' + body), base64_decode(authorization))
public_keyは公開キーを指定し、承認はコールバック要求ヘッダーに含める署名を指定します。
署名を検証する手順
コールバック要求の
x-oss-pub-key-url
ヘッダーには、公開鍵のBase64-encoded URLが格納されます。 Base64-encoded URLをデコードして公開鍵を取得します。public_key = urlopen(base64_decode(x-oss-pub-key-urlヘッダー値))
たとえば、Base64で
aHR0cDovL2dvc3NwdWJsaWMuYWxpY2RuLmNvbS9jYWxsYmFja19wdWJfa2V5X3YxLnBlbQ==
をデコードして公開鍵のURLを取得します。 デコードされた URL はhttp://gosspublic.alicdn.com/callback_pub_key_v1.pem
です。説明ossが発行するpublic_keyフィールドの
x-OSS-pub-key-url
ヘッダーの値は、http://gosspublic.alicdn.com/
またはhttps://gosspublic.alicdn.com/
で始まる必要があります。Base64でデコードされた署名を取得します。
signature = base64_decode (認証ヘッダー値)
コールバック要求が署名された後に文字列を取得するのと同じ手順を実行して、署名する文字列を取得します。
sign_str = url_decode (パス) + query_string + '\n' + body
署名を検証します。
result = rsa_verify(public_key, md5(sign_str), signature)
例:
次のコードは、アプリケーションサーバーが署名を検証する方法の例を示しています。 OSS SDK for Pythonでコードを実行する前に、M2Cryptoライブラリをインストールします。
httplibのインポート インポートbase64 md5のインポート urllib2のインポート BaseHTTPequestHandler、HTTPServerのインポートから M2CryptoからRSAをインポート M2CryptoからBIOをインポート def get_local_ip(): 試してみてください。 csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) csock.connect(('8.8.8.8', 80)) (addr, port) = csock.getsockname() csock.close() return addr except socket.error: "" を返す クラスMyHTTPRequestHandler(BaseHTTPRequestHandler): ''' def log_message(self, format, *args): リターン ''' def do_POST(self): #get public key pub_key_url = '' 試してみてください。 pub_key_url_base64 = self.headers['x-oss-pub-key-url'] pub_key_url = pub_key_url_base64.decode('base64') if not pub_key_url.startswith("http://gosspublic.alicdn.com/") and not pub_key_url.startswith("https://gosspublic.alicdn.com/"): self.send_response(400) self.end_headers() リターン url_reader = urllib2.urlopen(pub_key_url) #you can cache it pub_key = url_reader.read() except: print 'pub_key_url : ' + pub_key_url print 'Get pub key failed!' self.send_response(400) self.end_headers() リターン #get authorization authorization_base64 = self.headers['authorization'] authorization = authorization_base64.decode('base64') #get callback body content_length = self.headers['content-length'] callback_body = self.rfile.read(int(content_length)) #compose authorization string auth_str = '' pos = self.path.find('?') if -1 == pos: auth_str = urllib2.unquote(self.path) + '\n' + callback_body else: auth_str = urllib2.unquote(self.path[0:pos]) + self.path[pos:] + '\n' + callback_body print auth_str #verify authorization auth_md5 = md5.new(auth_str).digest() bio = BIO.MemoryBuffer(pub_key) rsa_pub = RSA.load_pub_key_bio(bio) 試してみてください。 result = rsa_pub.verify(auth_md5, authorization, 'md5') except: result = False if not result: print 'Authorization verify failed!' print 'Public key : %s' % (pub_key) print 'Auth string : %s' % (auth_str) self.send_response(400) self.end_headers() リターン #do something according to callback_body #response to OSS resp_body = '{"Status":"OK"}' self.send_response(200) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(resp_body))) self.end_headers() self.wfile.write(resp_body) クラスMyHTTPServer(HTTPServer): def __init__(self, host, port): HTTPServer.__init__(self, (host, port), MyHTTPRequestHandler) if '__main__' == __name ___: server_ip = get_local_ip() server_port = 23451 server = MyHTTPServer(server_ip, server_port) server.serve_forever()
次の表に、他のプログラミング言語でサーバー上の署名を検証するために使用できるコードを示します。
SDKプログラミング言語
説明
Java
ダウンロードリンク: OSS SDK for Java
実行方法: パッケージを解凍し、
java -jar oss-callback-server-demo.jar 9000
を実行します。 ポート番号は9000です。 別のポート番号を指定できます。
Python
ダウンロードリンク: OSS SDK for Python
実行方法: パッケージを解凍し、
python callback_app_server.py
を実行します。 コードを実行する前に、RSA依存関係をインストールします。
Go
ダウンロードリンク: OSS SDK for Go
実行方法: パッケージを解凍し、README.mdの指示に従います。
PHP
ダウンロードリンク: OSS SDK for PHP
実行方法: コードをApache環境にデプロイして、コード内の特定のヘッダーが依存関係として環境を使用できるようにします。 環境に基づいてサンプルコードを変更できます。
.NET
ダウンロードリンク: OSS SDK for。NET
実行方法: パッケージを解凍し、
README.md
の指示に従います。
Node.js
ダウンロードリンク: OSS SDK for Node.js
実行方法: パッケージを解凍し、
node example.js
を実行します。
Ruby
ダウンロードリンク: OSS SDK for Ruby
実行方法:ruby aliyun_oss_callback_server.rb を実行します。
ステップ5: コールバック結果を返す
アプリケーションサーバーはOSSに応答を返します。 次の例は、コールバック要求に対して返される応答を示しています。
HTTP/1.0 200 OK
サーバー: BaseHTTP/0.3 Python/2.7.6
日付: 9月14日月曜日2015 12:37:27 GMT
Content-Type: application/json
コンテンツ-長さ: 9
{"a":"b"}
アプリケーションサーバーからOSSに返されるレスポンスには、Content-Lengthヘッダーが含まれている必要があります。 レスポンスボディのサイズは1 MBを超えることはできません。
ステップ6: アップロード結果を返す
OSSは、アプリケーションサーバーによって返された情報を要求元に返します。
返されたレスポンスの例を次に示します。
HTTP/1.1 200 OK
日付: 9月14日月曜日2015 12:37:27 GMT
Content-Type: application/json
コンテンツ-長さ: 9
接続: キープアライブ
ETag: "D8E8FCA2DC0F896FD7CB4CB0031BA249"
サーバー: AliyunOSS
x-oss-bucket-version: 1442231779
x-oss-request-id: 55F6BF87207FB30F2640C548
{"a":"b"}
CompleteMultipartUpload
リクエストのレスポンスボディには、XML形式のデータなどのコンテンツが含まれています。 アップロードコールバック機能を使用すると、{"a":"b"}
などの元の本文コンテンツが上書きされます。
エラーコード
エラーコード | HTTPステータスコード | 説明 |
InvalidArgument | 400 | callbackまたはcallback-varパラメーターの値は、次のいずれかの理由で無効です。
|
CallbackFailed | 203 | オブジェクトはOSSにアップロードされますが、コールバックは失敗します。 コールバックの失敗は、OSSが期待されるコールバック応答を受信しないことを示します。 失敗は、アプリケーションサーバーがコールバック要求を受信しないことを示すものではありません。 たとえば、アプリケーションサーバーから返される応答がJSON形式でない場合、コールバックの失敗が発生します。 |
よくある質問
オブジェクトのアップロードに失敗した場合、OSSはアプリケーションサーバーにコールバック要求を送信しますか。
いいえ。 OSSは、オブジェクトがアップロードされた場合にのみ、コールバック要求をアプリケーションサーバーに送信します。 オブジェクトのアップロードに失敗した場合、OSSはコールバック要求をアプリケーションサーバーに送信せず、エラーメッセージをアプリケーションサーバーに返します。
"Response body is not valid json format" エラーメッセージが返された場合はどうすればよいですか?
リクエストの処理中にアプリケーションサーバーが例外をスローしたため、エラーメッセージが返されます。 この場合、OSSに返されるレスポンス本文はJSON形式ではありません。 次の図は、このエラーが発生したときにOSSに返されるレスポンスを示しています。
解決策:
次のコマンドを実行してコンテンツを確認します。
curl -d "<コンテンツ>" <CallbackServerURL> -v
パケットをキャプチャしてコンテンツを確認します。
WindowsでWiresharkツールを使用するか、Linuxでtcpdumpコマンドを実行してパケットをキャプチャすることを推奨します。
コールバックサーバーからOSSに返されるレスポンスの本文には、BOMヘッダーが含まれています。
このエラーは、OSS SDK for PHPを使用して作成されたアプリケーションサーバーでよく発生します。 OSS SDK for PHPはBOMヘッダーを返します。 その結果、OSSは、JSON形式ではないレスポンス本文でさらに3バイトを受け取ります。 次の図は、ef、bb、bfバイトがレスポンスボディの追加バイトであることを示しています。
解決策: アプリケーションサーバーからOSSに返されるレスポンス本文からBOMヘッダーを削除します。