drogon icon indicating copy to clipboard operation
drogon copied to clipboard

fails to respond when the data size is extra large (1M or larger)

Open yutanoma opened this issue 4 years ago • 10 comments

Describe the bug

When returning a large value from a HttpController, the server stucks into an infinite loop, showing the message below on the console. (Maybe this is a bug of trantor)

20210211 16:27:43.975639 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975643 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975649 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975652 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975657 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975660 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975666 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975669 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975674 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975677 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975683 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
20210211 16:27:43.975686 UTC 1171326 DEBUG [writeCallback] EPIPE or ECONNRESET, erron=32 - TcpConnectionImpl.cc:489
...

To Reproduce

  1. create a post request
  2. send a large size array json
  3. just return the request json
void some_controller::index(
    const HttpRequestPtr &req,
    std::function<void(const HttpResponsePtr &)> &&callback) {
  
  auto resp = HttpResponse::newHttpResponse();
  resp->setStatusCode(k200OK);
  resp->setBody(req->bodyData());

  callback(resp);
}

Desktop (please complete the following information):

  • Mac OSX 10.15.7 (Catalina)
  • clang 12.0.0

yutanoma avatar Feb 11 '21 16:02 yutanoma

Hi, I can't reproduce the issue on my MacOS (with the same version of OS and compiler), are any other conditions missed? Would you like to give me more info? Thanks.

an-tao avatar Feb 11 '21 17:02 an-tao

Are the client and the server on the same host? What is the client used to send large requests?

an-tao avatar Feb 11 '21 17:02 an-tao

The client is on localhost:8080 and the drogon server is on localhost:8081. I set the request with fetch function of javascript:

const res = await fetch(origin + urlString, {
      method: this.method,
      body: params.body ? JSON.stringify(params.body) : undefined,
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      },
      mode: 'no-cors',
      ...params.query
}).then(async r => r.json())

yutanoma avatar Feb 12 '21 01:02 yutanoma

Did u use the latest version of drogon?

an-tao avatar Feb 12 '21 02:02 an-tao

I used Postman to send requests with a 1.8M body. it works as expected.

an-tao avatar Feb 12 '21 03:02 an-tao

Did u use the latest version of drogon?

I re-installed drogon and updated to the latest version but the issue remains...

yutanoma avatar Feb 16 '21 03:02 yutanoma

When I used the cURL command, somehow the request succeeds. It seems that this problem is specific to requests from browsers.

yutanoma avatar Feb 16 '21 04:02 yutanoma

Please give me an HTML page with js code that can reproduce the issue. Thanks.

an-tao avatar Feb 16 '21 08:02 an-tao

Using no-cors with fetch doesn't allow application/json as the content type. It allows the content type header but only for application/x-www-form-urlencoded, multipart/form-data, or text/plain.

Additionally, Access-Control-Allow-Origin must come in the response from the server, not in the request payload. In a typical CORS request the request contains an Origin header. The server inspects this and decides if it wants to trust it and responds with a Access-Control-Allow-Origin header typically with a * as the value.

See: https://javascript.info/fetch-crossorigin#cors-for-safe-requests https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#supplying_request_options

spegoraro avatar Mar 19 '21 13:03 spegoraro

Just to clarify on my previous comment, there is no issue with drogon here, the issue is with the default behaviour of the fetch API.

spegoraro avatar Mar 19 '21 13:03 spegoraro