Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Dec 03 23:44

    colinbankier on master

    Use mime_guess's built in defau… (compare)

  • Dec 03 23:44
    colinbankier closed #383
  • Dec 03 11:27
    agraven synchronize #383
  • Dec 03 10:50
    agraven opened #383
  • Dec 03 07:13
    dependabot-preview[bot] labeled #382
  • Dec 03 07:13
    dependabot-preview[bot] opened #382
  • Dec 03 07:13

    dependabot-preview[bot] on cargo

    Update http requirement from 0.… (compare)

  • Dec 01 16:14
    msrd0 opened #381
  • Nov 30 21:09
    alsuren synchronize #281
  • Nov 28 07:12

    dependabot-preview[bot] on cargo

    (compare)

  • Nov 28 07:12
    dependabot-preview[bot] closed #344
  • Nov 28 07:12
    dependabot-preview[bot] commented #344
  • Nov 28 07:12
    dependabot-preview[bot] labeled #380
  • Nov 28 07:12
    dependabot-preview[bot] opened #380
  • Nov 28 07:12

    dependabot-preview[bot] on cargo

    Update tokio-rustls requirement… (compare)

  • Nov 27 07:18
    dependabot-preview[bot] labeled #379
  • Nov 27 07:18
    dependabot-preview[bot] opened #379
  • Nov 27 07:18

    dependabot-preview[bot] on cargo

    Update tokio-openssl requiremen… (compare)

  • Nov 27 07:18
    dependabot-preview[bot] labeled #378
  • Nov 27 07:18
    dependabot-preview[bot] opened #378
Judson Lester
@nyarly
For 0.5 we'll be rolling out more restrictive featureing, which'll further cover that case.
Why do you ask?
Marwan Rabbâa
@waghanza
because I tried, and I have a cannot produce proc-macro forfailure_derive v0.1.6as the targetx86_64-unknown-linux-musldoes not support these crate types
however I can compile from debian with alpine as target
but I'm not very confident with cross-compilation
cortesis
@cortesis
Hi there, I'm searching away to get a path passed to a router-function in a handler. The Path can also be red out of the request, however the route must point explicit to the passed path. F.e.:
fn get_router(path: &str) -> Router {
    fn echo(state: State) -> (State, String) {
        //(state, path.to_string())
        //or
        //(state, state.complete_path)
    };
    build_simple_router(|route| {
        route.get(path).to(echo)
    })
}
Colin Bankier
@colinbankier

Hi @cortesis - If I understand correctly, the basic thing you're trying to do can be done with a closure:

fn get_router(path: &'static str) -> Router {
    let echo = { move |state| (state, path.to_string()) };
    build_simple_router(|route| route.get(path).to(echo))
}

but requires the static lifetime. If you can't live with that - you can grab the current path from the state like: let uri = Uri::borrow_from(state); and just define your handler as a top level function outside your get_router function.

Rui Loura
@rjloura

Is there a way to synchronously concatenate the body of a POST request?

Right now I'm looking at this example:
https://github.com/gotham-rs/gotham/blob/master/examples/handlers/form_urlencoded/src/main.rs#L20

For my use case the post data will be very small.
David Laban
@alsuren
@rjloura Sorry for the delay in responding. If you want your handler to have the body of the post request up-front then you could write a middleware that does the concat2 dance and stores the result in State.
syncronously blocking in the handler and waiting for the body to arrive sounds like a good way to open yourself up to slowloris-style attacks, where the attacker drip-feeds the body and blocks an entire OS thread for ages without doing any work.
David Laban
@alsuren
Relatedly, I have been converting a few examples that use async/.await syntax. This landed in stable a couple of weeks ago, and allows you to write your business logic in a way that looks like it is blocking but doesn't suffer from the slowloris problem. gotham-rs/gotham#281 . If I get time over the weekend then I will also make a .await version of the form_urlencoded example so that you can see what I mean.
David Laban
@alsuren
@rjloura https://github.com/alsuren/gotham/commit/ec1340cb4416554611a88bdeed5fb7796c66e942#diff-6d17b708a96e7cff0b9a65acf5adc16bR23-R42 -- a version of the form_urlencoded example that uses .await . I will submit it for review once I have feedback from my above PR.
Danilo Cianfrone
@ar3s3ru

