mirror of https://github.com/rwf2/Rocket.git
parent
f86b1cd775
commit
71419933a5
|
@ -191,6 +191,11 @@ fn from_form_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substruct
|
|||
for (k, v) in ::rocket::request::FormItems($arg) {
|
||||
match k {
|
||||
$arms
|
||||
field if field == "_method" => {
|
||||
/* This is a Rocket-specific field. If the user hasn't asked
|
||||
* for it, just let it go by without error. This should stay
|
||||
* in sync with Rocket::preprocess. */
|
||||
}
|
||||
_ => {
|
||||
println!(" => {}={} has no matching field in struct.",
|
||||
k, v);
|
||||
|
|
|
@ -47,6 +47,12 @@ struct DefaultInput<'r> {
|
|||
arg: Option<&'r str>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, FromForm)]
|
||||
struct ManualMethod<'r> {
|
||||
_method: Option<&'r str>,
|
||||
done: bool
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Same number of arguments: simple case.
|
||||
let task = TodoTask::from_form_string("description=Hello&completed=on");
|
||||
|
@ -59,6 +65,13 @@ fn main() {
|
|||
let task = TodoTask::from_form_string("other=a&description=Hello&completed=on");
|
||||
assert!(task.is_err());
|
||||
|
||||
// Ensure _method isn't required.
|
||||
let task = TodoTask::from_form_string("_method=patch&description=Hello&completed=off");
|
||||
assert_eq!(task, Ok(TodoTask {
|
||||
description: "Hello".to_string(),
|
||||
completed: false
|
||||
}));
|
||||
|
||||
let form_string = &[
|
||||
"password=testing", "checkbox=off", "checkbox=on", "number=10",
|
||||
"checkbox=off", "textarea=", "select=a", "radio=c",
|
||||
|
@ -79,4 +92,18 @@ fn main() {
|
|||
assert_eq!(default, Ok(DefaultInput {
|
||||
arg: None
|
||||
}));
|
||||
|
||||
// Ensure _method can be captured if desired.
|
||||
let manual = ManualMethod::from_form_string("_method=put&done=true");
|
||||
assert_eq!(manual, Ok(ManualMethod {
|
||||
_method: Some("put"),
|
||||
done: true
|
||||
}));
|
||||
|
||||
// And ignored when not present.
|
||||
let manual = ManualMethod::from_form_string("done=true");
|
||||
assert_eq!(manual, Ok(ManualMethod {
|
||||
_method: None,
|
||||
done: true
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -38,9 +38,14 @@ use error::Error;
|
|||
/// ```
|
||||
///
|
||||
/// When deriving `FromForm`, every field in the structure must implement
|
||||
/// [FromFormValue](trait.FromFormValue.html). If you implement `FormForm`
|
||||
/// yourself, use the [FormItems](struct.FormItems.html) iterator to iterate
|
||||
/// through the form key/value pairs.
|
||||
/// [FromFormValue](trait.FromFormValue.html).
|
||||
///
|
||||
/// # Implementing
|
||||
///
|
||||
/// If you implement `FormForm` yourself, use the
|
||||
/// [FormItems](struct.FormItems.html) iterator to iterate through the form
|
||||
/// key/value pairs. Be aware that form fields that are typically hidden from
|
||||
/// your application, such as `_method`, will be present while iterating.
|
||||
pub trait FromForm<'f>: Sized {
|
||||
/// The associated error to be returned when parsing fails.
|
||||
type Error;
|
||||
|
|
|
@ -75,7 +75,7 @@ impl Rocket {
|
|||
#[inline]
|
||||
fn issue_response(&self, mut response: Response, hyp_res: hyper::FreshResponse) {
|
||||
// Add the 'rocket' server header, and write out the response.
|
||||
// TODO: If removing Hyper, write out `Data` header too.
|
||||
// TODO: If removing Hyper, write out `Date` header too.
|
||||
response.set_header(header::Server("rocket".to_string()));
|
||||
|
||||
match self.write_response(response, hyp_res) {
|
||||
|
@ -134,7 +134,8 @@ impl Rocket {
|
|||
}
|
||||
|
||||
/// Preprocess the request for Rocket-specific things. At this time, we're
|
||||
/// only checking for _method in forms.
|
||||
/// only checking for _method in forms. Keep this in-sync with derive_form
|
||||
/// when preprocessing form fields.
|
||||
fn preprocess_request(&self, req: &mut Request, data: &Data) {
|
||||
// Check if this is a form and if the form contains the special _method
|
||||
// field which we use to reinterpret the request's method.
|
||||
|
@ -176,7 +177,7 @@ impl Rocket {
|
|||
// convince it to give us another mutable reference.
|
||||
// FIXME: Pay the cost to copy Request into UnsafeCell? Pay the
|
||||
// cost to use RefCell? Move the call to `issue_response` here
|
||||
// to move Request and move directly into a RefCell?
|
||||
// to move Request and move directly into an UnsafeCell?
|
||||
let request: &'r mut Request = unsafe {
|
||||
&mut *(request as *const Request as *mut Request)
|
||||
};
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#![feature(plugin, custom_derive)]
|
||||
#![plugin(rocket_codegen)]
|
||||
|
||||
extern crate rocket;
|
||||
|
||||
use rocket::request::Form;
|
||||
|
||||
#[derive(FromForm)]
|
||||
struct FormData {
|
||||
form_data: String,
|
||||
}
|
||||
|
||||
#[patch("/", data = "<form_data>")]
|
||||
fn bug(form_data: Form<FormData>) -> &'static str {
|
||||
assert_eq!("Form data", &form_data.get().form_data);
|
||||
"OK"
|
||||
}
|
||||
|
||||
|
||||
use rocket::testing::MockRequest;
|
||||
use rocket::http::Method::*;
|
||||
use rocket::http::ContentType;
|
||||
|
||||
#[test]
|
||||
fn method_eval() {
|
||||
let rocket = rocket::ignite().mount("/", routes![bug]);
|
||||
|
||||
let mut req = MockRequest::new(Patch, "/")
|
||||
.header(ContentType::Form)
|
||||
.body("_method=patch&form_data=Form+data");
|
||||
|
||||
let mut response = req.dispatch_with(&rocket);
|
||||
let body_str = response.body().and_then(|b| b.into_string());
|
||||
assert_eq!(body_str, Some("OK".to_string()));
|
||||
}
|
Loading…
Reference in New Issue