2016-03-20 9 views
1

Hyperを使用してRustで小さなWebサービスを構築しようとしています。 r2d2しかし、私は形質に関するいくつかの問題にぶち当たっています。私はコンパイラによって投げられたエラーメッセージを解析することができないので、誰かが私を助けてくれることを望んでいました。接続プールをハイパーハンドラに渡すときに「trait core :: ops :: Fn(Request、Response)>が実装されていません」

は、次のコードを考えてみましょう:

extern crate hyper; 
extern crate postgres; 
extern crate r2d2; 
extern crate r2d2_postgres; 

use hyper::Server; 
use hyper::server::{Request,Response,Handler}; 
use r2d2_postgres::{SslMode, PostgresConnectionManager}; 
use r2d2::{Pool, PooledConnection}; 
use postgres::{Connection}; 

fn connect() -> Pool<PostgresConnectionManager>{ 
    let config = r2d2::Config::default(); 
    let conns = "postgres://abc:[email protected]/abc"; 
    let manager = PostgresConnectionManager::new(conns, SslMode::None).unwrap(); 
    let pool = r2d2::Pool::new(config, manager).unwrap(); 
    return pool; 
} 

fn hello(pool: Pool<PostgresConnectionManager>, req: Request, res: Response) { 
    res.send(b"Hello world").unwrap(); 
} 

fn main() { 
    let pool = connect(); 
    let dispatch = move |req: Request, res: Response| hello(pool, req, res); 
    Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap(); 
} 

私の目標は、機能hellopoolを使用することです。クロージャを使用することによって、私は、ハイパーが持っている期待に応えながら環境変数を引き継ぐことができたと思いました。残念ながら、私は次のエラーを取得する:

src/main.rs:28:45: 28:61 error: the trait `for<'r, 'r, 'r> core::ops::Fn<(hyper::server::request::Request<'r, 'r>, hyper::server::response::Response<'r>)>` is not implemented for the type `[[email protected]/main.rs:27:20: 27:76 pool:r2d2::Pool<r2d2_postgres::PostgresConnectionManager>]` [E0277] 
src/main.rs:28  Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap(); 
                  ^~~~~~~~~~~~~~~~ 
src/main.rs:28:45: 28:61 help: run `rustc --explain E0277` to see a detailed explanation 
error: aborting due to previous error 

それはpoolの種類によって異なります。たとえば、i64を渡そうとすると、すべてが膨らみ、コンパイラは不平を言っていません。

答えて

1

我々はハイパーためのソースを見れば、我々は必要な特性が実装されているクロージャいる見ることができます。

impl<F> Handler for F where F: Fn(Request, Response<Fresh>), F: Sync + Send { 
    fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, res: Response<'a, Fresh>) { 
     self(req, res) 
    } 
} 

これはあなたの閉鎖があなたのために実施されるHandler形質についてFn(Request, Response) + Sync + Sendを実装する必要があることを意味します。それ以外の場合は、自分で実装する必要があります。クロージャーは値によってpoolを取るので、FnOnce(Request, Response)poolが関数に移動すると1回しか呼び出せません)を実装します。

これを修正するには、関数を複数回呼び出すことができるようにプールに不変の参照を代入します(つまり、実装はFn(Request, Response))。

fn hello(pool: &Pool<PostgresConnectionManager>, req: Request, res: Response) { 
    res.send(b"Hello world").unwrap(); 
} 

fn main() { 
    let pool = connect(); 
    let dispatch = move |req: Request, res: Response| hello(&pool, req, res); 
    Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap(); 
} 

N.B.形質Fn(Request, Response)は、上位ランクの形質のための構文糖であるfor<'r> Fn(Request<'r,'r>, Response<'r>)です。これは、RequestResponseの両方が生涯にわたって汎用であるため、あなたの関数はRequestResponseのいずれかをの生涯にわたって処理する必要があるためです。

関連する問題