< 返回版块

139629905 发表于 2020-10-25 23:41

想把路由单独写在一个模块里 形如 /api/hello,/api/hi 这样

use warp::Filter;

pub fn api() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
    warp::path("api").and(warp::path("hello").map(|| ""))
}
use warp::Filter;

pub fn api() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
    warp::path("api").and(hello())
}

fn hello() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
    warp::path("hello").map(|| "")
}

上面第一种写法就可以,第二种不行,会报错

error[E0277]: the trait bound `impl warp::Reply: warp::generic::Tuple` is not satisfied
 --> src\api.rs:4:23
  |
4 |     warp::path("api").and(hello())
  |                       ^^^ the trait `warp::generic::Tuple` is not implemented for `impl warp::Reply`

代码是参照warp example 里面 todos.rs 写的,感觉可能是返回值的 Extract 设置的有问题,但是没头绪要怎么改,求教大家

或者大家知不知道有什么用warp实现的项目?我想去学习一下

万分感谢

评论区

写评论
作者 139629905 2020-10-26 21:33

多谢老哥了,但我试了你的法子,发现并没有解决问题

我只想在/api后面多挂几个路径,并不需要动态的参数啊

不过受你启发,我发现了一种比较丑陋的解法 main.rs

use warp::Filter;
mod api;

#[tokio::main]
async fn main() {
    let api = warp::path("api").and(api::apis());

    warp::serve(api).run(([127, 0, 0, 1], 3030)).await;
}

api.rs

use warp::Filter;

pub fn apis() -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
    hi().or(hello())
}

fn hi() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
    warp::path("hi").map(|| "hi ~~~")
}

fn hello() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
    warp::path("hello").map(|| "hello ~~~")
}

/api/这个段不能放在想要的文件里,感觉简直如鲠在喉

--
👇
c5soft: cargo.toml

[dependencies]
tokio = { version = "0.2.22", features = ["macros"] }
warp = "0.2.5"

main.rs

mod service;
use service::api;

#[tokio::main]
async fn main() {
    //GET /hello/warp => 200 OK with body "Hello, warp!"
    //let api = warp::path!("hello" / String).map(|name| format!("Hello, {}!", name));
    //let api = warp::path!("hello" / String).and_then(hello);
    let api = api();
    warp::serve(api).run(([0, 0, 0, 0], 3030)).await;
}

service.rs

use std::convert::Infallible;
use warp::{Filter, Rejection, Reply};

pub fn api() -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
    warp::path!("hello" / String).and_then(hello)
}
async fn hello(name: String) -> Result<impl Reply, Infallible> {
    Ok(format!("hello {} !", name))
}
lithbitren 2020-10-26 16:05

谢谢,原来这么简单

--
👇
c5soft: service.rs with hello+query

use std::collections::HashMap;
use std::convert::Infallible;
use warp::{Filter, Rejection, Reply};

pub fn api() -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
    let hello = warp::path!("hello" / String).and_then(hello);
    let query = warp::path("query")
        .and(warp::query::<HashMap<String, String>>())
        .and_then(query);
    hello.or(query)
}
async fn hello(name: String) -> Result<impl Reply, Infallible> {
    Ok(format!("hello {} !", name))
}
async fn query(q: HashMap<String, String>) -> Result<impl Reply, Infallible> {
    Ok(format!("query is {:?}", q))
}

http://127.0.0.1:3030/query?a=aaa&b=bbb 应答:query is {"a": "aaa", "b": "bbb"}

--
👇
lithbitren: 路过问一下,warp的url参数应该怎么拿比如说abc.com/set?name=jack&age=18

这里的name和age怎么拿啊,api文档里面好像没有找到啊(可能是我看得不仔细

--
👇
c5soft: tokio 0.3版的warp正在施工中,目前只能用0.2版的tokio

c5soft 2020-10-26 14:42

service.rs with hello+query

use std::collections::HashMap;
use std::convert::Infallible;
use warp::{Filter, Rejection, Reply};

pub fn api() -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
    let hello = warp::path!("hello" / String).and_then(hello);
    let query = warp::path("query")
        .and(warp::query::<HashMap<String, String>>())
        .and_then(query);
    hello.or(query)
}
async fn hello(name: String) -> Result<impl Reply, Infallible> {
    Ok(format!("hello {} !", name))
}
async fn query(q: HashMap<String, String>) -> Result<impl Reply, Infallible> {
    Ok(format!("query is {:?}", q))
}

http://127.0.0.1:3030/query?a=aaa&b=bbb 应答:query is {"a": "aaa", "b": "bbb"}

--
👇
lithbitren: 路过问一下,warp的url参数应该怎么拿比如说abc.com/set?name=jack&age=18

这里的name和age怎么拿啊,api文档里面好像没有找到啊(可能是我看得不仔细

--
👇
c5soft: tokio 0.3版的warp正在施工中,目前只能用0.2版的tokio

作者 139629905 2020-10-26 12:33

谢谢老哥,晚上回去试一下😁

--
👇
c5soft: tokio 0.3版的warp正在施工中,目前只能用0.2版的tokio

lithbitren 2020-10-26 12:26

路过问一下,warp的url参数应该怎么拿比如说abc.com/set?name=jack&age=18

这里的name和age怎么拿啊,api文档里面好像没有找到啊(可能是我看得不仔细

--
👇
c5soft: tokio 0.3版的warp正在施工中,目前只能用0.2版的tokio

c5soft 2020-10-26 10:39

tokio 0.3版的warp正在施工中,目前只能用0.2版的tokio

c5soft 2020-10-26 10:37

cargo.toml

[dependencies]
tokio = { version = "0.2.22", features = ["macros"] }
warp = "0.2.5"

main.rs

mod service;
use service::api;

#[tokio::main]
async fn main() {
    //GET /hello/warp => 200 OK with body "Hello, warp!"
    //let api = warp::path!("hello" / String).map(|name| format!("Hello, {}!", name));
    //let api = warp::path!("hello" / String).and_then(hello);
    let api = api();
    warp::serve(api).run(([0, 0, 0, 0], 3030)).await;
}

service.rs

use std::convert::Infallible;
use warp::{Filter, Rejection, Reply};

pub fn api() -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
    warp::path!("hello" / String).and_then(hello)
}
async fn hello(name: String) -> Result<impl Reply, Infallible> {
    Ok(format!("hello {} !", name))
}
1 共 7 条评论, 1 页