2016-04-03 2 views
1

アイアンフレームワークを使用してRustの単純なバックエンドを構築しようとしています。このハンドラは特定のファイルの内容を返すことになっており、unwrap()で正常に動作させることができますが、適切なエラー処理を行いたいと考えています。これは結構ですエラーnot all control paths return a value [E0269]を、スロー結果がErr(_)を返す場合、関数全体がHTTPリクエストエラーを返すようにします。

fn get_content(res: &mut Request) -> IronResult<Response> { 
    let mut id = String::new(); 
    res.body.read_to_string(&mut id).unwrap(); 

    let file_path_string = &("../content/".to_string() + &id + ".rdt"); 

    // TODO: Error handling 
    match File::open(file_path_string) { 
     Ok(f) => { 
      let mut s = String::new(); 
      f.read_to_string(&mut s); 
      Ok(Response::with(((status::Ok), s))) 
     } 
     Err(err) => Err(Response::with(((status::InternalServerError), "File not found"))) 
    }; 
} 

:これは、私はそれは次のようになります想像する方法です。私は試合の一部の後に応答を追加した場合でも:

match File::open(file_path_string) { 
    Ok(f) => { 
     let mut s = String::new(); 
     f.read_to_string(&mut s); 
     Ok(Response::with(((status::Ok), s))) 
    } 
    Err(err) => Err(Response::with(((status::InternalServerError), "File not found"))) 
}; 

Err(Response::with(((status::InternalServerError), "File not found"))) 

私が代わりにエラーメッセージが出ます:

expected `iron::error::IronError`, 
    found `iron::response::Response` 
(expected struct `iron::error::IronError`, 
    found struct `iron::response::Response`) [E0308] 
src/main.rs:95   
Err(Response::with(((status::InternalServerError), "File not found"))) 

を私はこの問題は、錆のErrとアイアンのErr間の衝突であると思いますか?私は確信していません。そして、私は過去に多くのWeb開発(またはRust)を行っていないので、コードに関するフィードバックも高く評価されています。

更新:これはもっと「錆の道」だと思いますか?しかし、私はread_to_stringも世話をする必要があり、それはエラー処理のネストされた混乱を作成するのでしょうか?とエラー処理の内部コードを有する

fn get_content(res: &mut Request) -> IronResult<Response> { 
    let mut id = String::new(); 
    res.body.read_to_string(&mut id).unwrap(); 

    let file_path_string = &("../content/".to_string() + &id + ".rdt"); 

    // TODO: Error handling 
    let f; 
    match File::open(file_path_string) { 
     Ok(file) => f = file, 
     Err(err) => Err(HttpError::Io(err)) 
    }; 
    let mut s = String::new(); 
    f.read_to_string(&mut s); 
    Ok(Response::with(((status::Ok), s))) 
} 

は奇妙なようでわからないんだけどしかし、これらの一致するアームは明らかに互換性のないタイプなので、動作しません...どのような提案ですか?

答えて

2

Ok()Responseであるが、Err()IronErrorである。

...Responseの場合、Err(...)は無効です。

修正方法?最初のステップは、返信するIronErrorを作成する必要があります。アイアンは自動的に適切なエラーコードを表示し、それを行うことはあなたの仕事ではないと私は思っています(アイアンには慣れていません)。

pub enum HttpError { 
    Method, 
    Uri(ParseError), 
    Version, 
    Header, 
    TooLarge, 
    Status, 
    Io(Error), 
    Ssl(Box<Error + 'static + Send + Sync>), 
    Http2(HttpError), 
    Utf8(Utf8Error), 
    // some variants omitted 
} 

私は「ファイルが見つかりません」などの任意の文字列を許容するものを見ることができません。ドキュメントでは、IronErrorを実装する一つのキータイプを見つけます。しかし、あなたのユースケースはIO障害の1つです。だから、それはあなたが戻ってFile::open()から得たstd::IoErrorHttpError::Ioを使用するように理にかなって:「:エラー処理TODO」

match File::open(file_path_string) { 
    Ok(f) => { 
     let mut s = String::new(); 
     f.read_to_string(&mut s); 
     Ok(Response::with(((status::Ok), s))) 
    } 
    Err(err) => Err(HttpError::Io(err)) 
}; 

ところで、それはまたあなたを修正!なんと美しい!

+0

エラー処理の中でコード部分の残りの部分を実行するのは正しいのですか? '' '' read_to_string'''の結果を処理する必要があることを考慮して、エラー処理のネストされた混乱を作りませんか? – mnordber

+0

'' try! 'マクロが当てはまるかどうかを最初に確認するのが慣用であると思います(アイアンのエラータイプや関数のシグネチャであるかどうかわかりません)。 'let what_you_want = match ... {...}'と、1. Ok分岐をwhat_you_wantで終わらせます。2. Err分岐からの早期復帰。この方法で、入れ子にすることなく下に続けることができます。実際、これは 'try! 'の背後にある哲学です。 – mdup

+0

ええ、最初は 'try! 'を使ってみましたが、Ironパッケージと何らかの衝突がありました。ソリューションは単に 'try! 'を放棄するのか、これを回避することができますか?私は 'let what_you_want = match'アプローチを試しましたが、一致するタイプを持たない武器を混乱させました。早期返品とは何ですか?単純にリターンを追加していますか? 'return Err(HttpError :: Io(err))'?なぜなら、私が得る問題は、 'ハイパー::エラー:エラー'を返していますが、 'iron :: error :: IronError'をエキスパートしているからです... – mnordber

関連する問題