2016-04-03 8 views
1

Ich versuche das Iron-Framework zu verwenden, um ein einfaches Backend in Rust zu erstellen. Dieser Handler soll nur den Inhalt einer bestimmten Datei zurückgeben, und ich kann es mit unwrap() richtig funktionieren lassen, aber ich möchte versuchen, eine ordnungsgemäße Fehlerbehandlung zu tun. Dies ist, wie ich könnte mir vorstellen, es aussehen würde:Wenn ein Ergebnis Err (_) zurückgibt, möchte ich, dass die gesamte Funktion einen HTTP-Anforderungsfehler zurückgibt.

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"))) 
    }; 
} 

not all control paths return a value [E0269], dies führt den Fehler, der in Ordnung ist. Aber wenn ich eine Antwort nach dem Spiel Teil hinzufügen:

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"))) 

ich stattdessen die Fehlermeldung:

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"))) 

Ich denke, das Problem ist die Kollision zwischen Rust Err und Eisen Err? Ich bin mir nicht sicher. Und ich habe in der Vergangenheit nicht viel Web-Entwicklung (oder Rust in der Tat) gemacht, also wird jede Rückmeldung über den Code auch geschätzt!

UPDATE: Ich denke, das ist mehr "The Rust Way", es zu tun? Aber ich bin nicht sicher,

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))) 
} 

den Code Nachdem innerhalb der Fehlerbehandlung seltsam scheint, als read_to_string muss auch gesorgt werden, und das würde eine verschachtelte Chaos der Fehlerbehandlung erstellen? Diese passenden Arme sind jedoch offensichtlich inkompatibel, also wird es nicht funktionieren ... irgendwelche Vorschläge?

Antwort

2

Ein Ok() dauert ein Response, aber ein Err() dauert ein IronError.

Daher Err(...) Ihr Anruf ist nicht gültig, wenn ... ein Response ist!

Wie wird es korrigiert? Nun der erste Schritt ist, Sie müssen eine IronError erstellen, um zurück zu senden. Ich glaube (nicht vertraut mit Iron), dass Iron automatisch einen passenden Fehlercode bekommt und dass es nicht deine Aufgabe ist, das zu tun. In der Dokumentation finden wir eine Schlüsselart Umsetzung 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 
} 

Ich kann nicht man sehen, was für eine beliebige Zeichenfolge ermöglicht wie „Datei nicht gefunden“. Ihr Anwendungsfall ist jedoch ein IO-Fehler, richtig? So wäre es sinnvoll, HttpError::Io zu verwenden, um mit den std::IoError, dass Sie wieder von File::open() bekommen:

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)) 
}; 

By the way, es Sich auch behebt "TODO: Fehlerbehandlung"! Wie schön!

(-Code ungetestet, wenden Sie sich bitte bearbeiten, wenn Kompilation ausfällt)

+0

Ist es idiomatisch korrekt den Rest des Codes Teil innerhalb der Fehlerbehandlung zu tun? Wenn ich bedenke, dass ich mit dem Ergebnis von '' read_to_string''' umgehen muss, wird es nicht zu einer verschachtelten Fehlerbehandlung kommen? – mnordber

+0

Was idiomatisch wäre, denke ich, ist zuerst zu sehen, ob das 'try!' - Makro anwendbar ist (ich weiß nicht, ob es mit Iron's-Error-Typen und/oder der Signatur Ihrer Funktion ist.) Wenn nicht, ein guter Workaround wäre wie folgt zu strukturieren: 'let what_you_want = passt zu ... {...}' und 1. lasse den Ok-Zweig mit what_you_want 2. früh-Rückkehr vom Err-Zweig enden. Auf diese Weise können Sie weiter unten ohne Nesting weitermachen. Eigentlich ist das die Philosophie hinter "try!". – mdup

+0

Ja, zuerst habe ich versucht, 'try!' Zu verwenden, aber es gab eine Art Kollision mit dem Iron-Paket.Ist die Lösung einfach "Versuch" zu verlassen oder kannst du das umgehen? Ich habe auch den Ansatz "let what_you_want = match" ausprobiert, endete aber in einem Durcheinander von Armen, die keine passenden Typen hatten. Was ist eine frühe Rückkehr? Summiert es einfach die Rendite? 'return Err (HttpError :: Io (err))'? Weil das Problem, das ich dann bekomme, ist, dass ich einen 'hyper :: error: Error' zurückgebe, aber es erwartet einen 'iron :: error :: IronError' ... – mnordber

Verwandte Themen