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 properly400 Bad RequestTo 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′)