Reputation: 2579
In order to support application/json
and multipart/form-data
on the same URL, I would like to check the "Content-Type" header and choose a proper Data<T>
type to hand in to the .data
function of App::new
.
If I uncomment the .guard
line, then curl -X POST -H "Content-Type: multipart/form-data" -F files=\"qqq\" localhost:8080/upload
is dropped. But without the .guard
line all works as it was supposed. What is wrong?
HttpServer::new(move || {
App::new()
.service(resource("/upload")
// .guard(actix_web::guard::Header("Content-Type", "multipart/form-data"))
.data(form.clone())
.route(post()
.to(upload_multipart)
)
)
})
How to join them properly in one instance of App?
Upvotes: 0
Views: 1255
Reputation: 3647
Currently, actix-web 1.0.3 does not support multipart/form-data, but you can use actix_multipart. Since the focus is deserializing same data with different content-types, I've simplified to using application/x-www-form-urlencoded
.
To support two different content-types, nest web::resource
and add guards to each of the handlers:
web::resource("/")
.route(
web::post()
.guard(guard::Header(
"content-type",
"application/x-www-form-urlencoded",
))
.to(form_handler),
)
.route(
web::post()
.guard(guard::Header("content-type", "application/json"))
.to(json_handler),
),
Create handlers that takes deserialized data, and send the data to a common handler:
fn form_handler(user: web::Form<User>) -> String {
handler(user.into_inner())
}
fn json_handler(user: web::Json<User>) -> String {
handler(user.into_inner())
}
fn handler(user: User) -> String {
format!("Got username: {}", user.username)
}
Result:
$ curl -d 'username=adsf' localhost:8000
Got username: asdf⏎
$ curl -d '{"username": "asdf"}' localhost:8000
Parse error⏎
$ curl -d '{"username": "asdf"}' -H 'content-type: application/json' localhost:8000
Got username: asdf⏎
To create your own deserializer, implement the FromRequest
trait.
Upvotes: 2