background
When the new project was launched, I found a strange BUG that the Request interface had a very small probability of returning 400 Bad Requests. I got the parameters of the logged Request and tested the Request interface in POSTMAN, and found that it could respond normally.
The screening process
- First, the server responds properly
400 Bad Request
To troubleshoot interface faults.
- The log is detected during log comparison
{
"hello":"world"
}Copy the code
The interface can respond to service data properly.
{
"hello":"world"."kw":"I am brother Eight."
}Copy the code
The interface returns an error of 400, and the interface request is post JSON, so the code is reviewed. It was found that content-Length was set when the request was sent. In the case of Chinese characters, the interface returned 400, and the cause was located. The request pseudocode is shown below
let param = {
"hello":"world"."kw":"I am brother Eight."
}
let _options = {
headers: {
'Content-Type': 'application/json'.'Content-Length': JSON.stringify(param).length
},
url: url,
method: 'POST',
json: true,
time: true,
timeout: 5 * 1000,
body: param
}
return new Promise((resolve,reject)=>{
request(_options,(error, response, body)=>{
///XXXX
])
})Copy the code
The results of the analysis
The content-Length header tells the browser the size of the body in the HTTP message. This size includes Content encoding, such as gzip compressed files, and content-Length is the compressed size (which is important for writing servers). Unless block encoding is used, the Content-Length header is required for packets with entity bodies. The content-Length header is used to detect packet truncation caused by a server crash and properly fragment multiple packets sharing a persistent connection.
Second, why request parameters with Chinese characters return 400, because Content-Length counts the number of bytes of the request parameter, not the number of characters. Json.stringify (param).length returns the number of characters. In the case of Chinese characters
console.log('Eight brother'.length) //3, i.e. 3 charactersCopy the code
console.log(Buffer.byteLength('Eight brother'.'utf8')); //9, utF-8 encoding, a Chinese character is stored in 3 bytesCopy the code
As a result, the content-Length received by the interface layer is smaller than the actual byte Length, so the data cannot be properly parsed and 400 Bad Requests are returned. Set content-Length to buffer.bytelength (json.stringify (param),’utf8′)