RustWeb开发:API实现与CORS处理
立即解锁
发布时间: 2025-09-04 01:53:31 阅读量: 13 订阅数: 26 AIGC 


Rust Web开发实战指南
### Rust Web 开发:API 实现与 CORS 处理
#### 1. 基础 API 请求与响应
在开发过程中,我们可以使用 `curl` 命令从服务器获取问题数据。例如,使用以下命令:
```bash
curl --location --request GET 'localhost:3030/questions'
```
执行该命令后,会得到一个 JSON 响应,示例如下:
```json
[{"id":"1","title":"How?","content":"Please help!","tags":["general"] }]
```
借助这个可行的解决方案,我们可以进一步尝试实现更多问题,对代码进行修改和调整。比如,尝试返回无效的 JSON 或不同的成功/错误代码。Rust 的优势在于其严格的类型系统,这使得在像 `warp` 这样的库中查找功能、理解返回对象的格式以及在重构时发现错误变得直接明了,编译器会帮助我们处理这些问题。
#### 2. CORS 处理
在开发面向公众的 API 时,需要考虑跨域资源共享(CORS)。Web 浏览器有一个安全机制,即同源策略(SOP),它不允许从域名 A 发起的请求访问域名 B。例如,用户在一个标签页中登录银行账户,在另一个标签页浏览其他网站时,第二个标签页不能对登录银行账户的标签页进行任何更改。
为了解决这个问题,CORS 应运而生。它可以放宽同源策略的限制,允许浏览器向其他域名发送请求。具体来说,浏览器不会直接发送如 HTTP PUT 请求,而是先发送一个预检请求(HTTP OPTIONS 请求)到服务器。这个 OPTIONS 请求询问服务器是否允许发送请求,服务器会在响应头中返回允许的方法。浏览器读取这些允许的方法,如果包含 PUT,就会发送包含实际数据的第二个 HTTP 请求。
不过,也有一些例外情况。由于 CORS 标准不应破坏旧服务器,以下请求头的请求和 HTTP 请求不需要预检请求:
- 请求头:
- `application/x-www-form-urlencoded`
- `multipart/form-data`
- `text/plain`
- HTTP 请求:
- HTTP GET
- HTTP POST
在我们的服务器上,仍然需要验证每个传入的请求。如果要将 API 向公众开放,还需要在响应任何 HTTP OPTION 请求时,返回我们接受的方法和接受请求的来源位置。
通常,CORS 处理是在基础设施层面完成的。但如果运行单个应用实例并希望将 API 向更广泛的公众开放,就需要在应用中处理 CORS。幸运的是,`warp` 框架已经内置了对 CORS 的支持。
##### 2.1 在应用层面返回 CORS 头
我们可以使用 `warp` 框架提供的 `cors` 过滤器来配置和返回正确的 CORS 头。以下是一个示例代码:
```rust
use warp::{
Filter,
http::Method,
reject::Reject,
Rejection,
Reply,
http::StatusCode
};
#[tokio::main]
async fn main() {
let cors = warp::cors()
.allow_any_origin()
.allow_header("content-type")
.allow_methods(&[Method::PUT, Method::DELETE]);
let get_items = warp::get()
.and(warp::path("questions"))
.and(warp::path::end())
.and_then(get_questions)
.recover(return_error);
let routes = get_items.with(cors);
warp::serve(routes)
.run(([127, 0, 0, 1], 3030))
.await;
}
```
在这个代码中,我们从 `warp` 框架导入 `http::Method` 用于 `allow_methods` 数组。浏览器在拦截如 PUT 请求时,会先发送 OPTION 请求,并期望得到以下信息:
- 允许的头信息
- 允许的方法
- 允许的来源
##### 2.2 测试 CORS 响应
为了测试 CORS 配置,我们可以发送一个 OPTION 请求到 `localhost:3030/questions` 路由,并模拟来自不同服务器。使用以下 `curl` 命令:
```bash
curl -X OPTIONS localhost:3030/questions/1 -H "Access-Control-Request-Method: PUT" -H "Access-Control-Request-Headers: content-type" -H "Origin: https://not-origin.io" --verbose
```
执行该命令后,控制台会输出类似以下的信息:
```
> OPTIONS /questions/1 HTTP/1.1
> Host: localhost:3030
> User-Agent: curl/7.64.1
> Accept: */*
> Access-Control-Request-Method: PUT
> Access-Control-Request-Headers: content-type
> Origin: https://reqbin.com
>
< HTTP/1.1 200 OK
< access-control-allow-headers: content-type
< access-control-allow-methods: DELETE, PUT
< access-control-allow-origin: https://reqbin.com
< content-length: 0
< date: Fri, 12 Feb 2021 10:15:19 GMT
```
浏览器会将这个响应视为允许,并继续发送原始的 PUT 请求。我们还可以测试不允许的情况,例如移除允许的头信息,在错误处理中添加 `println!` 语句,然后再次运行 `curl` 命令。
```rust
async fn return_error(r: Rejection) -> Result<impl Reply, Rejection> {
println!("{:?}", r);
if let Some(InvalidId) = r.find() {
Ok(warp::reply::with_status(
"No valid ID presented",
StatusCode::UNPROCESSABLE_ENTITY,
))
} else {
Ok(warp::reply::with_status(
"Route not found",
StatusCode::NOT_FOUND,
))
}
}
#[tokio::main]
async fn main() {
let cors = warp::cors()
.allow_any_origin()
.allow_header("not-in-the-request")
.allow_methods(&[Method::PUT, Method::DELETE]);
// ...
}
```
此时,Rust 端会输出错误信息,`curl` 响应会显示 404 Not Found。为了处理这种情况,我们可以导入 `warp` 中的 `CorsForbidden` 拒绝类型,并在错误处理中使用它:
```rust
use warp::{
Filter,
http::Method,
filters::{
cors::CorsForbidden,
},
reject::Reject,
Rejection,
Reply,
http::StatusCode
};
async fn return_error(r: Rejection) -> Result<impl
```
0
0
复制全文
相关推荐