Hello peeps, quick question: I'm trying to pass state to some of my handlers:

#[derive(Clone, StateData)]
pub struct ControllerState<R, C, V>
where
    R: Finder<HfBox> + Sync + Send + 'static,
    C: Calculator + Sync + Send + 'static,
    V: Validator + Sync + Send + 'static,
{
    pub handler: &'static CommandHandler<R, C, V>,
}

pub fn handle<R, C, V>(mut state: State) -> Box<HandlerFuture>
where
    R: Finder<HfBox> + Sync + Send + 'static,
    C: Calculator + Sync + Send + 'static,
    V: Validator + Sync + Send + 'static,
{
    let query_params = Input::take_from(&mut state);

    let converted: Result<InputPlan, InputValidationError> = query_params.try_into();

    if let Err(validation_error) = converted {
        println!("Error: {:?}", validation_error);
        return future::err((state, validation_error.into_handler_error())).boxed();
    }

    let command_handler: &CommandHandler<R, C, V> = &ControllerState::borrow_from(&state).handler;

    println!("Received params: {:?}", converted);

    let response = create_response(
        &state,
        StatusCode::OK,
        mime::APPLICATION_JSON,
        Body::from("Hello world"),
    );

    future::ok((state, response)).boxed()
}

but StateData requires that the struct containing data implements Clone, so I need to implement Clone for every part of the shared state.

Isn't that bad efficiency-wise?

Technically I only need a single instance of that CommandHandler, initialized in main(), and passing immutable references of it to the http handlers.

Am I missing something?

The other problem I have is that the lifetime of that CommandHandler reference in ControllerState is not 'static since, again, it's initialized in main()
Denis Lisov
@tanriol
You don't need to implement Clone for every part.
Danilo Cianfrone
@ar3s3ru
@tanriol
the trait bound `R: std::clone::Clone` is not satisfied

the trait `std::clone::Clone` is not implemented for `R`

help: consider adding a `where R: std::clone::Clone` bound
note: required because of the requirements on the impl of `std::clone::Clone` for `controller::content::get::ControllerState<R, C, V>`
note: required by `gotham::middleware::state::StateMiddleware`rustc(E0277)
mod.rs(29, 22): the trait `std::clone::Clone` is not implemented for `R`
the trait bound `C: std::clone::Clone` is not satisfied

the trait `std::clone::Clone` is not implemented for `C`

help: consider adding a `where C: std::clone::Clone` bound
note: required because of the requirements on the impl of `std::clone::Clone` for `controller::content::get::ControllerState<R, C, V>`
note: required by `gotham::middleware::state::StateMiddleware`rustc(E0277)
mod.rs(29, 22): the trait `std::clone::Clone` is not implemented for `C`
the trait bound `V: std::clone::Clone` is not satisfied

the trait `std::clone::Clone` is not implemented for `V`

help: consider adding a `where V: std::clone::Clone` bound
note: required because of the requirements on the impl of `std::clone::Clone` for `controller::content::get::ControllerState<R, C, V>`
note: required by `gotham::middleware::state::StateMiddleware`rustc(E0277)
mod.rs(29, 22): the trait `std::clone::Clone` is not implemented for `V`
Denis Lisov
@tanriol
The derive is known to be a bit too strict, but a manual implementation does not need this.
Danilo Cianfrone
@ar3s3ru
Manual implementation of StateData you mean?
Denis Lisov
@tanriol
What's really needed is that &'static CommandHandler<R, C, V> is Clone, and shared references are always Clone.
Manual impl Clone for ControllerState<R, C, V>
Danilo Cianfrone
@ar3s3ru
Oh great, that actually worked.
Thanks a ton! @tanriol :bow:
Danilo Cianfrone
@ar3s3ru

