httprust

the content length always 0 when using rust actix send response


I am using react pdf 9.1.0 to show the pdf in browser, now I want to make the react pdf support the partial download. The server side was using openresty, I read the pdf.js manual that told me to make the server side add partial download. Then I add the server side rust actix code like this:

    // tell the client support slice loading
    return HttpResponse::PartialContent()
        .insert_header(CacheControl(vec![CacheDirective::NoCache]))
        .append_header(("Accept-Ranges", "bytes"))
        .append_header((
            "Access-Control-Expose-Headers",
            "Accept-Ranges,Content-Range",
        ))
        .append_header(("Content-Encoding", "identity"))
        .append_header(("Content-Length", content_length))
        .content_type("application/pdf")
        .body("");

but now I found the response content length alway 0 even through I set the length. why did this happen? what should I do do fixed this issue? I have checked the variable content_length and make sure the content length is greather than 0. Should I put the content into body? And now I just want to told the client the server support paritial content loading, if the file is huge(>500MB). put the content into body did not decrease the network transfer. there is no difference about transfer the whole file.


Solution

  • I think you might have a misunderstanding of how http ranges work.

    The server cannot 'force' the client to use ranges. It can only inform the client as part of another transfer.

    In any case, the client starts the transfer.

    Case 1: Client requests a range

    If the client already includes a Range: header, then you can directly respond with:

    HTTP/2 206
    content-length: <partial size>
    accept-ranges: bytes
    content-range: bytes <range>
    

    ... and the data of the given range.

    Case 2: Client requests a GET without a range

    If the client does not include the Range: header, you must respond with the entire file. Don't worry, you don't need to load the entire >500MB into RAM, you can simply open a file stream and tell actix to stream that file to the connection.

    You can further now inform the client that you also support ranges, by adding the Accept-Ranges header to your response. This does not mean that you should send an empty response, you still need to send the entire file. The client can however cancel the download and start a partial transfer instead like in Case 1.

    Case 3: Client requests a HEADER without a range

    In order to avoid having to start/stop/restart the download as in Case 2, the client can send a HEADER request. This means the server can now respond with an Accept-Ranges: response header without having to send data. This is a performance optimization that can be triggered by the CLIENT, not the server. The server has to comply with the client's request, it cannot actively switch modes. The client has to do this.

    Actix built-in ranges support

    If you simply need to serve a file, however, be aware that NamedFile and everything based on it already supports ranges and does not require an explicit implementation.