Debug serialization problem?

I am using crates Rocket and base64 and I'm trying to decode base64 from an upload, but somewhere in the process the base64 is not serializing or deserializing correction. I have identified that at least the "+" character is being converted to a space, no idea what else may not be handled correctly and I don't know how to trace the bug. Any help???

In javascript I get identical results from the first and last logs and the middle is the correct plain text, where item is a text file from an upload field:

    console.log("orig: ",item);
    console.log("eURI: ",atob(encodeURI(item)));
    console.log("from eURI: ",btoa(atob(encodeURI(item))))

I have a struct:

    #[derive(Serialize)]
    #[derive(FromForm,Debug)]
    pub struct NewArticle{
        pub content:String,
    }

This is the relevant function

    #[post("/upload", data="<form>")]
    pub fn receive_post(form: Form<NewArticle>){
    let test = form.into_inner();
        let resp = NewArticle::from(test);
        println!("{:?}",resp.content);    
        let decoded = base64::decode_config(&resp.content, base64::URL_SAFE).unwrap();
        println!("{:?}",decoded);
    }

This is the error I receive:

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: InvalidByte(19, 32)',

I have both done a println!("{:?}",item) as well as sent the string back to the browser and output it in console.log with no attempt at base64 and that's where I see the character that's been converted. The first " " instead of "+" occurs at the 19th character.

Woud you mind taking a look at the post about code formatting?

Sorry, I couldn't find that piece of info before. Thank you!

1 Like

While I AM still very curious how to debug this and why it happened, I'm moving on. I was able to get it working by moving to application/json content type to transmit and receive and using base64::STANDARD instead of base64::URL_SAFE.

But I suppose a whole lot more testing is warranted now.

#[derive(Serialize,Deserialize,Debug)]
pub struct NewArticle{
    pub content:String,
}
#[post("/upload", data="<form>")]
pub fn receive_post(form: Json<NewArticle>)->Json<NewArticle>{
let test = form.into_inner();
    let resp = NewArticle::from(test);
    println!("{:?}",resp.content);    
    let decoded = base64::decode_config(&resp.content, base64::STANDARD).unwrap();
    Json(resp)
}

Are you sure about that? I don't know anything about Javascript, but it sure looks like you're URI-encoding item, then base64-encoding it, then undoing the base64 encoding but not the URI-encoding.

[deleted: some distraction in which I confuse encodeURI with various other forms of encoding]

I do lots of weird things trying to figure out what's failing. You're right that in the first one, item is not URI encoded, but for some reason yeah, they're the same. Something weird may be going on on the JS side, but the chars weren't missing client side, not till they got to the server.

So apparently there's a difference between general URI/URL-encoding, encoding used for HTML forms and whatever the heck encodeURI does. It looks like maybe the client is erroneously injecting the base64-encoded string in as if it were the application/x-www-form-urlencoded data, and that is being automatically decoded on the server side (which is why the '+'s are being translated "back" to ' ').