Now I have another problem, don't know what's going on:

#[derive(StateData)]
pub struct State<R, C, V>
where
    R: Sync + Send + 'static,
    C: Sync + Send + 'static,
    V: Sync + Send + 'static,
{
    inner: std::sync::Arc<CommandHandler<R, C, V>>,
}

impl<R, C, V> Clone for State<R, C, V>
where
    R: Finder<HfBox> + Sync + Send + 'static,
    C: Calculator + Sync + Send + 'static,
    V: Validator + Sync + Send + 'static,
{
    fn clone(&self) -> Self {
        State {
            inner: self.inner.clone(),
        }
    }
}

impl<R, C, V> State<R, C, V>
where
    R: Finder<HfBox> + Sync + Send + 'static,
    C: Calculator + Sync + Send + 'static,
    V: Validator + Sync + Send + 'static,
{
    pub fn new(inner: std::sync::Arc<CommandHandler<R, C, V>>) -> Self {
        State { inner }
    }

    async fn handle(
        &self,
        input: <CommandHandler<R, C, V> as Handler>::Input,
    ) -> Result<
        <CommandHandler<R, C, V> as Handler>::Output,
        <CommandHandler<R, C, V> as Handler>::Error,
    > {
        self.inner.handle(input).await
    }
}

pub fn handle<R, C, V>(mut state: GothamState) -> Box<HandlerFuture>
where
    R: Finder<HfBox> + Sync + Send + 'static,
    C: Calculator + Sync + Send + 'static,
    V: Validator + Sync + Send + 'static,
{
    let input: Result<InputPlan, InputValidationError> = Input::take_from(&mut state).try_into();
    if let Err(err) = input {
        return future::err((state, err.into_handler_error())).boxed();
    }

    let input_plan = input.unwrap();
    let command = Command {
        interval: (&input_plan).into(),
        plan: input_plan.into(),
    };

    State::<R, C, V>::borrow_from(&state)
        .handle(command)
        .boxed()
        .compat()
        .then(move |result| match result {
            Err(err) => future::err((state, err.into_handler_error())),
            Ok(hfbox) => {
                let json = serde_json::to_string(&hfbox).unwrap();

                let response = create_response(
                    &state,
                    StatusCode::OK,
                    mime::APPLICATION_JSON,
                    Body::from(json),
                );

                future::ok((state, response))
            }
        })
        .boxed()
}

This thing fails here:

error[E0597]: `state` does not live long enough
   --> my-service-api/src/controller/content/get.rs:97:35
    |
97  |     State::<R, C, V>::borrow_from(&state)
    |     ------------------------------^^^^^^-
    |     |                             |
    |     |                             borrowed value does not live long enough
    |     argument requires that `state` is borrowed for `'static`
...
117 | }
    | - `state` dropped here while still borrowed

error[E0505]: cannot move out of `state` because it is borrowed
   --> my-service-api/src/controller/content/get.rs:101:15
    |
97  |     State::<R, C, V>::borrow_from(&state)
    |     -------------------------------------
    |     |                             |
    |     |                             borrow of `state` occurs here
    |     argument requires that `state` is borrowed for `'static`
