Stiffstream / restinio

Cross-platform, efficient, customizable, and robust asynchronous HTTP(S)/WebSocket server C++ library with the right balance between performance and ease of use
Other
1.13k stars 92 forks source link

Empty response with the sendfile operation #164

Closed govinddanil closed 2 years ago

govinddanil commented 2 years ago

Hi,

I am trying to use the sendfile operation to send a text file, but I get an empty response. This is a minimal example of what I am doing:

restinio::run(
        restinio::on_this_thread()
          .port(8080)
          .address("localhost")
          .request_handler([](auto req) {
            return req->create_response().append_header(restinio::http_field::content_type, "text/plain; charset=utf-8").set_body(restinio::sendfile("C:/Workspace/test.txt")).done();
          }));

Any help would be much appreciated. Thanks! :)

eao197 commented 2 years ago

Hi!

Try this minimal example with logging enabled:

#include <restinio/all.hpp>

int main()
{
    struct my_traits : restinio::default_single_thread_traits_t {
        using logger_t = restinio::single_threaded_ostream_logger_t;
    };

    restinio::run(
        restinio::on_this_thread<my_traits>()
            .port(8080)
            .address("localhost")
            .request_handler([](auto req) {
                return req->create_response()
                        .append_header(
                                restinio::http_field::content_type,
                                "text/plain; charset=utf-8")
                        .set_body(
                                restinio::sendfile("C:/Workspace/test.txt"))
                        .done();
            }));

    return 0;
}

and use curl -v http://localhost:8080/ to get more information about data flow.

govinddanil commented 2 years ago

Hi,

Thank you so much for the quick response! So I tried the minimal example with logging enabled and I see that the connection gets closed with 8 bytes remaining to read.

