Early return inside middleware! macro
mmacedoeu opened this issue · comments
I need to return early if preconditions are not met, but tuple response is not accepted if I use return:
fn main() {
let mut server = Nickel::new();
server.post("/claim",
middleware!{ |request, response|
let condition : bool = try_with!(response, {handle_preconditions().map_err(|e| (StatusCode::BadRequest, e))});
if !condition {
return (StatusCode::PreconditionRequired, "invalid state".to_string()); // this is not compilling
// expected type `std::result::Result<nickel::Action<nickel::Response<'mw, _>, //nickel::Response<'mw, _, hyper::net::Streaming>>, nickel::NickelError<'mw, _>>`
// = note: found type `(hyper::status::StatusCode, std::string::String)`
}
let good : bool = try_with!(response, {handle_processing().map_err(|e| (StatusCode::BadRequest, e))});
if good {
(StatusCode::Accepted, "Fine".to_string())
} else {
(StatusCode::NotAcceptable, "Not Fine".to_string())
}
});
server.listen("127.0.0.1:6767").unwrap();
}
It is expecting a return of type std::result::Result<nickel::Action<nickel::Response<'mw, _>, nickel::Response<'mw, _, hyper::net::Streaming>>, nickel::NickelError<'mw, _>>
How can I early return ?
I'm not very good at offering advice, but im currently banging my head against Nickel.rs and it's macros.
I believe this might help you.
In your file, use
use nickel::MiddlewareResult;
and then for your early return use return response.send(put your stuff here);
Ex:
return response.send((StatusCode::Accepted, "Fine".to_string()));
I guess this also should work:
return Err(From::from((
response, (
StatusCode::PreconditionRequired,
String::from("invalid state")
)
)));
https://github.com/nickel-org/nickel.rs/blob/master/src/nickel_error.rs#L72
I figured this out while sorting out #399. Basically the middleware macro is somewhat fragile. It looks like it takes a closure, but is actually taking a block. The block must return something implementing Responder. Note that since it is a block, the return statement interacts with the macro expansion in unexpected ways. To make the original example work, you need to not use return, and instead nest the if statements:
fn main() {
let mut server = Nickel::new();
server.post("/claim", middleware!{ |request, response|
let condition : bool = try_with!(response, {handle_preconditions().map_err(|e| (StatusCode::BadRequest, e))});
if !condition {
(StatusCode::PreconditionRequired, "invalid state".to_string())
} else {
let good : bool = try_with!(response, {handle_processing().map_err(|e| (StatusCode::BadRequest, e))});
if good {
(StatusCode::Accepted, "Fine".to_string())
} else {
(StatusCode::NotAcceptable, "Not Fine".to_string())
}
}
});
server.listen("127.0.0.1:6767").unwrap();
}