I'm trying to build an actix server using actix-web = "3.3.2"
to send a POST request to AWS SES which will send an email to the address provided in the body to the route. I've created a route, called signup
which returns a 400 response with the following curl
request:
curl -i POST -d "name=test_name&[email protected]" 127.0.0.1:8000/signup -v
.
I've also tried sending a json
object for the -d
arg with:
curl -i POST -d '{"name": "test_name", "email": "[email protected]"}' 127.0.0.1:8000/signup -v
Both respond with:
curl: (6) Could not resolve host: POST
* Expire in 0 ms for 6 (transfer 0x5c7286c42fb0)
* Trying 127.0.0.1...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x5c7286c42fb0)
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#1)
> POST /signup HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/7.64.0
> Accept: */*
> Content-Length: 42
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 42 out of 42 bytes
< HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
< content-length: 0
content-length: 0
<
* Connection #1 to host 127.0.0.1 left intact
In my main.rs
file, I have the following which creates the actix server running on port 8000.
#[actix_web::main]
async fn main() -> Result<(), StdErr> {
env_logger::init();
HttpServer::new(move || {
actix_web::App::new()
.wrap(Logger::default())
.service(signup)
})
.bind(("127.0.0.1", 8000))?
.run()
.await?;
Ok(())
}
My service, signup
is located at src/signup
which contain a mod.rs
that exposes pub mod routes
from my routes.rs
file where I've written the following:
#[post("/signup")]
pub async fn signup(body: actix_web::web::Json<SignupBody>) -> impl Responder {
let name = &body.name;
let email = &body.email;
let message = send_message(name.to_string(), email.to_string())
.await;
match message {
Ok(()) => {
web::Json(
SignupResp::Success(Success{ message: "Email Sent Successfully".into() })
)
}
Err(e) => {
web::Json(
SignupResp::ErrorResp(ErrorResp{ message: format!("{}", e) })
)
}
}
}
async fn send_message(name: String, email: String) -> Result<(), Box<dyn std::error::Error>> {
let ses_client = SesClient::new(rusoto_core::Region::UsEast1);
let from = "Test <[email protected]>";
let to = format!("{}, <{}>", name, email);
let subject = "Signup";
let body = "<h1>User Signup</h1>".to_string();
send_email_ses(&ses_client, from, &to, subject, body).await
}
async fn send_email_ses(
ses_client: &SesClient,
from: &str,
to: &str,
subject: &str,
body: String,
) -> Result<(), Box<dyn std::error::Error>> {
let email = Message::builder()
.from(from.parse()?)
.to(to.parse()?)
.subject(subject)
.body(body.to_string())?;
let raw_email = email.formatted();
let ses_request = SendRawEmailRequest {
raw_message: RawMessage {
data: base64::encode(raw_email).into(),
},
..Default::default()
};
ses_client.send_raw_email(ses_request).await?;
Ok(())
}
I'm new to actix and wondering if someone could verify whether or not my curl
request is malformed, or if I've messed something up in my actix server. Any help would be greatly appreciated.
Your request is being rejected because it doesn't specify the content type.
In order to do so, you have to add the Content-Type
header. In cURL you do it like this:
-H "Content-Type: application/json"