源代码
编写 Web 应用程序,输入两个自然数,输出其最大公约数。
Cargo.toml 文件
[package]
name = "testweb"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
iron = "0.5.1"
mime = "0.2.3"
router = "0.5.1"
urlencoded = "0.5.0"
main.rs 文件:
extern crate iron;
#[macro_use] extern crate mime;
use iron::prelude::*;
use iron::status;
use iron::Response;
extern crate router;
use router::Router;
use std::str::FromStr;
use urlencoded::UrlEncodedBody;
fn main() {
let mut router = Router::new();
router.get("/", get_form, "root");
router.post("/gcd", post_gcd, "gcd");
println!("serving on http://localhost:8080...");
Iron::new(router).http("0.0.0.0:8080").unwrap();
}
fn get_form(request: &mut Request) -> IronResult<Response> {
let mut response = Response::new();
response.set_mut(status::Ok);
response.set_mut(mime!(Text/Html; Charset=Utf8));
response.set_mut(r#"
<title>GCD Calculator</title>
<form action="/gcd" method="post">
<input type="text" name="n"/>
<input type="text" name="n"/>
<button type="submit">Compute GCD</button>
</form>
"#);
Ok(response)
}
fn post_gcd(request: &mut Request) -> IronResult<Response> {
let mut response = Response::new();
let form_data = match request.get_ref::<UrlEncodedBody>() {
Err(e) => {
response.set_mut(status::BadRequest);
response.set_mut(format!("Error parsing form data: {:?}\n", e));
return Ok(response);
}
Ok(map) => map
};
let unparsed_numbers = match form_data.get("n") {
None => {
response.set_mut(status::BadRequest);
response.set_mut(format!("form data has no 'n' parameter\n"));
return Ok(response);
}
Some(nums) => nums
};
let mut numbers = Vec::new();
for unparsed in unparsed_numbers {
match u64::from_str(&unparsed) {
Err(_) => {
response.set_mut(status::BadRequest);
response.set_mut(
format!("Value for 'n' paramster not a number: {:?}\n",
unparsed));
return Ok(response);
}
Ok(n) => { numbers.push(n);}
}
}
let mut d = numbers[0];
for m in &numbers[1..] {
d = gcd(d, *m);
}
response.set_mut(status::Ok);
response.set_mut(mime!(Text/Html; Charset=Utf8));
response.set_mut(
format!("The greatest comon divisor of the numbers {:?} is <b>{}</b>\n",
numbers, d));
Ok(response)
}
fn gcd(mut x: u64, mut y: u64) -> u64 {
loop {
if x == y { return x; }
if x > y { x = x - y; }
if x < y { y = y - x; }
}
}
代码注释
主程序:
fn main() {
// Router 可把网页请求路由指定的函数。
let mut router = Router::new();
// 收到 URL地址 "/" 的 get 请求,调用 get_form 函数,"root" 是 route_id。
router.get("/", get_form, "root");
// 收到 URL地址 "/" 的 post 请求,调用 post_gcd 函数,"gcd" 是 route_id。
router.post("/gcd", post_gcd, "gcd");
println!("serving on http://localhost:8080...");
Iron::new(router).http("0.0.0.0:8080").unwrap();
}
get_form 函数:
fn get_form(request: &mut Request) -> IronResult<Response> {
// get_form 返回一个 html 网页,网页内容封装在 Response 结构中。
let mut response = Response::new();
// 返回网页的状态。
response.set_mut(status::Ok);
// 设置网页的类型和属性。如果不设置这个,即使后面设置的文本符合 html 语法,
// 浏览器也不会把它解释成为渲染为网页。
response.set_mut(mime!(Text/Html; Charset=Utf8));
// 设置 html 网页的文本。
response.set_mut(r#"
<title>GCD Calculator</title>
<form action="/gcd" method="post">
<input type="text" name="n"/>
<input type="text" name="n"/>
<button type="submit">Compute GCD</button>
</form>
"#);
Ok(response)
}
post_gcd 函数:
fn post_gcd(request: &mut Request) -> IronResult<Response> {
// get_form 返回一个 html 网页,网页内容封装在 Response 结构中。
let mut response = Response::new();
// 从 request 中获取网页内容。
let form_data = match request.get_ref::<UrlEncodedBody>() {
Err(e) => {
// 展示了遇到错误时,如何生成一个携带错误信息的网页。
response.set_mut(status::BadRequest);
response.set_mut(format!("Error parsing form data: {:?}\n", e));
return Ok(response);
}
// 解析出网页数据,保存到变量 map 中。
Ok(map) => map
};
/* 示例数据, json 格式数据
form_data = {"n": ["123", "456"]}
*/
// 从
let unparsed_numbers = match form_data.get("n") {
None => {
response.set_mut(status::BadRequest);
response.set_mut(format!("form data has no 'n' parameter\n"));
return Ok(response);
}
Some(nums) => nums
};
/* 示例数据,应该是 &str 类型
unparsed_numbers = ["123", "456"]
*/
// 把数据从 &str 解析到 Vec 动态数组中。
let mut numbers = Vec::new();
for unparsed in unparsed_numbers {
match u64::from_str(&unparsed) {
Err(_) => {
response.set_mut(status::BadRequest);
response.set_mut(
format!("Value for 'n' paramster not a number: {:?}\n",
unparsed));
return Ok(response);
}
Ok(n) => { numbers.push(n);}
}
}
let mut d = numbers[0];
for m in &numbers[1..] {
d = gcd(d, *m);
}
// 返回结果封装到 response 结构中。
response.set_mut(status::Ok);
response.set_mut(mime!(Text/Html; Charset=Utf8));
response.set_mut(
format!("The greatest comon divisor of the numbers {:?} is <b>{}</b>\n",
numbers, d));
Ok(response)
}