gotham-rs / gotham

A flexible web framework that promotes stability, safety, security and speed.
https://gotham.rs
Other
2.24k stars 125 forks source link

Example for working with JSON data #351

Open ghost opened 5 years ago

ghost commented 5 years ago

Thanks for the hard work on Gotham.

Would it be possible to have an example for how to handle incoming JSON data? I might be missing it if it already exists, if so sorry for the issue.

Context: I am thinking of making a small API using Gotham and would need to accept JSON and then return a JSON response back to the client. I think the latter may be documented though I can't remember where I saw it.

colinbankier commented 5 years ago

Hi @evitalis. Definitely a good idea to include a nice json example. Here is a pattern I currently use, I create a helper function to extract the body into any type, for example, given a struct Registration:

fn extract_json<T>(state: &mut State) -> impl Future<Item = T, Error = HandlerError>
where
    T: serde::de::DeserializeOwned,
{
    Body::take_from(state)
        .concat2()
        .map_err(bad_request)
        .and_then(|body| {
            let b = body.to_vec();
            from_utf8(&b)
                .map_err(bad_request)
                .and_then(|s| serde_json::from_str::<T>(s).map_err(bad_request))
        })
}

pub fn register(mut state: State) -> Box<HandlerFuture> {
    let repo = Repo::borrow_from(&state).clone();
    let f = extract_json::<Registration>(&mut state)
        .and_then(|registration| {
            users::insert(repo, registration.user).map_err(|e| e.into_handler_error())
        })
        .then(|result| match result {
            Ok(user) => {
                let body = serde_json::to_string(&user).expect("Failed to serialize user.");
                let res = create_response(&state, StatusCode::OK, mime::APPLICATION_JSON, body);
                future::ok((state, res))
            }
            Err(e) => future::err((state, e.into_handler_error())),
        });
    Box::new(f)
}

I also hope to include such helper functions in gotham itself at some point - for various common request formats. I've started a full gotham json api with diesel example app over here if that's helpful: https://github.com/colinbankier/realworld-gotham It's bare-bones and incomplete at the moment - now that we have the 0.4 release out I hope to keep filling it out - but it might give you some ideas in the meantime.

We can keep this issue open to actually include a minimal json example in the gotham examples dir - PRs always welcome!

ghost commented 5 years ago

@colinbankier Thanks I will try to review this and see how it goes. I was typing on mobile and realized my wording was not great, sorry if it was confusing at all.

When I get a chance to test I will post an update with results. I don't mind doing a PR but not yet that familiar with gotham, and still getting my bearings with Rust, so may not be the best person to submit it.