...
101 |         .then(move |result| match result {
    |               ^^^^^^^^^^^^^ move out of `state` occurs here
102 |             Err(err) => future::err((state, err.into_handler_error())),
    |                                      ----- move occurs due to use in closure
I don't understand why is the borrow reference outliving the future, the reference to State is returned after State::<R, C, V>::borrow_from(&state), so it should be safe to move state inside then, no? I'm probably missing something here
Denis Lisov
@tanriol
The reference is never returned as it's reborrowed along the whole call chain.
How about take_from instead of borrow_from?
Danilo Cianfrone
@ar3s3ru
take_from made it work, thank you again :bow:
it seems i need to go back to the borrowing system
synul
@synul_gitlab
Hi everybody, I have a problem with the futures crate in one of the examples, maybe someone can help: I'm trying to implement the MiddlewareAddingResponseHeader example from the docs.rs examples. I'm getting the error "The 'map' method cannot be invoked on a trait object". Compiler then suggests to use futures::future::Future, which I tried (plus any other Future import I could find on different examples) but to no avail - any ideas?
synul
@synul_gitlab
Ok, I solved it with use hyper::rs::Future, current situation with Rust futures I guess...
Rui Loura
@rjloura

I have a JSON response that looks like this:

{
    "action": "evacuate",
    "complete": 9999,
    "result": [
          .... upto 1 million small entries ....
    ]
}

Does gotham automatically stream the results for me? Also I'd rather not build this array up in memory if I don't have to, and instead just pipe the result array entries to the response body as I receive them from the database (using diesel if that matters).

David Laban
@alsuren
@rjloura how far did you get with this? I've not tried this myself, but I think the building blocks you need are https://github.com/gotham-rs/gotham/issues/189#issuecomment-383265362 (streaming the response body) and https://github.com/serde-rs/json/issues/345#issuecomment-323592752 (serialising sequences in a streaming manner, using serde)
Seaton Ullberg
@seatonullberg
Hi everyone! I realize this is probably a more general rust question but I haven't found anything on google so I figured I would try here. I am trying to derive StateData on a struct but the compiler complains that the "trait is implemented but not in scope". I have #[macro_use] gotham_derive; in my src/lib.rs file and have use gotham::state::FromState; in src/mysubmodule/myfile.rs. Is there some extra statement I need to include in src/mysubmodule/mod.rs to make this work?
Kristjan Kosic
@kristjank

@kristjank
hi all
I am evaluation some of the rust frameworks and looking for the best option to build an API Gateway ...

I am looking for some best practices or examples related to building an API gateway with rust.

I checked for samples and docs, would like some community feedback too.

Use case would be simple forwarding to a dynamic address that changes during runtime. Most of the examples had this backed it during the http server start as fixed arguments.

Requirements

  • Incoming rest request with headers

  • Analyse the header and choose correct forwarding host

  • Forward the dance request from 1 to host chosen in 2

  • Handle response from host and send same response to client

So how would this look with Gotham? or do I have to stick with lower level libs, like hyper?

Marwan Rabbâa
@waghanza
Hi,

I have an

error: `core::slice::<impl [T]>::len` is not yet stable as a const fn

when compiling 0.4.0 in https://github.com/the-benchmarker/web-frameworks/blob/master/rust/gotham/src/main.rs
anyone has a workaroung ?

(I have totally no skills in rust)
Denis Lisov
@tanriol
Update your compiler to the latest stable version?
rustup update stable if you're using rustup
Marwan Rabbâa
@waghanza
ok, I was using 1.38 inside docker
I try 1.39
Marwan Rabbâa
@waghanza
still an error with 1.39
error[E0277]: the trait bound `hyper::Body: hyper::body::payload::Payload` is not satisfied
Denis Lisov
@tanriol
The hyper dependency in Cargo.toml is specified as *, which means "any version", but 0.13 is not compatible. The dependency needs to be 0.12
Marwan Rabbâa
@waghanza
ok, I see, and is there a way that I can say I alwyas want the most update-to-date compatible version ?
Denis Lisov
@tanriol
A dependency specified as hyper = "0.12" would be that because it's interpreted as "the latest version considered compatible according to (Rust-flavored) semver"
Marwan Rabbâa
@waghanza
:+1:
Marwan Rabbâa
@waghanza
is there a doc saying that 0.13 is not stable ?
Denis Lisov
@tanriol
It is stable, but gotham is not compatible with it yet.