From c6fb4086deb9c982e01f52ee8c3e5fbc7eeea833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Pitucha?= Date: Mon, 25 May 2015 10:49:39 +1000 Subject: [PATCH 1/2] Add common usage helpers --- Cargo.toml | 4 +++ src/helpers.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ 3 files changed, 83 insertions(+) create mode 100644 src/helpers.rs diff --git a/Cargo.toml b/Cargo.toml index d63743e..fdbb453 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,10 @@ documentation = "http://ironframework.io/doc/urlencoded/" description = "Decoding middleware for url-encoded data. For use with Iron." license = "MIT" +[lib] +name = "urlencoded" +doctest = false + [dependencies] iron = "*" url = "*" diff --git a/src/helpers.rs b/src/helpers.rs new file mode 100644 index 0000000..f844b3e --- /dev/null +++ b/src/helpers.rs @@ -0,0 +1,77 @@ +//! Helpers for the urlencoded module +//! +//! Provides one liners for the common usage of urlencoded + +use ::iron::prelude::*; +use ::iron::status; +use ::std::fmt::{Display,Formatter}; +use ::std::fmt::Error as FmtError; +use ::std::error::Error as StdError; +use super::{UrlEncodedBody,UrlEncodedQuery,QueryMap}; + +/// Error returned when the requested parameter is missing +#[derive(Debug, PartialEq)] +pub struct MissingParamError { + name: String +} + +impl StdError for MissingParamError { + fn description(&self) -> &str { + "Missing parameter" + } +} + +impl Display for MissingParamError { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "Missing parameter {}", self.name) + } +} + +/// Returns the parameters hashmap constructed from the request body +/// +/// # Examples +/// ``` +/// fn request_handler(req: &mut Request) => IronResult { +/// let params = try!(require_body_params(req)); +/// ``` +pub fn require_body_params(req: &mut Request) -> IronResult { + req.get::() + .map_err(|err| IronError::new(err, status::BadRequest)) +} + +/// Returns the parameters hashmap constructed from the request query +/// +/// # Examples +/// ``` +/// fn request_handler(req: &mut Request) => IronResult { +/// let params = try!(require_query_params(req)); +/// +/// ``` +pub fn require_query_params(req: &mut Request) -> IronResult { + req.get::() + .map_err(|err| IronError::new(err, status::BadRequest)) +} + +/// Returns the first parameter for a given parameter name, or a `MissingParamError` +/// +/// # Examples +/// ``` +/// fn request_handler(req: &mut Request) => IronResult { +/// let params = try!(require_body_params(req)); +/// let search = try!(require_parameter(¶ms, "search")); +/// +/// ``` +pub fn require_parameter<'a, T: Into>(hashmap: &'a QueryMap, name: T) -> IronResult<&'a String> { + let name_val = name.into(); + hashmap.get(&name_val) + .and_then(|vals| vals.first()) + .ok_or(IronError::new(MissingParamError { name: name_val }, status::BadRequest)) +} + +#[test] +fn test_require_single() { + let mut hash = QueryMap::new(); + hash.insert("var".to_string(), vec!["value".to_string()]); + let val = require_parameter(&hash, "var").unwrap(); + assert_eq!(val, "value"); +} diff --git a/src/lib.rs b/src/lib.rs index 70153b1..279dfa1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,8 @@ use std::collections::hash_map::Entry::*; use std::fmt; use std::error::Error as StdError; +pub mod helpers; + /// Plugin for `Request` that extracts URL encoded data from the URL query string. /// /// Use it like this: `req.get_ref::()` From 587416c06735b99004c72daa4c8ae9f2add2a2e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Pitucha?= Date: Mon, 25 May 2015 10:58:17 +1000 Subject: [PATCH 2/2] Add an example for helpers --- examples/helpers.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 examples/helpers.rs diff --git a/examples/helpers.rs b/examples/helpers.rs new file mode 100644 index 0000000..e3eb022 --- /dev/null +++ b/examples/helpers.rs @@ -0,0 +1,24 @@ +//! This example uses helper functions instead of direct interface. +//! +//! It cannot differentiate between a single and repeated parameter and will +//! fail with 400 as soon as either the body or the required parameter are not +//! provided. + +extern crate iron; +extern crate urlencoded; + +use iron::prelude::*; +use iron::status; +use urlencoded::helpers::{require_body_params, require_parameter}; + +fn log_post_data(req: &mut Request) -> IronResult { + let hashmap = try!(require_body_params(req)); + let name = try!(require_parameter(&hashmap, "name")); + + Ok(Response::with((status::Ok, format!("Hello {}", name)))) +} + +// Test with `curl -i -X POST "http://localhost:3000/" --data "name=world"` +fn main() { + Iron::new(log_post_data).http("127.0.0.1:3000").unwrap(); +}