String::from_utf8 Error | After some update

Good day everybody!

I have an application written without any crates on my Windows 10.
After recent updates (probably 1.68.1 or previous ones) some my tests began to crash. The project was inactive so I just waited for auto solving the problem with some new update. But it didn't happen.

//the test

        //add new word
        let curl_output = Command::new("curl")
            .args(&[
                "-X",
                "POST",
                "http://localhost/words",
                "-H",
                "Content-Type: text/plain",
                "--data-binary",
                "newword\n5000\nновое слово\n",
            ])
            .output()
            .expect("Failed to execute command");
        let page_add_new = String::from_utf8(curl_output.stdout.as_slice().to_owned())
            .expect("Failed to convert to String");

assert_eq!("Word \"newword\" is added \u{1F60E}", page_add_new);
//the error message

thread '<unnamed>' panicked at 'Failed to get string: FromUtf8Error { bytes: [13, 10, 110, 101, 119, 119, 111, 114, 100, 10, 53, 48, 48, 48, 10, 208, 189, 208, 190, 208, 178, 208, 190, 208, 181, 32, 209, 129, 208, 187, 208, 190, 208
, 178, 208], error: Utf8Error { valid_up_to: 34, error_len: None } }', src\frameworks_and_drivers\message\http_request.rs:89:26
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Thread panicked, error is `Any { .. }`
thread '<unnamed>' panicked at 'Failed to get string: FromUtf8Error { bytes: [13, 10, 110, 101, 119, 119, 111, 114, 100, 10, 53, 48, 48, 48, 10, 208, 189, 208, 190, 208, 178, 208, 190, 208, 181, 32, 209, 129, 208, 187, 208, 190, 208
, 178, 208], error: Utf8Error { valid_up_to: 34, error_len: None } }', src\frameworks_and_drivers\message\http_request.rs:89:26
Thread panicked, error is `Any { .. }`
thread '<unnamed>' panicked at 'Failed to get string: FromUtf8Error { bytes: [13, 10, 110, 101, 119, 119, 111, 114, 100, 10, 55, 48, 48, 48, 10, 208, 189, 208, 190, 208, 178, 208, 190, 208, 181, 209, 129, 208, 187, 208, 190, 208, 17
8, 208], error: Utf8Error { valid_up_to: 33, error_len: None } }', src\frameworks_and_drivers\message\http_request.rs:89:26
Thread panicked, error is `Any { .. }`
test add_update_delete ... FAILED

failures:
---- add_update_delete stdout ----
thread 'add_update_delete' panicked at 'assertion failed: `(left == right)`
  left: `"Word \"newword\" is added 😎"`,
 right: `""`', tests\add_word.rs:121:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    add_update_delete

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.70s

//the code

    pub fn from_tcp_stream(tcp_stream: &mut TcpStream) -> Option<Self> {
        // Read the first line of the request to get the method and path
        let mut reader = BufReader::new(tcp_stream);
        let first_line = {
            let mut first_line = String::new();

            reader
                .read_line(&mut first_line)
                .expect("Failed to read line");
            first_line
        };
        let mut iter = first_line.split_whitespace();
        let (Some(http_method), Some(path)) = (iter.next(), iter.next()) else {
            return None;
        };

        let http_method = HttpMethod::from_value(http_method);

        let Some(http_method) = http_method else {
            return None;
        };

        //println!("{:#?} {:#?}", http_method, path);

        let mut content: Vec<String> = vec![];

        if HttpMethod::Post == http_method || HttpMethod::Put == http_method {
            // Read the headers to find the "Content-Length" header
            let mut headers = String::new();
            let mut content_length = 0;
            while reader.read_line(&mut headers).is_ok() {
                if let Some(position) = headers.find("Content-Length:") {
                    let (_, value) = headers.split_at(position + "Content-Length:".len());
                    content_length = value.trim().parse().expect("Failed to parse to integer");
                    break;
                }
            }

            // Read the body from the stream
            content = {
                if content_length > 0 {
                    let mut buffer: Vec<u8> = vec![0; content_length];

                    reader
                        .read_exact(&mut buffer)
                        .expect("Failed to read exact length");

                    //println!("{:#?}", buffer);

                    String::from_utf8(buffer)
                        .expect("Failed to get string")
                        .lines()
                        .map(|line| line.trim().to_owned())
                        .filter(|line| !line.is_empty())
                        .collect()
                } else {
                    vec![]
                }
            };
        }

        let application_request = 'block: {
            if content.is_empty() {
                break 'block None;
            }

            //println!("{:#?}", content);

            if let Some(raw_word_data) = Self::parse_content(content) {
                break 'block Some(ApplicationRequest::Word((
                    raw_word_data.0,
                    raw_word_data.1,
                    raw_word_data.2,
                )));
            }
            None
        };

        Some(Self::new(http_method, path.to_owned(), application_request))
    }

That code works before and I don't see any announced changes :neutral_face:

What is the code that actually writes the http response?

And can you try running the curl command in a terminal to see if there are any errors printed? Your current code discards stderr.

1 Like

it fails here, it doesn't go further to write the http response :wink:

I don't have such a problem in Go :smile:

The problem was that the newline symbol was not being recognized. Now I use something like

        let str = "newword
            5000
            новое слово";

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.