mirror of https://github.com/rwf2/Rocket.git
parent
4dbd87a36f
commit
5762208bba
|
@ -15,8 +15,8 @@
|
|||
#[macro_use]
|
||||
extern crate pear;
|
||||
extern crate smallvec;
|
||||
#[macro_use]
|
||||
extern crate percent_encoding;
|
||||
#[doc(hidden)] #[macro_use]
|
||||
pub extern crate percent_encoding;
|
||||
extern crate cookie;
|
||||
extern crate time;
|
||||
extern crate indexmap;
|
||||
|
|
|
@ -59,6 +59,22 @@ pub enum Uri<'a> {
|
|||
Asterisk,
|
||||
}
|
||||
|
||||
/// This encode set is used for strings where '/' characters are known to be
|
||||
/// safe; all other special path segment characters are encoded.
|
||||
define_encode_set! {
|
||||
#[doc(hidden)]
|
||||
pub UNSAFE_PATH_ENCODE_SET = [::percent_encoding::DEFAULT_ENCODE_SET] | {
|
||||
'%', '[', '\\', ']', '^', '|'
|
||||
}
|
||||
}
|
||||
|
||||
/// This encode set should be used for path segments (components) of a
|
||||
/// `/`-separated path. It encodes as much as possible.
|
||||
define_encode_set! {
|
||||
#[doc(hidden)]
|
||||
pub DEFAULT_ENCODE_SET = [UNSAFE_PATH_ENCODE_SET] | { '/' }
|
||||
}
|
||||
|
||||
impl<'a> Uri<'a> {
|
||||
#[inline]
|
||||
crate unsafe fn raw_absolute(
|
||||
|
@ -161,7 +177,7 @@ impl<'a> Uri<'a> {
|
|||
|
||||
/// Returns a URL-encoded version of the string. Any characters outside of
|
||||
/// visible ASCII-range are encoded as well as ' ', '"', '#', '<', '>', '`',
|
||||
/// '?', '{', '}', '%', and '/'.
|
||||
/// '?', '{', '}', '%', '/', '[', '\\', ']', '^', and '|'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -173,8 +189,7 @@ impl<'a> Uri<'a> {
|
|||
/// assert_eq!(encoded, "hello%3Fa=%3Cb%3Ehi%3C%2Fb%3E");
|
||||
/// ```
|
||||
pub fn percent_encode(string: &str) -> Cow<str> {
|
||||
let set = ::percent_encoding::PATH_SEGMENT_ENCODE_SET;
|
||||
::percent_encoding::utf8_percent_encode(string, set).into()
|
||||
::percent_encoding::utf8_percent_encode(string, DEFAULT_ENCODE_SET).into()
|
||||
}
|
||||
|
||||
/// Returns a URL-decoded version of the string. If the percent encoded
|
||||
|
|
|
@ -2,17 +2,10 @@ use std::fmt;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
|
||||
use percent_encoding::utf8_percent_encode;
|
||||
|
||||
use {RawStr, uri::{Uri, Formatter}, ext::Normalize};
|
||||
|
||||
mod priv_encode_set {
|
||||
/// This encode set is used for strings where '/' characters are known to be
|
||||
/// safe; all other special path segment characters are encoded.
|
||||
define_encode_set! { pub PATH_ENCODE_SET = [super::DEFAULT_ENCODE_SET] | {'%'} }
|
||||
}
|
||||
|
||||
use self::priv_encode_set::PATH_ENCODE_SET;
|
||||
use uri::{Uri, Formatter, UNSAFE_PATH_ENCODE_SET};
|
||||
use {RawStr, ext::Normalize};
|
||||
|
||||
/// Trait implemented by types that can be displayed as part of a URI in `uri!`.
|
||||
///
|
||||
|
@ -241,7 +234,7 @@ impl UriDisplay for PathBuf {
|
|||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
let string = self.normalized_str();
|
||||
let enc: Cow<str> = utf8_percent_encode(&string, PATH_ENCODE_SET).into();
|
||||
let enc: Cow<str> = utf8_percent_encode(&string, UNSAFE_PATH_ENCODE_SET).into();
|
||||
f.write_raw(&enc)
|
||||
}
|
||||
}
|
||||
|
@ -251,7 +244,7 @@ impl UriDisplay for Path {
|
|||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
let string = self.normalized_str();
|
||||
let enc: Cow<str> = utf8_percent_encode(&string, PATH_ENCODE_SET).into();
|
||||
let enc: Cow<str> = utf8_percent_encode(&string, UNSAFE_PATH_ENCODE_SET).into();
|
||||
f.write_raw(&enc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
#![feature(proc_macro_hygiene, decl_macro)]
|
||||
|
||||
#[macro_use] extern crate rocket;
|
||||
|
||||
use rocket::response::Redirect;
|
||||
use rocket::http::uri::Uri;
|
||||
|
||||
const NAME: &str = "John[]|\\%@^";
|
||||
|
||||
#[get("/hello/<name>")]
|
||||
fn hello(name: String) -> String {
|
||||
format!("Hello, {}!", name)
|
||||
}
|
||||
|
||||
#[get("/raw")]
|
||||
fn raw_redirect() -> Redirect {
|
||||
Redirect::to(format!("/hello/{}", Uri::percent_encode(NAME)))
|
||||
}
|
||||
|
||||
#[get("/uri")]
|
||||
fn uri_redirect() -> Redirect {
|
||||
Redirect::to(uri!(hello: NAME))
|
||||
}
|
||||
|
||||
fn rocket() -> rocket::Rocket {
|
||||
rocket::ignite().mount("/", routes![hello, uri_redirect, raw_redirect])
|
||||
}
|
||||
|
||||
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rocket::local::Client;
|
||||
use rocket::http::{Status, uri::Uri};
|
||||
|
||||
#[test]
|
||||
fn uri_percent_encoding_redirect() {
|
||||
let expected_location = vec!["/hello/John%5B%5D%7C%5C%25@%5E"];
|
||||
let client = Client::new(rocket()).unwrap();
|
||||
|
||||
let response = client.get("/raw").dispatch();
|
||||
let location: Vec<_> = response.headers().get("location").collect();
|
||||
assert_eq!(response.status(), Status::SeeOther);
|
||||
assert_eq!(&location, &expected_location);
|
||||
|
||||
let response = client.get("/uri").dispatch();
|
||||
let location: Vec<_> = response.headers().get("location").collect();
|
||||
assert_eq!(response.status(), Status::SeeOther);
|
||||
assert_eq!(&location, &expected_location);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uri_percent_encoding_get() {
|
||||
let client = Client::new(rocket()).unwrap();
|
||||
let name = Uri::percent_encode(NAME);
|
||||
let mut response = client.get(format!("/hello/{}", name)).dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.body_string().unwrap(), format!("Hello, {}!", NAME));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue