OSS upload callbacks automatically notify your application server after an object is successfully uploaded, enabling subsequent processing.
Limitations
Region availability
The callback feature is supported in the following regions: China (Hangzhou), China (Shanghai), China (Qingdao), China (Beijing), China (Zhangjiakou), China (Hohhot), China (Ulanqab), China (Shenzhen), China (Heyuan), China (Guangzhou), China (Chengdu), China (Hong Kong), US (Silicon Valley), US (Virginia), Japan (Tokyo), Singapore, Malaysia (Kuala Lumpur), Indonesia (Jakarta), Philippines (Manila), Germany (Frankfurt), UK (London), and UAE (Dubai).
Callback behavior
A callback request must receive a response within 5 seconds. Otherwise, the callback fails.
A failed callback does not affect the success of the object upload.
OSS does not automatically retry failed callbacks.
Supported operations
You can configure callbacks for the PutObject, PostObject, and CompleteMultipartUpload operations. The file upload manager and presigned URLs in V2 SDKs, which build on these basic operations, also support callbacks.
How it works
The OSS callback process includes the following steps:
The client uploads an object with callback parameters
When uploading an object, the client must include the
callbackparameter to specify the application server's URL and the content of the callback request. To pass custom variables, you can also include the optionalcallback-varparameter.OSS stores the object and sends a callback request
After the object is successfully uploaded, OSS sends a POST request to the specified callback URL. The request includes object information, such as the bucket, object, size, and etag, and any custom parameters.
The application server processes the callback and sends a response
After receiving the callback request, the application server processes it, optionally verifies the request signature for security, and returns a JSON response within 5 seconds. An HTTP status code of 200 indicates success. Any other status code indicates failure.
OSS returns the upload result
After receiving a successful response from the application server, OSS forwards the response to the client as the final upload result.
Implementation
Debugging an upload callback involves two parts: the client-side upload and the server-side callback processing. Debug the client-side implementation first, then the application server. After both parts work independently, perform a full end-to-end test.
Client-side implementation
For a quicker implementation, refer to the sample code provided in the SDKs.
To trigger an automatic OSS callback after an object is uploaded, include the callback parameter and the optional callback-var parameter in your upload request.
Construct the
callbackparameter.This parameter defines the application server URL and the request body format. It must be structured as a JSON object and then Base64-encoded.
Minimal configuration example:
{ "callbackUrl":"http://oss-demo.aliyuncs.com:23450", "callbackBody":"bucket=${bucket}&object=${object}&my_var=${x:my_var}" }In this example:
callbackUrl: The address of the application server. You must set this parameter to the actual address. This topic useshttp://oss-demo.aliyuncs.com:23450as an example.callbackBody: The content of the callback request body. You can use placeholders to dynamically include upload information, such as${bucket}for the bucket name,${object}for the full file path, and${x:xxx}to reference custom variables. OSS replaces these placeholders with actual values during the callback. For more information about supported system parameters, see System parameters supported by callbackBody.
Advanced configuration example:
{ "callbackUrl":"http://oss-demo.aliyuncs.com:23450", "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"bucket=${bucket}&object=${object}&my_var=${x:my_var}", "callbackBodyType":"application/x-www-form-urlencoded", "callbackSNI":false }For more information about the fields, see Callback parameter.
Construct the
callback-varparameter (Optional)ImportantThe callback-var parameter must be in JSON format. The key for each custom parameter must start with x: and contain only lowercase letters, for example,
x:uid.Use this parameter to pass custom business information, such as a user ID or an order number, to your application server. Example:
{ "x:uid": "12345", "x:order_id": "67890" }The
callback-varparameter must be used with thecallbackBodyparameter. For the custom variables in the preceding example (uidandorder_id), reference them incallbackBodyby using the${x:xxx}placeholder. Example:{ "callbackUrl": "http://oss-demo.aliyuncs.com:23450", "callbackBody": "uid=${x:uid}&order=${x:order_id}" }When the callback is triggered, OSS sends the following content, assuming
callbackBodyTypeis set toapplication/x-www-form-urlencoded:uid=12345&order=67890Base64-encode the
callbackandcallback-varparameters.Example:
callbackparameter encodingOriginal
callbackparameter:{ "callbackUrl": "http://oss-demo.aliyuncs.com:23450", "callbackHost": "your.callback.com", "callbackBody": "bucket=${bucket}&object=${object}&uid=${x:uid}&order=${x:order_id}", "callbackBodyType": "application/x-www-form-urlencoded", "callbackSNI": false }Result after Base64 encoding:
eyJjYWxsYmFja0hvc3QiOiAieW91ci5jYWxsYmFjay5jb20iLCAiY2FsbGJhY2tVcmwiOiAiaHR0cDovL29zcy1kZW1vLmFsaXl1bmNzLmNvbToyMzQ1MCIsICJjYWxsYmFja0JvZHkiOiAiYnVja2V0PSR7YnVja2V0fSZvYmplY3Q9JHtvYmplY3R9JnVpZD0ke3g6dWlkfSZvcmRlcj0ke3g6b3JkZXJfaWR9IiwgImNhbGxiYWNrQm9keVR5cGUiOiAiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIiwgImNhbGxiYWNrU05JIjogZmFsc2V9Example:
callback-varparameter encodingOriginal
callback-varparameter:{ "x:uid": "12345", "x:order_id": "67890" }Result after Base64 encoding:
eyJ4OnVpZCI6ICIxMjM0NSIsICJ4Om9yZGVyX2lkIjogIjY3ODkwIn0=
Add the encoded parameters to the request.
After you encode the parameters, you can pass them to OSS in one of the following ways.
Header (Recommended)
This method is suitable for uploads from an SDK or backend code. It provides high security and is the recommended method. You can pass callback parameters by setting the
x-oss-callbackandx-oss-callback-varHTTP header fields.x-oss-callback: The Base64-encodedcallbackparameter.x-oss-callback-var(Optional): The Base64-encodedcallback-varparameter.
Note: When you calculate the request signature, these two parameters must be included in the canonical headers to ensure the request is valid.
Example: Pass callback parameters in the header
PUT /your_object HTTP/1.1 Host: callback-test.oss-test.aliyun-inc.com Accept-Encoding: identity Content-Length: 5 x-oss-callback-var: eyJ4OnVpZCI6ICIxMjM0NSIsICJ4Om9yZGVyX2lkIjogIjY3ODkwIn0= User-Agent: 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: eyJjYWxsYmFja0hvc3QiOiAieW91ci5jYWxsYmFjay5jb20iLCAiY2FsbGJhY2tVcmwiOiAiaHR0cDovL29zcy1kZW1vLmFsaXl1bmNzLmNvbToyMzQ1MCIsICJjYWxsYmFja0JvZHkiOiAiYnVja2V0PSR7YnVja2V0fSZvYmplY3Q9JHtvYmplY3R9JnVpZD0ke3g6dWlkfSZvcmRlcj0ke3g6b3JkZXJfaWR9IiwgImNhbGxiYWNrQm9keVR5cGUiOiAiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIiwgImNhbGxiYWNrU05JIjogZmFsc2V9 Host: callback-test.oss-test.aliyun-inc.com Expect: 100-Continue Date: Wed, 26 Apr 2023 03:46:17 GMT Content-Type: text/plain Authorization: OSS qn6q**************:77Dv**************** TestPOST request body
This method applies only to PostObject uploads. Callback parameters must be passed as form fields in the body of the POST request.
callbackparameter: Pass this parameter as a separate form field. The value is the Base64-encoded JSON configuration.--9431149156168 Content-Disposition: form-data; name="callback" eyJjYWxsYmFja0hvc3QiOiAieW91ci5jYWxsYmFjay5jb20iLCAiY2FsbGJhY2tVcmwiOiAiaHR0cDovL29zcy1kZW1vLmFsaXl1bmNzLmNvbToyMzQ1MCIsICJjYWxsYmFja0JvZHkiOiAiYnVja2V0PSR7YnVja2V0fSZvYmplY3Q9JHtvYmplY3R9JnVpZD0ke3g6dWlkfSZvcmRlcj0ke3g6b3JkZXJfaWR9IiwgImNhbGxiYWNrQm9keVR5cGUiOiAiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIiwgImNhbGxiYWNrU05JIjogZmFsc2V9callback-varparameter (custom variables): Each custom variable must be passed as a separate form field. You cannot encapsulate them into a singlecallback-varfield.For example, consider the custom variables
uidandorder_id:{ "x:uid": "12345", "x:order_id": "67890" }You must convert them into two separate form fields.
--9431149156168 Content-Disposition: form-data; name="x:uid" 12345 --9431149156168 Content-Disposition: form-data; name="x:order_id" 67890Verify the
callbackparameter (Optional): You can specify validation conditions for thecallbackparameter in thepolicy. If this condition is omitted, the parameter is not validated during the upload. Example:{ "expiration": "2021-12-01T12:00:00.000Z", "conditions": [ {"bucket": "examplebucket" }, {"callback": "eyJjYWxsYmFja0hvc3QiOiAieW91ci5jYWxsYmFjay5jb20iLCAiY2FsbGJhY2tVcmwiOiAiaHR0cDovL29zcy1kZW1vLmFsaXl1bmNzLmNvbToyMzQ1MCIsICJjYWxsYmFja0JvZHkiOiAiYnVja2V0PSR7YnVja2V0fSZvYmplY3Q9JHtvYmplY3R9JnVpZD0ke3g6dWlkfSZvcmRlcj0ke3g6b3JkZXJfaWR9IiwgImNhbGxiYWNrQm9keVR5cGUiOiAiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIiwgImNhbGxiYWNrU05JIjogZmFsc2V9"}, ["starts-with", "$key", "user/eric/"] ] }
URL
This method is typically used for uploading objects with a presigned URL. The Base64-encoded callback parameters are appended to the URL to enable the automatic callback. However, this method exposes callback information in the URL and poses security risks. Use it only for temporary access or in low-sensitivity scenarios.
If you choose to pass callback parameters in the URL, you must include the
callbackparameter. Thecallback-varparameter is optional. When the signature is calculated, these parameters must be included as part of the Canonical Query String. For more information, see Signature Version 4.Example:
PUT /your_object?OSSAccessKeyId=LTAI******************&Signature=vjby*************************************&Expires=1682484377&callback-var=eyJ4OnVpZCI6ICIxMjM0NSIsICJ4Om9yZGVyX2lkIjogIjY3ODkwIn0=&callback=eyJjYWxsYmFja0hvc3QiOiAieW91ci5jYWxsYmFjay5jb20iLCAiY2FsbGJhY2tVcmwiOiAiaHR0cDovL29zcy1kZW1vLmFsaXl1bmNzLmNvbToyMzQ1MCIsICJjYWxsYmFja0JvZHkiOiAiYnVja2V0PSR7YnVja2V0fSZvYmplY3Q9JHtvYmplY3R9JnVpZD0ke3g6dWlkfSZvcmRlcj0ke3g6b3JkZXJfaWR9IiwgImNhbGxiYWNrQm9keVR5cGUiOiAiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIiwgImNhbGxiYWNrU05JIjogZmFsc2V9 HTTP/1.1 Host: callback-test.oss-cn-hangzhou.aliyuncs.com Date: Wed, 26 Apr 2023 03:46:17 GMT Content-Length: 5 Content-Type: text/plain
Server-side implementation
The following section describes the server-side processing flow. For sample code in different programming languages, see Server-side sample code.
Your application server must be able to perform the following actions:
Receive POST requests from OSS
After a successful object upload, OSS automatically sends a POST request to your application server. The following sample code shows an example request:
POST /test HTTP/1.1 Host: your.callback.com Connection: close Authorization: GevnM3**********3j7AKluzWnubHSVWI4dY3VsIfUHYWnyw== Content-MD5: iKU/O/JB***ZMd8Ftg== Content-Type: application/x-www-form-urlencoded Date: Tue, 07 May 2024 03:06:13 GMT User-Agent: aliyun-oss-callback x-oss-bucket: your_bucket x-oss-pub-key-url: aHR0cHM6Ly9nb3NzcHVi**********vY2FsbGJeV92MS5wZW0= x-oss-request-id: 66399AA50*****3334673EC2 x-oss-requester: 23313******948342006 x-oss-signature-version: 1.0 x-oss-tag: CALLBACK bucket=your_bucket&object=your_object&uid=12345&order_id=67890Verify the request signature for security (Optional)
To ensure that callback requests originate from OSS, verify the request signature on your application server. For detailed instructions, see Recommended configurations.
NoteSignature verification is optional and can be enabled based on your security requirements.
Send a callback response
After your application server receives a callback request, it must send a response to OSS. The response must meet the following requirements:
The application server should return
HTTP/1.1 200 OKto indicate success.The response header must include
Content-Length.The response body supports the JSON or XML format. This topic uses JSON as an example. If you want to use the XML format, add
Content-Type: application/xmlto the response header.
For example, the application server returns
{"Status": "OK"}.Note: The Python version in this example is 2.7.6. We recommend using Python 3 for development.
HTTP/1.0 200 OK Server: BaseHTTP/0.3 Python/2.7.6 Date: Mon, 14 Sep 2015 12:37:27 GMT Content-Type: application/json Content-Length: 9 {"Status": "OK"}OSS then forwards this response to the client. Example:
HTTP/1.1 200 OK Date: Mon, 14 Sep 2015 12:37:27 GMT Content-Type: application/json Content-Length: 9 Connection: keep-alive ETag: "D8E8FCA2DC0F896FD7CB4CB0031BA249" Server: AliyunOSS x-oss-bucket-version: 1442231779 x-oss-request-id: 55F6BF87207FB30F2640C548 {"Status": "OK"}ImportantFor a
CompleteMultipartUploadrequest, if the original response body contains content (such as information in JSON format), this content is overwritten by the response from the callback when the upload callback is enabled. For example, in this case, the content is overwritten by{"Status": "OK"}.
Recommended configurations
Verify the request signature
After you configure callback parameters, OSS sends a POST callback request to the application server based on the specified callbackUrl. To ensure that the request originates from OSS, you can verify the signature of the callback request. The following steps describe the verification process.
How OSS generates the signature
OSS uses the RSA asymmetric encryption algorithm with an MD5 hash to generate a signature for the request content. The signature is then included in the
authorizationfield of the request header.The signature is calculated by using the following formula:
authorization = base64_encode(rsa_sign(private_key, url_decode(path) + query_string + '\n' + body, md5))NoteIn this formula,
private_keyis the private key,pathis the resource path of the callback request,query_stringis the query string, andbodyis the message body of the callback.Steps to generate the signature:
Construct the string-to-sign: URL-decode the resource path and append the original query string, a newline character (
\n), and the callback message body.Generate the RSA signature: Use the private key to sign the string-to-sign. The hash function for signing is MD5.
Base64-encode the result to obtain the final signature, and include it in the
authorizationheader of the callback request.
Example of signature generation:
POST /index.php?id=1&index=2 HTTP/1.0 Host: 172.16.XX.XX Connection: close Content-Length: 18 authorization: kKQeGTRccDKyHB3H9vF+xYMSrmhMZj****/kdD1ktNVgbWEfYTQG0G2SU/RaHBovRCE8OkQDjC3uG33esH2t**** Content-Type: application/x-www-form-urlencoded User-Agent: http-client/0.0.1 x-oss-pub-key-url: aHR0cDovL2dvc3NwdWJsaWMuYWxpY2RuLmNvbS9jYWxsYmFja19wdWJfa2V5X3YxLnsr**** bucket=examplebucketThe path is
/index.php, the query_string is?id=1&index=2, the body isbucket=examplebucket, and the resulting signature iskKQeGTRccDKyHB3H9vF+xYMSrmhMZjzzl2/kdD1ktNVgbWEfYTQG0G2SU/RaHBovRCE8OkQDjC3uG33esH2t****.
The callback server verifies the signature
Your application server must verify the signature of the request from OSS to confirm its authenticity. The verification process is as follows:
Obtain the public key:
Get the Base64-encoded public key URL from the
x-oss-pub-key-urlfield in the request header and decode it.public_key = urlopen(base64_decode(value of the x-oss-pub-key-url header))Example value before decoding:
aHR0cDovL2dvc3NwdWJsaWMuYWxpY2RuLmNvbS9jYWxsYmFja19wdWJfa2V5X3YxLnBlbQ==After decoding:
http://gosspublic.alicdn.com/callback_pub_key_v1.pemNoteThe public key URL must start with
http://gosspublic.alicdn.com/orhttps://gosspublic.alicdn.com/. Because the content at the public key URL does not change, we recommend that you cache the public key to avoid service disruptions caused by network fluctuations.Decode the signature.
Get the signature from the
authorizationfield of the request header and Base64-decode it.signature = base64_decode(value of the authorization header)Construct the string-to-verify.
Concatenate the resource path, query string, a newline character (
\n), and the callback message body in the following format:sign_str = url_decode(path) + query_string + ‘\n’ + bodyPerform signature verification.
Use the MD5 hash and the RSA public key to perform the verification.
result = rsa_verify(public_key, md5(sign_str), signature)
Signature verification example
The following Python 3 code provides an example of how to verify a signature on an application server. This example requires the M2Crypto library.
import http.client import base64 import hashlib import urllib.request import urllib.parse import socket from http.server import BaseHTTPRequestHandler, HTTPServer from M2Crypto import RSA from M2Crypto import BIO def get_local_ip(): try: 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: return "" class MyHTTPRequestHandler(BaseHTTPRequestHandler): ''' def log_message(self, format, *args): return ''' def do_POST(self): # Get the public key. pub_key_url = '' try: pub_key_url_base64 = self.headers['x-oss-pub-key-url'] pub_key_url = base64.b64decode(pub_key_url_base64).decode() 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() return url_reader = urllib.request.urlopen(pub_key_url) # You can cache the public key. We recommend caching the public key content based on the public key URL to improve performance. pub_key = url_reader.read() except Exception as e: print('pub_key_url : ' + pub_key_url) print('Get pub key failed! Error:', str(e)) self.send_response(400) self.end_headers() return # Get the signature. authorization_base64 = self.headers['authorization'] authorization = base64.b64decode(authorization_base64) # Get the callback body. content_length = self.headers['content-length'] callback_body = self.rfile.read(int(content_length)) # Construct the string for signature verification. auth_str = '' pos = self.path.find('?') if -1 == pos: auth_str = urllib.parse.unquote(self.path) + '\n' + callback_body.decode() else: auth_str = urllib.parse.unquote(self.path[0:pos]) + self.path[pos:] + '\n' + callback_body.decode() print(auth_str) # Verify the signature. auth_md5 = hashlib.md5(auth_str.encode()).digest() bio = BIO.MemoryBuffer(pub_key) rsa_pub = RSA.load_pub_key_bio(bio) try: 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() return # Perform subsequent operations based on the callback_body. # Send a 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.encode()) class MyHTTPServer(HTTPServer): def __init__(self, host, port): super().__init__((host, port), MyHTTPRequestHandler) if __name__ == '__main__': server_ip = get_local_ip() server_port = 23451 server = MyHTTPServer(server_ip, server_port) server.serve_forever()The following table provides server-side sample code for other languages.
Language
Description
Java
Download URL: Java
Execution method: Unzip the package and run
java -jar oss-callback-server-demo.jar 9000(9000 is the port number, which you can change).
Python
Download URL: Python
Unzip the package and run
python callback_app_server.py. This program requires the RSA dependency.
PHP
Download URL: PHP
To run: Deploy the script in an Apache environment. You may need to modify the example, as header retrieval in PHP can be environment-dependent.
.NET
Download URL: .NET
To run the application, decompress the package and see the
README.mdfile.
Node.js
Download URL: Node.js
To run the example, unzip the package and run
node example.js.
Ruby
Download URL: Ruby
To run:
ruby aliyun_oss_callback_server.rb
Callback parameter
The following table describes the fields of the callback parameter, which are used to configure the content and behavior of the callback request sent after a successful object upload to OSS.
Parameter | Required | Description |
callbackUrl | Yes | The URL to which OSS sends a POST callback request after the object is uploaded.
|
callbackBody | Yes | The content of the callback request body. The format must be consistent with the
The |
callbackHost | No | The value of the Host header in the callback request. The value can be a domain name or an IP address.
|
callbackSNI | No | Specifies whether to include the Server Name Indication (SNI) in the callback request. In an HTTPS request, SNI allows the server to present the correct certificate for the requested hostname. If
|
callbackBodyType | No | The Content-Type of the callback request, that is, the data format of The following types are supported:
|
System parameters supported by callbackBody
The callbackBody field of the callback parameter can reference multiple system parameters to pass information about the uploaded object in the callback request. The following table describes the supported system parameters.
Parameter | Description |
bucket | The name of the bucket. |
object | The full path of the object. |
etag | The etag of the object, which is the same as the etag value returned to the client. |
size | The size of the object. If the CompleteMultipartUpload operation is called, |
mimeType | The resource type. For example, the resource type of a JPEG image is |
imageInfo.height | The height of the image. This variable is only available for image files. |
imageInfo.width | The width of the image. This variable is only available for image files. |
imageInfo.format | The format of the image, such as JPG or PNG. This variable is only available for image files. |
crc64 | The value is the same as the value of the |
contentMd5 | The value is the same as the value of the Important This variable is available only for objects uploaded using the PutObject or PostObject operations. |
vpcId | The VPC ID of the client that sends the request. This variable is empty if the request did not originate from a VPC. |
clientIp | The IP address of the client that sends the request. |
reqId | The ID of the request. |
operation | The name of the requested operation, such as PutObject or PostObject. |
SDKs
The following table provides links to client-side implementation demos.
Simple upload (by using the PutObject operation) | Multipart upload (by using the CompleteMultipartUpload operation) | Upload using a presigned URL (by using the PutObject operation) | |
Java | |||
Python V2 | - | ||
Go V2 |
Troubleshooting
If an error occurs during the callback process, you can use the error code returned by OSS to troubleshoot the issue. Each error code corresponds to a specific cause. For callback-related error codes, see 07-CALLBACK.
FAQ
Callback on upload failure
No. OSS triggers a callback only after an object is successfully uploaded. If the upload fails, no callback is sent, and an error message is returned directly to the client.
"Response body is not valid json format" error
An exception during processing on the application server causes it to send a response body that is not in valid JSON format, as shown in the following code:
# Send a 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)Solution:
Run the following command to verify the content.
curl -d "<Content>" <CallbackServerURL> -vCapture packets to inspect the content.
On Windows, we recommend using Wireshark to capture packets. On Linux, use the tcpdump command to capture packets.
The response body that the application server returns to OSS contains a BOM header.
This error is common in PHP-based application servers. The PHP SDK returns a BOM header, which adds three extra bytes to the beginning of the response body that OSS receives. This makes the body invalid as a JSON object. In the following packet capture, the bytes
ef bb bfrepresent the BOM header.Frame 6: 448 bytes on wire (3584 bits), 448 bytes captured (3584 bits) Ethernet II, Src: Inventec_5e:4f:5c (00:8c:fa:5e:4f:5c), Dst: Inventec_5e:4b:64 (00:8c:fa:5e:4b:64) Internet Protocol Version 4, Src: 10.101.166.30, Dst: 10.101.166.53 Transmission Control Protocol, Src Port: 8083 (8083), Dst Port: 49607 (49607), Seq: 1, Ack: 518, Len: 382 Hypertext Transfer Protocol Line-based text data: text/html \357\273\277{"Status":"Ok"} 0090 64 20 48 61 74 29 0d 0a 53 65 74 2d 43 6f 6b d Hat).. Set-Cook 00a0 69 65 3a 20 50 48 50 53 45 53 53 49 44 3d 66 61 ie: PHPS ESSID=fa 00b0 74 37 33 6e 74 6c 70 68 30 6e 63 67 38 68 33 30 t73ntlph 0ncg8h30 00c0 65 6e 75 35 31 34 67 31 3b 20 48 74 74 70 4f 6e enu514g1 ; HttpOn 00d0 6c 79 0d 0a 45 78 70 69 72 65 73 3a 20 54 68 75 ly..Expi res: Thu 00e0 2c 20 31 39 20 4e 6f 76 20 31 39 38 31 20 30 38 , 19 Nov 1981 08 00f0 3a 35 32 3a 30 30 20 47 4d 54 0d 0a 43 61 63 68 :52:00 G MT..Cach 0100 65 2d 43 6f 6e 74 72 6f 6c 3a 20 6e 6f 2d 73 74 e-Contro l: no-st 0110 6f 72 65 2c 20 6e 6f 2d 63 61 63 68 65 2c 20 6d ore, no- cache, m 0120 75 73 74 2d 72 65 76 61 6c 69 64 61 74 65 2c 20 ust-reva lidate, 0130 70 6f 73 74 2d 63 68 65 63 6b 3d 30 2c 20 70 72 post-che ck=0, pr 0140 65 2d 63 68 65 63 6b 3d 30 0d 0a 50 72 61 67 6d e-check= 0..Pragm 0150 61 3a 20 6e 6f 2d 63 61 63 68 65 0d 0a 43 6f 6e a: no-ca che..Con 0160 74 65 6e 74 2d 4c 65 6e 67 74 68 3a 20 31 38 0d tent-Len gth: 18. 0170 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 63 6c 6f .Connect ion: clo 0180 73 65 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 se..Cont ent-Type 0190 3a 20 74 65 78 74 2f 68 74 6d 6c 3b 20 63 68 61 : text/h tml; cha 01a0 72 73 65 74 3d 55 54 46 2d 38 0d 0a 0d 0a ef bb rset=UTF -8..... 01b0 bf 7b 22 53 74 61 74 75 73 22 3a 22 4f 6b 22 7d .{"Statu s":"Ok"}Solution: Remove the BOM header from the response body that your application server returns to OSS.