mirror of https://github.com/rwf2/Rocket.git
Document the http module.
This commit is contained in:
parent
762b38efe9
commit
5a1a303c59
|
@ -8,6 +8,7 @@ term-painter = "^0.2"
|
|||
log = "^0.3"
|
||||
url = "^1"
|
||||
toml = "^0.2"
|
||||
# cookie = "^0.3"
|
||||
|
||||
[dependencies.hyper]
|
||||
git = "https://github.com/SergioBenitez/hyper"
|
||||
|
@ -16,6 +17,7 @@ branch = "0.9.x"
|
|||
|
||||
[dev-dependencies]
|
||||
lazy_static = "*"
|
||||
rocket_codegen = { path = "../codegen" }
|
||||
|
||||
[features]
|
||||
testing = []
|
||||
|
|
|
@ -17,23 +17,23 @@ use router::Collider;
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ContentType(pub TopLevel, pub SubLevel, pub Option<Vec<Param>>);
|
||||
|
||||
macro_rules! is_some {
|
||||
($ct:ident, $name:ident: $top:ident/$sub:ident) => {
|
||||
/// Returns a new ContentType that matches the MIME for this method's
|
||||
/// name.
|
||||
pub fn $ct() -> ContentType {
|
||||
macro_rules! ctrs {
|
||||
($($(#[$attr:meta])* | $name:ident: $top:ident/$sub:ident),+) => {
|
||||
$($(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name() -> ContentType {
|
||||
ContentType::of(TopLevel::$top, SubLevel::$sub)
|
||||
}
|
||||
|
||||
is_some!($name: $top/$sub);
|
||||
})+
|
||||
};
|
||||
}
|
||||
|
||||
($name:ident: $top:ident/$sub:ident) => {
|
||||
/// Returns true if `self` is the content type matching the method's
|
||||
/// name.
|
||||
macro_rules! checkers {
|
||||
($($(#[$attr:meta])* | $name:ident: $top:ident/$sub:ident),+) => {
|
||||
$($(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(&self) -> bool {
|
||||
self.0 == TopLevel::$top && self.1 == SubLevel::$sub
|
||||
}
|
||||
})+
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -61,47 +61,6 @@ impl ContentType {
|
|||
ContentType(t, s, None)
|
||||
}
|
||||
|
||||
/// Returns a new ContentType for `*/*`, i.e., any.
|
||||
#[inline(always)]
|
||||
pub fn any() -> ContentType {
|
||||
ContentType::of(TopLevel::Star, SubLevel::Star)
|
||||
}
|
||||
|
||||
/// Returns true if this content type is not one of the standard content
|
||||
/// types, that if, if it is an "extended" content type.
|
||||
pub fn is_ext(&self) -> bool {
|
||||
if let TopLevel::Ext(_) = self.0 {
|
||||
true
|
||||
} else if let SubLevel::Ext(_) = self.1 {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the content type is plain text, i.e.: `text/plain`.
|
||||
is_some!(is_text: Text/Plain);
|
||||
|
||||
/// Returns true if the content type is JSON, i.e: `application/json`.
|
||||
is_some!(json, is_json: Application/Json);
|
||||
|
||||
/// Returns true if the content type is XML, i.e: `application/xml`.
|
||||
is_some!(xml, is_xml: Application/Xml);
|
||||
|
||||
/// Returns true if the content type is any, i.e.: `*/*`.
|
||||
is_some!(is_any: Star/Star);
|
||||
|
||||
/// Returns true if the content type is HTML, i.e.: `application/html`.
|
||||
is_some!(html, is_html: Application/Html);
|
||||
|
||||
/// Returns true if the content type is that for non-data HTTP forms, i.e.:
|
||||
/// `application/x-www-form-urlencoded`.
|
||||
is_some!(is_form: Application/WwwFormUrlEncoded);
|
||||
|
||||
/// Returns true if the content type is that for data HTTP forms, i.e.:
|
||||
/// `multipart/form-data`.
|
||||
is_some!(is_data: Multipart/FormData);
|
||||
|
||||
/// Returns the Content-Type associated with the extension `ext`. Not all
|
||||
/// extensions are recognized. If an extensions is not recognized, then this
|
||||
/// method returns a ContentType of `any`.
|
||||
|
@ -128,7 +87,7 @@ impl ContentType {
|
|||
pub fn from_extension(ext: &str) -> ContentType {
|
||||
let (top_level, sub_level) = match ext {
|
||||
"txt" => (TopLevel::Text, SubLevel::Plain),
|
||||
"html" => (TopLevel::Text, SubLevel::Html),
|
||||
"html" | "htm" => (TopLevel::Text, SubLevel::Html),
|
||||
"xml" => (TopLevel::Application, SubLevel::Xml),
|
||||
"js" => (TopLevel::Application, SubLevel::Javascript),
|
||||
"css" => (TopLevel::Text, SubLevel::Css),
|
||||
|
@ -144,6 +103,57 @@ impl ContentType {
|
|||
|
||||
ContentType::of(top_level, sub_level)
|
||||
}
|
||||
|
||||
ctrs! {
|
||||
/// Returns a `ContentType` representing `*/*`, i.e., _any_ ContentType.
|
||||
| any: Star/Star,
|
||||
|
||||
/// Returns a `ContentType` representing JSON, i.e, `application/json`.
|
||||
| json: Application/Json,
|
||||
|
||||
/// Returns a `ContentType` representing XML, i.e, `application/xml`.
|
||||
| xml: Application/Xml,
|
||||
|
||||
/// Returns a `ContentType` representing HTML, i.e, `application/html`.
|
||||
| html: Application/Html
|
||||
}
|
||||
|
||||
/// Returns true if this content type is not one of the standard content
|
||||
/// types, that if, if it is an "extended" content type.
|
||||
pub fn is_ext(&self) -> bool {
|
||||
if let TopLevel::Ext(_) = self.0 {
|
||||
true
|
||||
} else if let SubLevel::Ext(_) = self.1 {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
checkers! {
|
||||
/// Returns true if the content type is plain text, i.e.: `text/plain`.
|
||||
| is_text: Text/Plain,
|
||||
|
||||
/// Returns true if the content type is JSON, i.e: `application/json`.
|
||||
| is_json: Application/Json,
|
||||
|
||||
/// Returns true if the content type is XML, i.e: `application/xml`.
|
||||
| is_xml: Application/Xml,
|
||||
|
||||
/// Returns true if the content type is any, i.e.: `*/*`.
|
||||
| is_any: Star/Star,
|
||||
|
||||
/// Returns true if the content type is HTML, i.e.: `application/html`.
|
||||
| is_html: Application/Html,
|
||||
|
||||
/// Returns true if the content type is that for non-data HTTP forms,
|
||||
/// i.e.: `application/x-www-form-urlencoded`.
|
||||
| is_form: Application/WwwFormUrlEncoded,
|
||||
|
||||
/// Returns true if the content type is that for data HTTP forms, i.e.:
|
||||
/// `multipart/form-data`.
|
||||
| is_form_data: Multipart/FormData
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ContentType {
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
//! Re-exported hyper HTTP library types.
|
||||
//!
|
||||
//! ## Hyper
|
||||
//!
|
||||
//! All types that are re-exported from Hyper resides inside of this module.
|
||||
//! These types will, with certainty, be removed with time, but they reside here
|
||||
//! while necessary.
|
||||
|
||||
// TODO: Remove from Rocket in favor of a more flexible HTTP library.
|
||||
pub use hyper::server::Request as HyperRequest;
|
||||
pub use hyper::server::Response as HyperResponse;
|
||||
|
|
|
@ -5,6 +5,9 @@ use error::Error;
|
|||
use http::hyper::HyperMethod;
|
||||
use self::Method::*;
|
||||
|
||||
// TODO: Support non-standard methods, here and in codegen.
|
||||
|
||||
/// Representation of HTTP methods.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Method {
|
||||
Get,
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
//! [unstable] Types that map to concepts in HTTP.
|
||||
//!
|
||||
//! This module exports types that map to HTTP concepts or to the underlying
|
||||
//! HTTP library when needed. Because the underlying HTTP library is likely to
|
||||
//! change (see <a
|
||||
//! href="https://github.com/SergioBenitez/Rocket/issues/17">#17</a>), most of
|
||||
//! this module should be considered unstable.
|
||||
pub mod hyper;
|
||||
pub mod uri;
|
||||
|
||||
|
@ -11,4 +18,6 @@ pub use hyper::mime;
|
|||
pub use self::method::Method;
|
||||
pub use self::hyper::StatusCode;
|
||||
pub use self::content_type::ContentType;
|
||||
|
||||
/// Can I document it here?
|
||||
pub use self::cookies::{Cookie, Cookies};
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
|
||||
use std::cell::Cell;
|
||||
use std::convert::From;
|
||||
use std::fmt::{self, Write};
|
||||
use std::fmt;
|
||||
|
||||
use router::Collider;
|
||||
|
||||
// TODO: Reconsider deriving PartialEq and Eq to make "//a/b" == "/a/b".
|
||||
/// Borrowed string type for absolute URIs.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct URI<'a> {
|
||||
uri: &'a str,
|
||||
|
@ -18,6 +19,7 @@ pub struct URI<'a> {
|
|||
}
|
||||
|
||||
impl<'a> URI<'a> {
|
||||
/// Constructs a new URI from a given string.
|
||||
pub fn new<T: AsRef<str> + ?Sized>(uri: &'a T) -> URI<'a> {
|
||||
let uri = uri.as_ref();
|
||||
|
||||
|
@ -41,6 +43,31 @@ impl<'a> URI<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the number of segments in the URI. Empty segments, which are
|
||||
/// invalid according to RFC#3986, are not counted.
|
||||
///
|
||||
/// The segment count is cached after the first invocation. As a result,
|
||||
/// this function is O(1) after the first invocation, and O(n) before.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// A valid URI with only non-empty segments:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("/a/b/c");
|
||||
/// assert_eq!(uri.segment_count(), 3);
|
||||
/// ```
|
||||
///
|
||||
/// A URI with empty segments:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("/a/b//c/d///e");
|
||||
/// assert_eq!(uri.segment_count(), 5);
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn segment_count(&self) -> usize {
|
||||
self.segment_count.get().unwrap_or_else(|| {
|
||||
|
@ -50,21 +77,114 @@ impl<'a> URI<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns an iterator over the segments of this URI. Skips empty segments.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// A valid URI with only non-empty segments:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("/a/b/c?a=true#done");
|
||||
/// for (i, segment) in uri.segments().enumerate() {
|
||||
/// match i {
|
||||
/// 0 => assert_eq!(segment, "a"),
|
||||
/// 1 => assert_eq!(segment, "b"),
|
||||
/// 2 => assert_eq!(segment, "c"),
|
||||
/// _ => panic!("only three segments")
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// A URI with empty segments:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("///a//b///c////d?#");
|
||||
/// for (i, segment) in uri.segments().enumerate() {
|
||||
/// match i {
|
||||
/// 0 => assert_eq!(segment, "a"),
|
||||
/// 1 => assert_eq!(segment, "b"),
|
||||
/// 2 => assert_eq!(segment, "c"),
|
||||
/// 3 => assert_eq!(segment, "d"),
|
||||
/// _ => panic!("only four segments")
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn segments(&self) -> Segments<'a> {
|
||||
Segments(self.path)
|
||||
}
|
||||
|
||||
/// Returns the query part of this URI without the question mark, if there is
|
||||
/// any.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// A URI with a query part:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("/a/b/c?alphabet=true");
|
||||
/// assert_eq!(uri.query(), Some("alphabet=true"));
|
||||
/// ```
|
||||
///
|
||||
/// A URI without the query part:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("/a/b/c");
|
||||
/// assert_eq!(uri.query(), None);
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn query(&self) -> Option<&'a str> {
|
||||
self.query
|
||||
}
|
||||
|
||||
/// Returns the fargment part of this URI without the hash mark, if there is
|
||||
/// any.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// A URI with a fragment part:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("/a?alphabet=true#end");
|
||||
/// assert_eq!(uri.fragment(), Some("end"));
|
||||
/// ```
|
||||
///
|
||||
/// A URI without the fragment part:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("/a?query=true");
|
||||
/// assert_eq!(uri.fragment(), None);
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn fragment(&self) -> Option<&'a str> {
|
||||
self.fragment
|
||||
}
|
||||
|
||||
/// Returns the inner string of this URI.
|
||||
///
|
||||
/// The returned string is in raw form. It contains empty segments. If you'd
|
||||
/// like a string without empty segments, use `to_string` instead.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
///
|
||||
/// let uri = URI::new("/a/b///c/d/e//f?name=Mike#end");
|
||||
/// assert_eq!(uri.as_str(), "/a/b///c/d/e//f?name=Mike#end");
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
self.uri
|
||||
|
@ -73,13 +193,16 @@ impl<'a> URI<'a> {
|
|||
|
||||
impl<'a> fmt::Display for URI<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut last = '\0';
|
||||
for c in self.uri.chars() {
|
||||
if !(c == '/' && last == '/') {
|
||||
f.write_char(c)?;
|
||||
for segment in self.segments() {
|
||||
write!(f, "/{}", segment)?;
|
||||
}
|
||||
|
||||
last = c;
|
||||
if let Some(query_str) = self.query {
|
||||
write!(f, "?{}", query_str)?;
|
||||
}
|
||||
|
||||
if let Some(fragment_str) = self.fragment {
|
||||
write!(f, "#{}", fragment_str)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -89,54 +212,116 @@ impl<'a> fmt::Display for URI<'a> {
|
|||
unsafe impl<'a> Sync for URI<'a> { /* It's safe! */ }
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
/// Owned string type for absolute URIs.
|
||||
///
|
||||
/// This is the owned analog to [URI](struct.URI.html). It serves simply to hold
|
||||
/// the backing String. As a result, most functionality will be achieved through
|
||||
/// the [as_uri](#method.as_uri) method.
|
||||
///
|
||||
/// The exception to this is the [segment_count](#method.segment_count) method,
|
||||
/// which is provided here for performance reasons. This method uses a cached
|
||||
/// count of the segments on subsequent calls. To avoid computing the segment
|
||||
/// count again and again, use the `segment_count` method on URIBuf directly.
|
||||
///
|
||||
/// ## Constructing
|
||||
///
|
||||
/// A URIBuf can be created with either a borrowed or owned string via the
|
||||
/// [new](#method.new) or `from` methods.
|
||||
pub struct URIBuf {
|
||||
uri: String,
|
||||
segment_count: Cell<Option<usize>>,
|
||||
}
|
||||
|
||||
// I don't like repeating all of this stuff. Is there a better way?
|
||||
impl URIBuf {
|
||||
/// Construct a new URIBuf.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// From a borrowed string:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URIBuf;
|
||||
///
|
||||
/// let uri = URIBuf::new("/a/b/c");
|
||||
/// assert_eq!(uri.as_uri().as_str(), "/a/b/c");
|
||||
/// ```
|
||||
///
|
||||
/// From an owned string:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URIBuf;
|
||||
///
|
||||
/// let uri = URIBuf::new("/a/b/c".to_string());
|
||||
/// assert_eq!(uri.as_str(), "/a/b/c");
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn new<S: Into<URIBuf>>(s: S) -> URIBuf {
|
||||
s.into()
|
||||
}
|
||||
|
||||
/// Returns the number of segments in the URI. Empty segments, which are
|
||||
/// invalid according to RFC#3986, are not counted.
|
||||
///
|
||||
/// The segment count is cached after the first invocation. As a result,
|
||||
/// this function is O(1) after the first invocation, and O(n) before.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// A valid URI with only non-empty segments:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URIBuf;
|
||||
///
|
||||
/// let uri = URIBuf::new("/a/b/c");
|
||||
/// assert_eq!(uri.segment_count(), 3);
|
||||
/// ```
|
||||
///
|
||||
/// A URI with empty segments:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URIBuf;
|
||||
///
|
||||
/// let uri = URIBuf::new("/a/b//c/d///e");
|
||||
/// assert_eq!(uri.segment_count(), 5);
|
||||
/// ```
|
||||
pub fn segment_count(&self) -> usize {
|
||||
self.segment_count.get().unwrap_or_else(|| {
|
||||
let count = self.segments().count();
|
||||
let count = self.as_uri().segments().count();
|
||||
self.segment_count.set(Some(count));
|
||||
count
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts this URIBuf into a borrowed URI. Does not consume this URIBuf.
|
||||
#[inline(always)]
|
||||
pub fn segments(&self) -> Segments {
|
||||
self.as_uri_uncached().segments()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn as_uri_uncached(&self) -> URI {
|
||||
pub fn as_uri(&self) -> URI {
|
||||
URI::new(self.uri.as_str())
|
||||
}
|
||||
|
||||
/// Returns the inner string of this URIBuf.
|
||||
///
|
||||
/// The returned string is in raw form. It contains empty segments. If you'd
|
||||
/// like a string without empty segments, use `to_string` instead.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URIBuf;
|
||||
///
|
||||
/// let uri = URIBuf::new("/a/b///c/d/e//f?name=Mike#end");
|
||||
/// assert_eq!(uri.as_str(), "/a/b///c/d/e//f?name=Mike#end");
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn as_uri(&self) -> URI {
|
||||
let mut uri = URI::new(self.uri.as_str());
|
||||
uri.segment_count = self.segment_count.clone();
|
||||
uri
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn as_str(&self) -> &str {
|
||||
pub fn as_str<'a>(&'a self) -> &'a str {
|
||||
self.uri.as_str()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_string(&self) -> String {
|
||||
self.uri.clone()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Sync for URIBuf { /* It's safe! */ }
|
||||
|
||||
impl fmt::Display for URIBuf {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.as_uri_uncached().fmt(f)
|
||||
self.as_uri().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,6 +365,25 @@ impl<'a, 'b> Collider<URI<'b>> for URI<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Iterator over the segments of an absolute URI path. Skips empty segments.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::http::uri::URI;
|
||||
/// use rocket::http::uri::Segments;
|
||||
///
|
||||
/// let segments: Segments = URI::new("/a/////b/c////////d").segments();
|
||||
/// for (i, segment) in segments.enumerate() {
|
||||
/// match i {
|
||||
/// 0 => assert_eq!(segment, "a"),
|
||||
/// 1 => assert_eq!(segment, "b"),
|
||||
/// 2 => assert_eq!(segment, "c"),
|
||||
/// 3 => assert_eq!(segment, "d"),
|
||||
/// _ => panic!("only four segments")
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Segments<'a>(&'a str);
|
||||
|
||||
|
@ -238,7 +442,7 @@ mod tests {
|
|||
let actual: Vec<&str> = uri.segments().collect();
|
||||
|
||||
let uri_buf = URIBuf::from(path);
|
||||
let actual_buf: Vec<&str> = uri_buf.segments().collect();
|
||||
let actual_buf: Vec<&str> = uri_buf.as_uri().segments().collect();
|
||||
|
||||
actual == expected && actual_buf == expected
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
//!
|
||||
//! Then, add the following to top of your `main.rs` file:
|
||||
//!
|
||||
//! ```rust,ignore
|
||||
//! ```rust
|
||||
//! #![feature(plugin)]
|
||||
//! #![plugin(rocket_codegen)]
|
||||
//!
|
||||
|
@ -53,11 +53,38 @@
|
|||
//! ```
|
||||
//!
|
||||
//! See the [guide](https://guide.rocket.rs) for more information on how to
|
||||
//! write Rocket applications.
|
||||
//! write Rocket applications. Here's a simple example to get you started:
|
||||
//!
|
||||
//! ```rust
|
||||
//! #![feature(plugin)]
|
||||
//! #![plugin(rocket_codegen)]
|
||||
//!
|
||||
//! extern crate rocket;
|
||||
//!
|
||||
//! #[get("/")]
|
||||
//! fn hello() -> &'static str {
|
||||
//! "Hello, world!"
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! # if false { // We don't actually want to launch the server in an example.
|
||||
//! rocket::ignite().mount("/", routes![hello]).launch()
|
||||
//! # }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Configuration
|
||||
//!
|
||||
//! Rocket is configured via the `Rocket.toml` file.
|
||||
//! Rocket and Rocket libraries are configured via the `Rocket.toml` file. For
|
||||
//! more information on how to configure Rocket, see the [configuration
|
||||
//! section](/guide/configuration) of the guide as well as the [config](config)
|
||||
//! module documentation.
|
||||
//!
|
||||
//! ## Testing
|
||||
//!
|
||||
//! Rocket includes a small testing library that can be used to test your Rocket
|
||||
//! application. The library's API is unstable. For information on how to test
|
||||
//! your Rocket applications, the [testing module](testing) documentation.
|
||||
//!
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
|
|
|
@ -88,7 +88,7 @@ impl Request {
|
|||
} else {
|
||||
// TODO: Really want to do self.uri.segments().skip(i).into_inner(),
|
||||
// but the std lib doesn't implement it for Skip.
|
||||
let mut segments = self.uri.segments();
|
||||
let mut segments = self.uri.as_uri().segments();
|
||||
for _ in segments.by_ref().take(i) { /* do nothing */ }
|
||||
|
||||
T::from_segments(segments).map_err(|_| Error::BadParse)
|
||||
|
|
|
@ -175,7 +175,7 @@ impl Rocket {
|
|||
pub fn mount(mut self, base: &str, routes: Vec<Route>) -> Self {
|
||||
info!("🛰 {} '{}':", Magenta.paint("Mounting"), base);
|
||||
for mut route in routes {
|
||||
let path = format!("{}/{}", base, route.path.as_str());
|
||||
let path = format!("{}/{}", base, route.path.as_uri());
|
||||
route.set_path(path);
|
||||
|
||||
info_!("{}", route);
|
||||
|
|
|
@ -61,7 +61,7 @@ impl Route {
|
|||
// is, whether you can have: /a<a>b/ or even /<a>:<b>/
|
||||
// TODO: Don't return a Vec...take in an &mut [&'a str] (no alloc!)
|
||||
pub fn get_params<'a>(&self, uri: URI<'a>) -> Vec<&'a str> {
|
||||
let route_segs = self.path.segments();
|
||||
let route_segs = self.path.as_uri().segments();
|
||||
let uri_segs = uri.segments();
|
||||
|
||||
let mut result = Vec::with_capacity(self.path.segment_count());
|
||||
|
|
Loading…
Reference in New Issue