欢迎光临
我们一直在努力

Rocket

Rust 语言作为一门逐渐流行的系统级语言,自然不能少了一个优秀的网络框架。Rust 语言的特性,使得 Web 开发更为安全,性能更为高效,不失为一个优秀的 Web 开发方向,Rocket,就是一个主流的 Rust 网络框架。

rocket

Rocket,是 SergioBenitez 在 Github 上开源的 Rust 语言 Web 框架,仓库位于
https://github.com/SergioBenitez/Rocket,目前版本为 0.4.7。

Rocket是目前 Rust 主流的网络框架之一,其 http 部分基于hyper。Rocket 具有如下三个特点:

  • 安全无误、开发体验好
  • 自动解决请求处理的类型问题,且无需全局状态
  • 拥有各种可插拔的可选组件

rocket

Rocket 需要 nightly 版本的 Rust:

rustup default nightly

要在项目中使用 Rocket,首先创建一个新项目:

cargo new hello-rocket --bin
cd hello-rocket

然后修改 Cargo.toml,添加 Rocket 依赖:

[dependencies]
rocket = "0.4.7"

修改 src/main.rs 来实现 HelloWorld 逻辑:

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}

编译运行程序,运行:

cargo run

就能够在命令行中看到:

  Configured for development.
    => address: localhost
    => port: 8000
    => log: normal
    => workers: [logical cores * 2]
    => secret key: generated
    => limits: forms = 32KiB
    => keep-alive: 5s
    => read timeout: 5s
    => write timeout: 5s
    => tls: disabled
  Mounting '/':
    => GET / (index)
  Rocket has launched from http://localhost:8000

访问 localhost:8000,就能看到启动的 Web 服务器了,返回一个 Hello, world! 的文本响应。

rocket

Rocket 功能丰富,包括:

  • 模板 : Rocket 通过内置的模板支持使模板变得轻而易举
  • cookie : 查看,添加或删除带有或不带加密的 cookie,无需麻烦
  • Stream : Rocket 会传输所有传入和传出的数据,因此不需要考虑大小
  • 配置环境 : 按照您的方式配置应用程序以进行开发,分段和生产
  • 测试 : 使用内置测试库轻松对您的应用程序进行单元测试
  • Typed URIs: Rocket typechecks 为您路由 URI,因此您再也不会错误地输入 URI
  • JSON , Form, State, 中间件… 等等

rocket

Rocket 实现了一个生命循环,步骤包括:

  • 路由:解析 HTTP 请求,并生成相应的数据结构
  • 校验:对数据进行有效性校验
  • 处理:进行实际的业务逻辑处理
  • 响应:生成相应的 HTTP 响应

Rocket 通过十分简洁的方式实现路由注册:

#[get("/world")]              // <- route attribute
fn world() -> &'static str {  // <- request handler
    "hello, world!"
}

Rocket 为路由提供了命名空间:

mod other {
    #[get("/world")]
    pub fn world() -> &'static str {
        "Hello, world!"
    }
}

#[get("/hello")]
pub fn hello() -> &'static str {
    "Hello, outside world!"
}

use other::world;

fn main() {
    // error[E0425]: cannot find value `static_rocket_route_info_for_world` in this scope
    rocket::ignite().mount("/hello", routes![hello, world]);
}

Rocket 内置了 cookies 处理,能够方便实现有状态的 HTTP 会话:

use rocket::http::{Cookie, Cookies};
use rocket::response::{Flash, Redirect};

/// Retrieve the user's ID, if any.
#[get("/user_id")]
fn user_id(mut cookies: Cookies) -> Option<String> {
    cookies.get_private("user_id")
        .map(|cookie| format!("User ID: {}", cookie.value()))
}

/// Remove the `user_id` cookie.
#[post("/logout")]
fn logout(mut cookies: Cookies) -> Flash<Redirect> {
    cookies.remove_private(Cookie::named("user_id"));
    Flash::success(Redirect::to("/"), "Successfully logged out.")
}

Rocket 支持表单数据处理,能够把原生表单数据绑定到 Rust 数据结构中:

use rocket::request::Form;

#[derive(FromForm)]
struct Task {
    complete: bool,
    description: String,
}

#[post("/todo", data = "<task>")]
fn new(task: Form<Task>) { /* .. */ }

Rocket 内置了数据校验功能,能够通过多样的数据校验规则,实现对于请求有效性的判别:

use rocket::http::RawStr;
use rocket::request::FromFormValue;

struct AdultAge(usize);

impl<'v> FromFormValue<'v> for AdultAge {
    type Error = &'v RawStr;

    fn from_form_value(form_value: &'v RawStr) -> Result<AdultAge, &'v RawStr> {
        match form_value.parse::<usize>() {
            Ok(age) if age >= 21 => Ok(AdultAge(age)),
            _ => Err(form_value),
        }
    }
}

#[derive(FromForm)]
struct Person {
    age: AdultAge
}

Rocket 支持通过自定义 Reponder 的方式,自定义全局的响应方式:

use rocket::http::{Header, ContentType};

#[derive(Responder)]
#[response(status = 500, content_type = "json")]
struct MyResponder {
    inner: OtherResponder,
    header: ContentType,
    more: Header<'static>,
    #[response(ignore)]
    unrelated: MyType,
}

Rocket 还提供了优秀的状态管理功能,能够管理跨请求的状态:

use rocket::request::{self, Request, FromRequest};

/// A global atomic counter for generating IDs.
static ID_COUNTER: AtomicUsize = AtomicUsize::new(0);

/// A type that represents a request's ID.
struct RequestId(pub usize);

/// Returns the current request's ID, assigning one only as necessary.
impl<'a, 'r> FromRequest<'a, 'r> for &'a RequestId {
    type Error = ();

    fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
        // The closure passed to `local_cache` will be executed at most once per
        // request: the first time the `RequestId` guard is used. If it is
        // requested again, `local_cache` will return the same value.
        request::Outcome::Success(request.local_cache(|| {
            RequestId(ID_COUNTER.fetch_add(1, Ordering::Relaxed))
        }))
    }
}

#[get("/")]
fn id(id: &RequestId) -> String {
    format!("This is request #{}.", id.0)
}

Rocket 作为目前 Rust 主流的网络框架之一,提供了安全无误、开发体验好、自动解决类型问题、可插拔可选组件等优秀特性,为 Rust 语言在 Web 开发领域提供了可靠的框架支持,同时也是一个优秀的 Rust 语言实践项目。

rocket

赞(0) 打赏
未经允许不得转载:划界MBA » Rocket

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册