Actix-web : handle HTTP request by struct's member function

App::new()
    .service(
        web::resource("/")
            .route(web::put().to_async(handle_upstream))
    )

actix-web's to_async function does not allow me to call a struct member.

As you see, AsyncFactory is either 'static or Fn

pub trait AsyncFactory<T, R>: Clone + 'static
where
    R: IntoFuture,
    R::Item: Responder,
    R::Error: Into<Error>,
{
    fn call(&self, param: T) -> R;
}

impl<F, R> AsyncFactory<(), R> for F
where
    F: Fn() -> R + Clone + 'static,
    R: IntoFuture,
    R::Item: Responder,
    R::Error: Into<Error>,
{
    fn call(&self, _: ()) -> R {
        (self)()
    }
}

Now I am using a stupid way to make it work

pub struct StreamingServer {
    sender : Mutex<UnboundedSender<InternalMessage>>,
    // ...
}
static mut SINGLETON: Option<StreamingServer> = None;


fn handle_upstream(req: HttpRequest, stream: web::Payload) -> impl futures01::future::Future<Item=HttpResponse, Error=()> {
    let srv : &mut StreamingServer;
    unsafe{
        srv = SINGLETON.as_mut().unwrap();
    }
    srv.handle_upstream(req, stream).unit_error().boxed_local().compat()
}


impl StreamingServer {

    pub fn new(tx : UnboundedSender<InternalMessage>) -> &'static mut StreamingServer {
        let srv = StreamingServer{
            sender : Mutex::new(tx)
        };
        unsafe {
            if !SINGLETON.is_none() {
                panic!("StreamingServer::new() cannot be called twice!");
            }
            SINGLETON = Some(srv);
            SINGLETON.as_mut().unwrap()
        }
    }

    pub fn start(&mut self, port : u16){

        Server::build().bind( "http/1.1", format!("0.0.0.0:{}", port), || {
            HttpService::build()
                .finish(
                    App::new()
                        .service(
                            web::resource("/")
                                .route(web::put().to_async(handle_upstream))
                        )
                ) 
            }
        )
        .expect(&format!("Unable to bind on port {}", port))
        .workers(1)
        .start();
    }

    async fn handle_upstream(&self, req: HttpRequest, stream: web::Payload) -> HttpResponse {
        
        let sender : UnboundedSender<InternalMessage>;
        {
            sender = self.sender.lock().expect("cannot lock UnboundedSender<InternalMessage>").clone();
        }


        // ....
        
        HttpResponse::Ok().finish()
    }
    

}

I understand StreamingServer struct instance has to be alive as long as the HTTP server is still handling requests. But this implementation is ugly.

Is there an elegant way to implement it?

Thanks

Finally I figured it out --

let srv = Arc::new(StreamingServer::new(upstream_tx));


 Server::build().bind( "http/1.1", format!("0.0.0.0:{}", port), move || {
        HttpService::build()
            .finish(
                App::new()
                    .data(srv.clone())
                    .service(
                        web::resource("/fsd/{id}")
                            .route(web::put().to_async(handle_put_request))
                    )
            ) 
        }
    )







fn handle_put_request(path: web::Path<String>, req: HttpRequest, stream: web::Payload, srv: web::Data<Arc<StreamingServer>>) -> impl futures01::future::Future<Item=HttpResponse, Error=()> {
    
     //...
}