$ curl -v http://localhost:8080/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying ::1:8080...
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.75.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Length: 8
< Content-Type: text/plain; charset=utf-8
<
{ [0 bytes data]
* transfer closed with 8 bytes remaining to read
  0     8    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
* Closing connection 0
curl: (18) transfer closed with 8 bytes remaining to read

Could this be an issue with Content-length field value calculated? Edit: I checked that the file I am sending is indeed 8 bytes

eao197 commented 2 years ago

Content-Length is calculated automatically based on the size of your file.

You didn't show the log from RESTinio. It should look like this:

[2022-07-15 14:26:43.153] TRACE: starting server on 127.0.0.1:8080
[2022-07-15 14:26:43.155]  INFO: init accept #0
[2022-07-15 14:26:43.155]  INFO: server started on 127.0.0.1:8080
[2022-07-15 14:26:45.221] TRACE: accept connection from 127.0.0.1:61121 on socket #0
[2022-07-15 14:26:45.223] TRACE: [connection:1] start connection with 127.0.0.1:61121
[2022-07-15 14:26:45.223] TRACE: [connection:1] start waiting for request
[2022-07-15 14:26:45.224] TRACE: [connection:1] continue reading request
[2022-07-15 14:26:45.226] TRACE: [connection:1] received 78 bytes
[2022-07-15 14:26:45.227] TRACE: [connection:1] request received (#0): GET /
[2022-07-15 14:26:45.228] TRACE: [connection:1] append response (#0), flags: { final_parts, connection_keepalive }, write group size: 2
[2022-07-15 14:26:45.229] TRACE: [connection:1] start next write group for response (#0), size: 2
[2022-07-15 14:26:45.231] TRACE: [connection:1] start response (#0): HTTP/1.1 200 OK
[2022-07-15 14:26:45.233] TRACE: [connection:1] sending resp data, buf count: 1, total size: 103
[2022-07-15 14:26:45.234] TRACE: [connection:1] start waiting for request
[2022-07-15 14:26:45.234] TRACE: [connection:1] continue reading request
[2022-07-15 14:26:45.235] TRACE: [connection:1] outgoing data was sent: 103 bytes
[2022-07-15 14:26:45.236] TRACE: [connection:1] sending resp file data, total size: 8
[2022-07-15 14:26:45.238] TRACE: [connection:1] file data was sent: 8 bytes
[2022-07-15 14:26:45.238] TRACE: [connection:1] finishing current write group
[2022-07-15 14:26:45.240] TRACE: [connection:1] should keep alive
[2022-07-15 14:26:45.240] TRACE: [connection:1] start waiting for request
[2022-07-15 14:26:45.241] TRACE: [connection:1] skip read operation: already running
[2022-07-15 14:26:45.260] TRACE: [connection:1] EOF and no request, close connection
[2022-07-15 14:26:45.260] TRACE: [connection:1] close
[2022-07-15 14:26:45.261] TRACE: [connection:1] close: close socket
[2022-07-15 14:26:45.265] TRACE: [connection:1] close: timer canceled
[2022-07-15 14:26:45.266] TRACE: [connection:1] close: reset responses data
[2022-07-15 14:26:45.268] TRACE: [connection:1] destructor called
govinddanil commented 2 years ago

Oh yes, sorry! Here you go:

[2022-07-15 13:34:35.913] TRACE: starting server on 127.0.0.1:8080
[2022-07-15 13:34:35.913]  INFO: init accept #0
[2022-07-15 13:34:35.914]  INFO: server started on 127.0.0.1:8080
[2022-07-15 13:34:51.053] TRACE: accept connection from 127.0.0.1:55431 on socket #0
[2022-07-15 13:34:51.054] TRACE: [connection:1] start connection with 127.0.0.1:55431
[2022-07-15 13:34:51.054] TRACE: [connection:1] start waiting for request
[2022-07-15 13:34:51.054] TRACE: [connection:1] continue reading request
[2022-07-15 13:34:51.056] TRACE: [connection:1] received 78 bytes
[2022-07-15 13:34:51.056] TRACE: [connection:1] request received (#0): GET /
[2022-07-15 13:34:51.057] TRACE: [connection:1] append response (#0), flags: { final_parts, connection_keepalive }, write group size: 2
[2022-07-15 13:34:51.057] TRACE: [connection:1] start next write group for response (#0), size: 2
[2022-07-15 13:34:51.057] TRACE: [connection:1] start response (#0): HTTP/1.1 200 OK
[2022-07-15 13:34:51.057] TRACE: [connection:1] sending resp data, buf count: 1, total size: 103
[2022-07-15 13:34:51.057] TRACE: [connection:1] start waiting for request
[2022-07-15 13:34:51.057] TRACE: [connection:1] continue reading request
[2022-07-15 13:34:51.058] TRACE: [connection:1] outgoing data was sent: 103 bytes
[2022-07-15 13:34:51.058] TRACE: [connection:1] sending resp file data, total size: 8
[2022-07-15 13:34:51.059] ERROR: [connection:1] handle_current_write_ctx failed: assign: The handle is invalid.
[2022-07-15 13:34:51.059] TRACE: [connection:1] close
[2022-07-15 13:34:51.059] TRACE: [connection:1] close: close socket
[2022-07-15 13:34:51.059] TRACE: [connection:1] close: timer canceled
[2022-07-15 13:34:51.059] TRACE: [connection:1] close: reset responses data
[2022-07-15 13:34:51.059] TRACE: [connection:1] destructor called
eao197 commented 2 years ago

There is some strange thing:

[2022-07-15 13:34:51.059] ERROR: [connection:1] handle_current_write_ctx failed: assign: The handle is invalid.

It shouldn't be here.

eao197 commented 2 years ago

I can't reproduce that problem so I can't help more :( It seems that the problem somewhere here: https://github.com/Stiffstream/restinio/blob/03e69fe720c91c65b8cfe93f463dc6063ab287bd/dev/restinio/impl/connection.hpp#L1197-L1245 It also seems that Asio throws an exception with content: assign: The handle is invalid.

Which version of Asio do you use?

govind-anil commented 2 years ago

I am using Asio version 1.12.1. Thank you so much for your support :) I will try to resolve the issue and post here what I find.

eao197 commented 2 years ago

Asio 1.12.1 is a rather old version. I even don't remember when we used it. Try something newest, like 1-18-2, 1-19-2, 1-20-0, 1-21-0 or 1-22-1.

govinddanil commented 2 years ago

I updated the Restinio version to 0.6.15 and I am now using Asio version 1.21.0 and now the sendfile operation works for me with the minimal example! Thanks a lot for your support @eao197. Cheers! :D

eao197 commented 2 years ago

and now the sendfile operation works for me with the minimal example!

Glad to hear that!