I've created the following login form and accompanying template:
main.rs
#[macro_use]
extern crate nickel;
extern crate mustache;
extern crate rustc_serialize;
use std::collections::HashMap;
use nickel::{Nickel, MediaType, HttpRouter};
use nickel::status::StatusCode;
fn main() {
let mut server = Nickel::new();
let mut router = Nickel::router();
router.get("/", middleware!(|request, mut response| {
response.set(StatusCode::Ok);
response.set(MediaType::Html);
return response.send_file("assets/login.tpl");
}));
router.post("/login", middleware!(|request, mut response| {
response.set(StatusCode::Ok);
response.set(MediaType::Html);
let mut data: HashMap<&str, &str> = HashMap::new();
data.insert("error", "hello");
return response.render("assets/login.tpl", &data);
}));
server.utilize(router);
server.listen("127.0.0.1:6767");
}
assets/login.tpl
<html lang="en">
<head>
<meta charset="utf8"/>
</head>
<body>
<h1>Login</h1>
<form method="post" action="login">
<label for="email">Email</label>
<input type="email" name="email"/>
<br/>
<label for="password">Password</label>
<input type="password" name="password"/>
<br/>
<button type="submit">Login</button><br/>
<a href="/register">Register</a>
</form>
{{error}}
</body>
</html>
When I submit the form the first time, I see the "hello" message. If I submit the form again, I see "Not Found".
I can't figure out where the problem is.
The issue is that you're sending POST data and it's not getting read, which bleeds into the next request (due to keepalive).
To fix, you can either ensure the body of the POST gets read, or add Connection: Close
to the response headers to prevent keepalive.
FWIW: This is a known issue in hyper, but nickel should add it's own solution to prevent confusion here. If you want to follow updates on this, please subscribe to the issue Shepmaster logged on Github.