mirror of https://github.com/rwf2/Rocket.git
Fix 'UriDisplay<Query>' 'Json', 'MsgPack', impls.
As 'FromForm' doesn't provide access to the raw, undecoded string, 'MsgPack' cannot implement 'FromForm::from_value()'. This means that it is not presently possible to parse a MessagePack form from a query string. As such, the 'UriDisplay<Query>' implementation was removed. The 'UriDisplay<Query>' for JSON was fixed such that a round-trip of a 'Json<T>' as a form works as expected.
This commit is contained in:
parent
bad762b8c4
commit
6a3d1ac1d5
|
@ -25,7 +25,7 @@ unicode-xid = "0.2"
|
|||
glob = "0.3"
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { version = "0.5.0-rc.1", path = "../lib", features = ["json"] }
|
||||
rocket = { version = "0.5.0-rc.1", path = "../lib", features = ["json", "msgpack"] }
|
||||
pretty_assertions = "0.7"
|
||||
version_check = "0.9"
|
||||
trybuild = "1.0"
|
||||
|
|
|
@ -1,14 +1,28 @@
|
|||
#[macro_use] extern crate rocket;
|
||||
|
||||
use rocket::http::uri::fmt::{UriDisplay, Query, Path};
|
||||
use rocket::serde::{Serialize, Deserialize};
|
||||
|
||||
macro_rules! assert_uri_display_query {
|
||||
($v:expr, $s:expr) => (
|
||||
($v:expr, $expected:expr) => (
|
||||
let uri_string = format!("{}", &$v as &dyn UriDisplay<Query>);
|
||||
assert_eq!(uri_string, $s);
|
||||
assert_eq!(uri_string, $expected);
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! assert_query_value_roundtrip {
|
||||
($T:ty, $v:expr) => ({
|
||||
use rocket::form::{Form, Strict};
|
||||
use rocket::http::RawStr;
|
||||
|
||||
let v = $v;
|
||||
let string = format!("={}", &v as &dyn UriDisplay<Query>);
|
||||
let raw = RawStr::new(&string);
|
||||
let value = Form::<Strict<$T>>::parse_encoded(raw).map(|s| s.into_inner());
|
||||
assert_eq!(value.expect("form parse"), v);
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(UriDisplayQuery, Clone)]
|
||||
enum Foo<'r> {
|
||||
First(&'r str),
|
||||
|
@ -194,3 +208,36 @@ fn uri_display_path() {
|
|||
assert_uri_display_path!(BamP(BazP(&100)), "100");
|
||||
assert_uri_display_path!(BopP(FooP("bop foo")), "bop%20foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uri_display_serde() {
|
||||
use rocket::serde::json::Json;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, UriDisplayQuery, Deserialize, Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
struct Bam {
|
||||
foo: String,
|
||||
bar: Option<usize>,
|
||||
baz: Result<String, usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, FromForm, UriDisplayQuery)]
|
||||
struct JsonFoo(Json<Bam>);
|
||||
|
||||
let bam = Bam {
|
||||
foo: "hi[]=there.baz !?".into(),
|
||||
bar: None,
|
||||
baz: Ok("what is baz, anyway?".into()),
|
||||
};
|
||||
|
||||
assert_query_value_roundtrip!(JsonFoo, JsonFoo(Json(bam.clone())));
|
||||
|
||||
// TODO: This requires `MsgPack` to parse from value form fields.
|
||||
//
|
||||
// use rocket::serde::msgpack::MsgPack;
|
||||
//
|
||||
// #[derive(Debug, PartialEq, FromForm, UriDisplayQuery)]
|
||||
// struct MsgPackFoo(MsgPack<Bam>);
|
||||
//
|
||||
// assert_query_value_roundtrip!(MsgPackFoo, MsgPackFoo(MsgPack(bam)));
|
||||
}
|
||||
|
|
|
@ -208,9 +208,10 @@ impl<'r, T: Serialize> Responder<'r, 'static> for Json<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::UriDisplay<fmt::Query>> fmt::UriDisplay<fmt::Query> for Json<T> {
|
||||
impl<T: Serialize> fmt::UriDisplay<fmt::Query> for Json<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_, fmt::Query>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
let string = to_string(&self.0).map_err(|_| std::fmt::Error)?;
|
||||
f.write_value(&string)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ use crate::data::{Limits, Data, FromData, Outcome};
|
|||
use crate::response::{self, Responder, content};
|
||||
use crate::http::Status;
|
||||
use crate::form::prelude as form;
|
||||
use crate::http::uri::fmt;
|
||||
// use crate::http::uri::fmt;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
|
@ -200,6 +200,9 @@ impl<'r, T: Serialize> Responder<'r, 'static> for MsgPack<T> {
|
|||
|
||||
#[crate::async_trait]
|
||||
impl<'v, T: Deserialize<'v> + Send> form::FromFormField<'v> for MsgPack<T> {
|
||||
// TODO: To implement `from_value`, we need to the raw string so we can
|
||||
// decode it into bytes as opposed to a string as it won't be UTF-8.
|
||||
|
||||
async fn from_data(f: form::DataField<'v, '_>) -> Result<Self, form::Errors<'v>> {
|
||||
Self::from_data(f.request, f.data).await.map_err(|e| {
|
||||
match e {
|
||||
|
@ -211,11 +214,13 @@ impl<'v, T: Deserialize<'v> + Send> form::FromFormField<'v> for MsgPack<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::UriDisplay<fmt::Query>> fmt::UriDisplay<fmt::Query> for MsgPack<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_, fmt::Query>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
// impl<T: Serialize> fmt::UriDisplay<fmt::Query> for MsgPack<T> {
|
||||
// fn fmt(&self, f: &mut fmt::Formatter<'_, fmt::Query>) -> std::fmt::Result {
|
||||
// let bytes = to_vec(&self.0).map_err(|_| std::fmt::Error)?;
|
||||
// let encoded = crate::http::RawStr::percent_encode_bytes(&bytes);
|
||||
// f.write_value(encoded.as_str())
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<T> From<T> for MsgPack<T> {
|
||||
fn from(value: T) -> Self {
|
||||
|
|
Loading…
Reference in New Issue