The crate awc formats string incorrectly?

Hi everyone,
I'm using awc and actix-web to call a url to request geographical data from it.

The correct curl command of the API is :

// Note : the below command returns a lot of data
curl -v -H "annee: 2021" -H "code_cultu: 18" -H "geom: {\"coordinates\":[[[[-0.288863182067871,48.96366660729598],[-0.299592018127441,48.95929920857614],[-0.296330451965332,48.95532595238504],[-0.282125473022461,48.950675995388366],[-0.279722213745117,48.96701938292233],[-0.288863182067871,48.96366660729598]]]],\"type\":\"MultiPolygon\"}" https://apicarto.ign.fr/api/rpg/v2

I have the following main.rs file :

use awc::Client;
use actix_web::{App, HttpResponse, HttpServer, middleware, web};
use actix_web::http::header::ContentType;
use actix_web::web::{Json, Query};
use geojson::GeoJson;
use serde::Deserialize;

#[actix_web::main]
async fn main() -> std::io::Result<()> {

    HttpServer::new(|| {
        App::new()
            // enable logger
            .wrap(middleware::Logger::default())
            .configure(init_routes)
    })
        .bind(("0.0.0.0", 8000))?
        .run()
        .await
}

fn init_routes(cfg: &mut web::ServiceConfig) {
    cfg.service(web::resource("/index.html").to(|| async { "Hello world!" }))
        .service(web::resource("/get_rpg").to(get_rpg_v2));
}

#[derive(Deserialize, Debug)]
struct RpgQuery {
    annee: u16,
    code_cultu:u8,
}

async fn get_rpg_v2 (rpg_query: Query<RpgQuery>, geom_json: Json<GeoJson>) -> Result<HttpResponse, Box<dyn std::error::Error>> {
    let rgp_v2_api = "https://apicarto.ign.fr/api/rpg/v2";
    let client = Client::default();

    let geom_string = serde_json::to_string(&geom_json)?;
    println!("geom_string : {}", geom_string);

    let request = client.get(rgp_v2_api)
        .insert_header(("annee", rpg_query.annee.to_string()))
        .insert_header(("code_cultu", rpg_query.code_cultu.to_string()))
        .insert_header(("geom", geom_string));


    println!("{:?}", request);
    match request.send().await {
        Ok(mut response) => {
            let body = response.body().await?;
            println!("Response body: {:?}", body);
            Ok(HttpResponse::Ok().content_type(ContentType::json()).body(body))
        }
        Err(e) => {
            println!("Error during request: {:?}", e);
            Err(Box::new(e))
        }
    }
}

The output in my console is :

geom_string : {"coordinates":[[[[-0.288863182067871,48.96366660729598],[-0.299592018127441,48.95929920857614],[-0.296330451965332,48.95532595238504],[-0.282125473022461,48.950675995388366],[-0.279722213745117,48.96701938292233],[-0.288863182067871,48.96366660729598]]]],"type":"MultiPolygon"}

ClientRequest HTTP/1.1 GET https://apicarto.ign.fr/api/rpg/v2
  headers:
    "annee": "2021"
    "code_cultu": "18"
    "geom": "{\"coordinates\":[[[[-0.288863182067871,48.96366660729598],[-0.299592018127441,48.95929920857614],[-0.296330451965332,48.95532595238504
],[-0.282125473022461,48.950675995388366],[-0.279722213745117,48.96701938292233],[-0.288863182067871,48.96366660729598]]]],\"type\":\"MultiPolygon\"}"

Error during request: Connect(Io(Custom { kind: Other, error: "unexpected EOF" }))

As you can see, this line ends prematurely by a newline:

"geom": "{\"coordinates\":[[[[-0.288863182067871,48.96366660729598],[-0.299592018127441,48.95929920857614],[-0.296330451965332,48.95532595238504

This above string is followed in the console by a whole newline:

],[-0.282125473022461,48.950675995388366],........

Does my problem come from that Serialization problem or possibly from something else ?

EDIT :
I hard coded the String in the code :

    let r = r#"{"type":"MultiPolygon","coordinates":[[[[-0.288863182067871,48.963666607295977],[-0.299592018127441,48.959299208576141],[-0.296330451965332,48.955325952385039],[-0.282125473022461,48.950675995388366],[-0.279722213745117,48.967019382922331],[-0.288863182067871,48.963666607295977]]]]}"#;
    let request = client.get(rgp_v2_api)
        .insert_header(("annee", rpg_query.annee.to_string()))
        .insert_header(("code_cultu", rpg_query.code_cultu.to_string()))
        .insert_header(("geom", r));
    println!("{:?}", request);

The output is :

ClientRequest HTTP/1.1 GET https://apicarto.ign.fr/api/rpg/v2
  headers:
    "code_cultu": "18"
    "geom": "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-0.288863182067871,48.963666607295977],[-0.299592018127441,48.959299208576141],[-0.29633
0451965332,48.955325952385039],[-0.282125473022461,48.950675995388366],[-0.279722213745117,48.967019382922331],[-0.288863182067871,48.963666607295977]]]]}"
    "annee": "2021"

Error during request: Connect(Io(Custom { kind: Other, error: "unexpected EOF" }))

So, the issue could be something else but I don't see what.

Also, here is my Cargo.toml :

[package]
name = "untitled"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-web = { version =  "4.6.0", features = ["openssl"] }
awc = { version = "3.5.0", features = ["openssl"] }
geojson = "0.24.1"
openssl = {version =  "0.10.64", features = ["vendored"] }
serde_json = "1.0.117"

[target.'cfg(windows)'.dependencies]
openssl-sys = { version = "0.9.102", features = ["vendored"] }
serde = { version = "1.0.202", features = ["derive"] }

Can you try calling the to_string method from GeoJson directly rather than using serde_json for the serialization?

The line :

let geom_string = serde_json::to_string(&geom_json)?;
println!("geom_string : {}", geom_string);

gives me the correct result the same way geom_json.to_string() also give the correct output :

let geom_string = geom_json.to_string();
println!("geom_string : {}", geom_string);

The serialization seems to be incorrect when I do :

.insert_header(("geom", geom_string));

Also, I'm wondering if, maybe it's just the

println!("{:?}", request);

that is not printing correctly something that is correct.

In that case, my problem could come from somewhere else ?

Have you enabled any of the TLS features such as openssl or rustls?

awc = { version = "3.5.0", features = ["openssl"] }

Yes, I did.

I added my Cargo.toml file some minutes after in the post.

It's at the end of the post now.

I think you might be on to something.
I added a new handler function that simply calls google.com and I get a similar error.

async fn get_google() -> Result<HttpResponse, Error> {
    let client = Client::default();
    let request = client.get("https://www.google.com");
    let mut response = request.send().await.map_err(|e| {
        println!("1 : {:?}", e);
        actix_web::error::ErrorInternalServerError("Failed to send request")
    })?;
    let body = response.body().await.map_err(|e| {
        println!("2 : {:?}", e);
        actix_web::error::ErrorInternalServerError("Failed to read response body")
    })?;

    Ok(HttpResponse::Ok()
        .content_type("text/html; charset=utf-8")
        .body(body))
}

Calling request.send().await returns the error :

1 : Connect(Io(Custom { kind: Other, error: "unexpected EOF" }))

I think I should close this thread and open a new one since the issue might not be about serialization anymore.

Can we close a thread ?

Closing.