Reqwest: как отправить запрос в другой кодировке?

Хочу POST запросом оставлять сообщения на форуме. Столкнулся с тем, что нужно отправлять сообщения в кодировке windows-1251.

Встроенных методов для указания нужной кодировки я не нашёл. Попробовал воспользоваться encoding_rs, но RequestBuilder::form отказывается принимать Vec<u8>: UrlEncoded(Custom(“unsupported value”)).

Есть ещё какие-то варианты?

из гиттера:

Denis Lisov @tanriol 00:16
Похоже, что вручную - сериализовать форму, перевести в нужную кодировку, задать Content-Type и Body

2 лайка

ContentEncoding пробовал указывать? https://docs.rs/reqwest/0.8.6/reqwest/header/struct.ContentEncoding.html

Само собой, тело нужно перекодировать самостоятельно.

Я пока не разобрался как это должно работать, но похоже это не поможет.
сделал

let mime = "application/x-www-form-urlencoded; charset=utf-8"
            .parse::<mime::Mime>()
            .unwrap();
let content_type = ContentType(mime);
request.header(content_type);
RequestBuilder {
    method: Post,
    url: "https://rutracker.cr/forum/posting.php?mode=editpost&p=75679265",
    headers: {
        "Content-Type": "application/x-www-form-urlencoded; charset=utf-8"
    }
}

результат

тест

вечером попробую вручную с другой кодировкой

Не получилось, serde_urlencoded::to_string не принимает у меня Vec<u8>, а других методов для сериализации там нет. Видимо нужно кодировать чем-то ещё.

Проблему удалось решить с помощью url::form_urlencoded::byte_serialize, итоговое решение выглядит примерно так:

fn encode(vec: &[(&str, &str)]) -> String {
    let enc = |s| byte_serialize(&WINDOWS_1251.encode(s).0).collect::<String>();
    vec.iter()
        .map(|(k, v)| format!("{}={}", enc(k), enc(v)))
        .collect::<Vec<_>>()
        .join("&")
}

client
    .post(url.as_str())
    .body(encode(&[("message", "тест")])
    .header(ContentType::form_url_encoded())
    .send()?;

Количество аллокаций String оставляет желать лучшего, но ничего другого пока не придумал.

upd: После повторного изучения документации нашёлся хороший вариант

fn encode(vec: &[(&str, &str)]) -> String {
    form_urlencoded::Serializer::new(String::new())
        .custom_encoding_override(|s| WINDOWS_1251.encode(s).0)
        .extend_pairs(vec)
        .finish()
}
4 лайка