Есть код запроса из внешнего интерфейса:

return axios.get("http://127.0.0.1:8088/mike" , {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  params: {
    foo: 'perfectGoods'
  }
})
.then(response => {
  console.log(JSON.stringify(response));
})
.catch(function (error) {
  console.log(error);
});

На бэкэнде данные принимаются следующим образом:

use actix_cors::Cors;
use actix_web::{http, web, App, HttpRequest, HttpResponse, HttpServer, Result};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct MyObj {
    name: String,
}

async fn index(obj: web::Path<MyObj>) -> Result<HttpResponse> {
    Ok(HttpResponse::Ok().json(MyObj {
        name: obj.name.to_string(),
    }))
}


#[actix_rt::main]
async fn main() -> std::io::Result<()> {

    use actix_web::{App, HttpServer};

    HttpServer::new(|| App::new()
        .wrap(
            Cors::new() // <- Construct CORS middleware builder
              .allowed_origin("http://localhost:3000")
              .allowed_methods(vec!["GET", "POST"])
              .allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
              .allowed_header(http::header::CONTENT_TYPE)
              .max_age(3600)
              .finish())
        .service(
            web::resource("")
              .route(web::get().to(index))
              .route(web::head().to(|| HttpResponse::MethodNotAllowed())
        ))
        .route(r"{name}", web::get().to(index)))
        .bind("127.0.0.1:8088")?
        .run()
        .await
}



Вопрос:
Как на бэкэнде я могу извлечь значение foo: perfectGoods, переданное из внешнего интерфейса?

Я пробовал пробовать разные примеры из этого руководства:
https://actix.rs/docs/extractors/

Но решить с его помощью нужную задачу не удалось.
(Некоторые примеры дают ошибку компилятора - некоторые мне не совсем ясно, по какому принципу они работают.)
Для начала хотелось бы увидеть самый примитивный способ получения этого значения ..

2
Mike Kharkov 13 Сен 2020 в 22:01

1 ответ

Лучший ответ

Ошибка в коде внешнего интерфейса. HTTP Content-Type: application/x-www-form-urlencoded предназначен для сообщений формы, которые не принимаются.

Фронтенд с использованием почтового запроса:

// post request
axios.post("http://127.0.0.1:8088/mike" , {
  foo: 'perfectGoods'
})
.then(response => {
  console.log(response.data);
})
.catch(function (error) {
  console.log(error);
});

Или Frontend с помощью запроса Get:

// get request
return axios.get("http://127.0.0.1:8088/mike" , {
  params: {
    foo: 'perfectGoods'
  }
})
.then(response => {
  console.log(JSON.stringify(response));
})
.catch(function (error) {
  console.log(error);
});

Затем используйте экстрактор web::Form, чтобы получить параметр foo из почтовых запросов, и web::Query, чтобы получить параметр foo из запросов на получение.

Вот бэкэнд, который поддерживает запросы как на публикацию, так и на получение. Протестировано с последней версией actix-web 3.0.0.

Cargo.toml

[package]
name = "web_form"
version = "0.1.0"
edition = "2018"

[dependencies]
actix-web = "3.0.1"
actix-cors = "0.3.0"
serde = "1.0.116"
actix-rt = "1.1.1"
env_logger = "0.7.1"

SRC / main.rs

use actix_cors::Cors;
use actix_web::{http, web, get, post, App, HttpResponse, HttpServer, Result};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct MyObj {
    name: String,
}

#[derive(Serialize, Deserialize, Clone)]
struct MyParams {
    foo: Option<String>,
}

#[derive(Serialize, Deserialize)]
struct MyResponseObj {
    name: String,
    params: MyParams,
}

#[get("/{name}")]
async fn index_get(path: web::Path<MyObj>, params: web::Query<MyParams>) -> Result<HttpResponse> {
    Ok(HttpResponse::Ok().json(MyResponseObj {
        name: path.name.to_string(),
        params: params.clone(),
    }))
}

#[post("/{name}")]
async fn index_post(path: web::Path<MyObj>, params: web::Json<MyParams>) -> Result<HttpResponse> {
    Ok(HttpResponse::Ok().json(MyResponseObj {
        name: path.name.to_string(),
        params: params.clone(),
    }))
}

#[actix_rt::main]
async fn main() -> std::io::Result<()> {

    HttpServer::new(|| App::new()
        .wrap(
            Cors::new() // <- Construct CORS middleware builder
              .allowed_origin("http://localhost:3000")
              .allowed_methods(vec!["GET", "POST"])
              .allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
              .allowed_header(http::header::CONTENT_TYPE)
              .max_age(3600)
              .finish())
        .service(index_get)
        .service(index_post)
    )
        .bind("127.0.0.1:8088")?
        .run()
        .await
}
2
Neopallium 14 Сен 2020 в 17:38