63238


Rustのactix-
webを使ってAPIサーバを書いているのですが、あるルートにリクエストがあった際に、別サーバのURLにリクエストを送り、結果が帰ってきたらデータベースにインサートする処理を実装したいです。

以下のように作成しましたが、エラーが出てしまいます。

[code]

    #[post("/backends")]
    async fn add_backend(
        pool: web::Data<DbPool>,
        form: web::Json<forms::BackendForm>,
        ) -> Result<HttpResponse, Error>{
    
        let version = reqwest::get(&(form.url+"/version"))
            .await?
            .text()
            .await?;
    
        let conn = pool.get().expect("cant get db pool");
        let backend = web::block(move || actions::create_backend(&form.name, &form.url, &version, &conn))
            .await
            .map_err(|e| {
                eprintln!("{}", e);
                HttpResponse::InternalServerError().finish()
            })?;
    
        Ok(HttpResponse::Ok().json(backend))
    }
    
[/code]

エラー内容

[code]

    error[E0277]: the trait bound `reqwest::Error: actix_http::error::ResponseError` is not satisfied
      --> src/main.rs:52:15
       |
    52 |         .await?
       |               ^ the trait `actix_http::error::ResponseError` is not implemented for `reqwest::Error`
       |
       = note: required because of the requirements on the impl of `std::convert::From<reqwest::Error>` for `actix_http::error::Error`
       = note: required by `std::convert::From::from`
    
    error[E0277]: the trait bound `reqwest::Error: actix_http::error::ResponseError` is not satisfied
      --> src/main.rs:54:15
       |
    54 |         .await?;
       |               ^ the trait `actix_http::error::ResponseError` is not implemented for `reqwest::Error`
       |
       = note: required because of the requirements on the impl of `std::convert::From<reqwest::Error>` for `actix_http::error::Error`
       = note: required by `std::convert::From::from`
    
    error: aborting due to 2 previous errors
    
[/code]

エラーを見ると、`actix_http::error::ResponseError`という返り値を期待しているのにも関わらず、`reqwest::Error`を返してしまっているので、`reqwest::Error`を受けて、`ResponseError`を返すようにすれば良いのではないかと考えましたが、どのようにすればよいのかわからないという状況です。  
初歩的な質問かもしれませんがどなたかおわかりになる方ご教授いただけませんでしょうか。


CC BY-SA 4.0
2020-02-21T09:53:21.847
63235
2020-02-21T11:26:27.627
2020-02-21T10:36:13.820
7232
7232
question
rust
actix-webのハンドラ内で別サーバにリクエストを送りたい。


`map_err` を使うとできます。

詳細な状況が分からないので actix-web 2.0, reqwest 0.10, serde,
1.0を仮定してコンパイルが通るようにしてみました。詳細はコメントに書いた通りです。

[code]

    #[post("/backends")]
    async fn add_backend(
        pool: web::Data<DbPool>,
        form: web::Json<forms::BackendForm>,
    ) -> Result<HttpResponse, Error> {
        // 所有権エラーが出るので `format!` を使って結合する
        let version = reqwest::get(&format!("{}/version", form.url))
            .await
            // map_errを使ってError型に変換可能な値に変換する。
            // ここでは安直にInternalServerErrorを使う。
            // もっと詳細にエラーを出したければ自分で定義した型を使うとよい。
            .map_err(|e| {
                eprintln!("{}", e);
                HttpResponse::InternalServerError().finish()
            })?
            .text()
            .await
            // 同上
            .map_err(|e| {
                eprintln!("{}", e);
                HttpResponse::InternalServerError().finish()
            })?;
    
        let conn = pool.get().expect("cant get db pool");
        let backend =
            web::block(move || actions::create_backend(&form.name, &form.url, &version, &conn))
                .await
                .map_err(|e| {
                    eprintln!("{}", e);
                    HttpResponse::InternalServerError().finish()
                })?;
    
        Ok(HttpResponse::Ok().json(backend))
    }
    
[/code]

コンパイルの通るコードはこちらに置いておきます。  
<https://gist.github.com/KeenS/f814f1c564b109cbb83a5c3be8a0de46>


CC BY-SA 4.0
2020-02-21T11:26:27.627
63238
2020-02-21T11:26:27.627
22816
63235
answer