TCP Stream read POST file in Edge or Chrome browsers

Viewed 231

I modified a mini server with "use std::net::TcpListener; use std::net::TcpStream;" from the Rust Book example (https://doc.rust-lang.org/book/ch20-03-graceful-shutdown-and-cleanup.html).

This code works from Firefox browser common "form" sending a "input type='file'" with obviously "'enctype='multipart/form-data'":

let mut datax = Vec::new();
let mut el_buffer = [0; 1024];
let mut limita = 0;

loop {
    let n = stream.read(&mut el_buffer).unwrap();
    if n<1024 {
        datax.extend_from_slice(&el_buffer[..n]);
        break;
    } else {
        datax.extend_from_slice(&el_buffer[..n]);
    }

    if limita >10000 {
        break;
    }
    limita += 1;
}

I tried: read_to_end(); read_exact(); BufReader::new(&stream); let mut el_buffer = [0; 1024]; // 1, 512, 4092, 10240, 102400, 2000 etc.
I tried "n==0... break"
I tried read without loop...

The result is the same:
From Firefox read all the file and works.
From Edge, Chrome, IE, cuts the POST received and the browser loses the server connection.

2 Answers
        if n<1024 {
            datax.extend_from_slice(&el_buffer[..n]);
            break;
        } else {

Read::read() returning a number less than the full size does not mean that the end of the input has been reached. It could mean the data is not yet available (e.g. the browser has not yet sent it) or it could be for any whim of the kernel.

You should end your reading loop when read() returns zero. That is the only return value which is specified to mean “end of file”.

After much try and error, googling, try and error, googling... I found an excellent explanation and that is "read()" function is not enough to handle bytes in "stream" so I find great tool called "buf_redux" which replaces the standard tool "std::io::BufReader". I used it like this:

In "Cargo.toml":

[dependencies]  
buf_redux = "0.8.4"

In "main.rs"

    use buf_redux::BufReader;

    // ....

    let mut datax = Vec::new();
    let mut el_buffer = [0; 4096];
    
    // A 10 MBytes aprox.:
    let mut lector = BufReader::with_capacity(10240000, &mut stream);

    loop {
        let n = lector.read(&mut el_buffer).unwrap();
        println!("Bytes : {:?}", n);
        if n<4096 {
            datax.extend_from_slice(&el_buffer[..n]);
            break;
        } else {
            datax.extend_from_slice(&el_buffer[..n]);
        }
    }

I hope it helps someone

Related