mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into payload-read-helpers
This commit is contained in:
commit
d1854b316e
|
@ -12,7 +12,7 @@ pub use self::{decoder::Decoder, encoder::Encoder};
|
||||||
/// Special-purpose writer for streaming (de-)compression.
|
/// Special-purpose writer for streaming (de-)compression.
|
||||||
///
|
///
|
||||||
/// Pre-allocates 8KiB of capacity.
|
/// Pre-allocates 8KiB of capacity.
|
||||||
pub(self) struct Writer {
|
struct Writer {
|
||||||
buf: BytesMut,
|
buf: BytesMut,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_apply_mask() {
|
fn test_apply_mask() {
|
||||||
let mask = [0x6d, 0xb6, 0xb2, 0x80];
|
let mask = [0x6d, 0xb6, 0xb2, 0x80];
|
||||||
let unmasked = vec![
|
let unmasked = [
|
||||||
0xf3, 0x00, 0x01, 0x02, 0x03, 0x80, 0x81, 0x82, 0xff, 0xfe, 0x00, 0x17, 0x74, 0xf9,
|
0xf3, 0x00, 0x01, 0x02, 0x03, 0x80, 0x81, 0x82, 0xff, 0xfe, 0x00, 0x17, 0x74, 0xf9,
|
||||||
0x12, 0x03,
|
0x12, 0x03,
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![allow(clippy::uninlined_format_args)]
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
|
@ -139,7 +137,7 @@ async fn expect_continue_h1() {
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn chunked_payload() {
|
async fn chunked_payload() {
|
||||||
let chunk_sizes = vec![32768, 32, 32768];
|
let chunk_sizes = [32768, 32, 32768];
|
||||||
let total_size: usize = chunk_sizes.iter().sum();
|
let total_size: usize = chunk_sizes.iter().sum();
|
||||||
|
|
||||||
let mut srv = test_server(|| {
|
let mut srv = test_server(|| {
|
||||||
|
@ -402,7 +400,7 @@ async fn content_length() {
|
||||||
let mut srv = test_server(|| {
|
let mut srv = test_server(|| {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h1(|req: Request| {
|
.h1(|req: Request| {
|
||||||
let indx: usize = req.uri().path()[1..].parse().unwrap();
|
let idx: usize = req.uri().path()[1..].parse().unwrap();
|
||||||
let statuses = [
|
let statuses = [
|
||||||
StatusCode::NO_CONTENT,
|
StatusCode::NO_CONTENT,
|
||||||
StatusCode::CONTINUE,
|
StatusCode::CONTINUE,
|
||||||
|
@ -411,7 +409,7 @@ async fn content_length() {
|
||||||
StatusCode::OK,
|
StatusCode::OK,
|
||||||
StatusCode::NOT_FOUND,
|
StatusCode::NOT_FOUND,
|
||||||
];
|
];
|
||||||
ok::<_, Infallible>(Response::new(statuses[indx]))
|
ok::<_, Infallible>(Response::new(statuses[idx]))
|
||||||
})
|
})
|
||||||
.tcp()
|
.tcp()
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Update `syn` dependency to `2`.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency.
|
- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency.
|
||||||
|
|
||||||
## 0.6.0 - 2023-02-26
|
## 0.6.0 - 2023-02-26
|
||||||
|
|
|
@ -17,11 +17,11 @@ all-features = true
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
darling = "0.14"
|
darling = "0.20"
|
||||||
parse-size = "1"
|
parse-size = "1"
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = "1"
|
syn = "2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-multipart = "0.6"
|
actix-multipart = "0.6"
|
||||||
|
|
|
@ -252,7 +252,7 @@ impl ResourceDef {
|
||||||
/// Multi-pattern resources can be constructed by providing a slice (or vec) of patterns.
|
/// Multi-pattern resources can be constructed by providing a slice (or vec) of patterns.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// Panics if path pattern is malformed.
|
/// Panics if any path patterns are malformed.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -838,6 +838,7 @@ impl ResourceDef {
|
||||||
|
|
||||||
fn construct<T: IntoPatterns>(paths: T, is_prefix: bool) -> Self {
|
fn construct<T: IntoPatterns>(paths: T, is_prefix: bool) -> Self {
|
||||||
let patterns = paths.patterns();
|
let patterns = paths.patterns();
|
||||||
|
|
||||||
let (pat_type, segments) = match &patterns {
|
let (pat_type, segments) = match &patterns {
|
||||||
Patterns::Single(pattern) => ResourceDef::parse(pattern, is_prefix, false),
|
Patterns::Single(pattern) => ResourceDef::parse(pattern, is_prefix, false),
|
||||||
|
|
||||||
|
@ -1528,7 +1529,12 @@ mod tests {
|
||||||
assert!(!resource.resource_path_from_iter(&mut s, &mut ["item"].iter()));
|
assert!(!resource.resource_path_from_iter(&mut s, &mut ["item"].iter()));
|
||||||
|
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
assert!(resource.resource_path_from_iter(&mut s, &mut vec!["item", "item2"].iter()));
|
|
||||||
|
assert!(resource.resource_path_from_iter(
|
||||||
|
&mut s,
|
||||||
|
#[allow(clippy::useless_vec)]
|
||||||
|
&mut vec!["item", "item2"].iter()
|
||||||
|
));
|
||||||
assert_eq!(s, "/user/item/item2/");
|
assert_eq!(s, "/user/item/item2/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased - 2023-xx-xx
|
||||||
|
|
||||||
|
- Update `syn` dependency to `2`.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency.
|
- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency.
|
||||||
|
|
||||||
## 4.2.0 - 2023-02-26
|
## 4.2.0 - 2023-02-26
|
||||||
|
|
|
@ -18,10 +18,10 @@ proc-macro = true
|
||||||
actix-router = "0.5"
|
actix-router = "0.5"
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = { version = "1", features = ["full", "extra-traits"] }
|
syn = { version = "2", features = ["full", "extra-traits"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-macros = "0.2.3"
|
actix-macros = "0.2.4"
|
||||||
actix-rt = "2.2"
|
actix-rt = "2.2"
|
||||||
actix-test = "0.1"
|
actix-test = "0.1"
|
||||||
actix-utils = "3"
|
actix-utils = "3"
|
||||||
|
|
|
@ -4,7 +4,54 @@ use actix_router::ResourceDef;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||||
use quote::{quote, ToTokens, TokenStreamExt};
|
use quote::{quote, ToTokens, TokenStreamExt};
|
||||||
use syn::{parse_macro_input, AttributeArgs, Ident, LitStr, Meta, NestedMeta, Path};
|
use syn::{punctuated::Punctuated, Ident, LitStr, Path, Token};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RouteArgs {
|
||||||
|
path: syn::LitStr,
|
||||||
|
options: Punctuated<syn::MetaNameValue, Token![,]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl syn::parse::Parse for RouteArgs {
|
||||||
|
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||||
|
// path to match: "/foo"
|
||||||
|
let path = input.parse::<syn::LitStr>().map_err(|mut err| {
|
||||||
|
err.combine(syn::Error::new(
|
||||||
|
err.span(),
|
||||||
|
r#"invalid service definition, expected #[<method>("<path>")]"#,
|
||||||
|
));
|
||||||
|
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// verify that path pattern is valid
|
||||||
|
let _ = ResourceDef::new(path.value());
|
||||||
|
|
||||||
|
// if there's no comma, assume that no options are provided
|
||||||
|
if !input.peek(Token![,]) {
|
||||||
|
return Ok(Self {
|
||||||
|
path,
|
||||||
|
options: Punctuated::new(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance past comma separator
|
||||||
|
input.parse::<Token![,]>()?;
|
||||||
|
|
||||||
|
// if next char is a literal, assume that it is a string and show multi-path error
|
||||||
|
if input.cursor().literal().is_some() {
|
||||||
|
return Err(syn::Error::new(
|
||||||
|
Span::call_site(),
|
||||||
|
r#"Multiple paths specified! There should be only one."#,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// zero or more options: name = "foo"
|
||||||
|
let options = input.parse_terminated(syn::MetaNameValue::parse, Token![,])?;
|
||||||
|
|
||||||
|
Ok(Self { path, options })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! standard_method_type {
|
macro_rules! standard_method_type {
|
||||||
(
|
(
|
||||||
|
@ -182,111 +229,90 @@ struct Args {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
fn new(args: AttributeArgs, method: Option<MethodType>) -> syn::Result<Self> {
|
fn new(args: RouteArgs, method: Option<MethodType>) -> syn::Result<Self> {
|
||||||
let mut path = None;
|
|
||||||
let mut resource_name = None;
|
let mut resource_name = None;
|
||||||
let mut guards = Vec::new();
|
let mut guards = Vec::new();
|
||||||
let mut wrappers = Vec::new();
|
let mut wrappers = Vec::new();
|
||||||
let mut methods = HashSet::new();
|
let mut methods = HashSet::new();
|
||||||
|
|
||||||
if args.is_empty() {
|
|
||||||
return Err(syn::Error::new(
|
|
||||||
Span::call_site(),
|
|
||||||
format!(
|
|
||||||
r#"invalid service definition, expected #[{}("<path>")]"#,
|
|
||||||
method
|
|
||||||
.map_or("route", |it| it.as_str())
|
|
||||||
.to_ascii_lowercase()
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let is_route_macro = method.is_none();
|
let is_route_macro = method.is_none();
|
||||||
if let Some(method) = method {
|
if let Some(method) = method {
|
||||||
methods.insert(MethodTypeExt::Standard(method));
|
methods.insert(MethodTypeExt::Standard(method));
|
||||||
}
|
}
|
||||||
|
|
||||||
for arg in args {
|
for nv in args.options {
|
||||||
match arg {
|
if nv.path.is_ident("name") {
|
||||||
NestedMeta::Lit(syn::Lit::Str(lit)) => match path {
|
if let syn::Expr::Lit(syn::ExprLit {
|
||||||
None => {
|
lit: syn::Lit::Str(lit),
|
||||||
let _ = ResourceDef::new(lit.value());
|
..
|
||||||
path = Some(lit);
|
}) = nv.value
|
||||||
}
|
{
|
||||||
_ => {
|
resource_name = Some(lit);
|
||||||
return Err(syn::Error::new_spanned(
|
} else {
|
||||||
lit,
|
return Err(syn::Error::new_spanned(
|
||||||
"Multiple paths specified! Should be only one!",
|
nv.value,
|
||||||
));
|
"Attribute name expects literal string!",
|
||||||
}
|
));
|
||||||
},
|
}
|
||||||
|
} else if nv.path.is_ident("guard") {
|
||||||
NestedMeta::Meta(syn::Meta::NameValue(nv)) => {
|
if let syn::Expr::Lit(syn::ExprLit {
|
||||||
if nv.path.is_ident("name") {
|
lit: syn::Lit::Str(lit),
|
||||||
if let syn::Lit::Str(lit) = nv.lit {
|
..
|
||||||
resource_name = Some(lit);
|
}) = nv.value
|
||||||
} else {
|
{
|
||||||
return Err(syn::Error::new_spanned(
|
guards.push(lit.parse::<Path>()?);
|
||||||
nv.lit,
|
} else {
|
||||||
"Attribute name expects literal string!",
|
return Err(syn::Error::new_spanned(
|
||||||
));
|
nv.value,
|
||||||
}
|
"Attribute guard expects literal string!",
|
||||||
} else if nv.path.is_ident("guard") {
|
));
|
||||||
if let syn::Lit::Str(lit) = nv.lit {
|
}
|
||||||
guards.push(lit.parse::<Path>()?);
|
} else if nv.path.is_ident("wrap") {
|
||||||
} else {
|
if let syn::Expr::Lit(syn::ExprLit {
|
||||||
return Err(syn::Error::new_spanned(
|
lit: syn::Lit::Str(lit),
|
||||||
nv.lit,
|
..
|
||||||
"Attribute guard expects literal string!",
|
}) = nv.value
|
||||||
));
|
{
|
||||||
}
|
wrappers.push(lit.parse()?);
|
||||||
} else if nv.path.is_ident("wrap") {
|
} else {
|
||||||
if let syn::Lit::Str(lit) = nv.lit {
|
return Err(syn::Error::new_spanned(
|
||||||
wrappers.push(lit.parse()?);
|
nv.value,
|
||||||
} else {
|
"Attribute wrap expects type",
|
||||||
return Err(syn::Error::new_spanned(
|
));
|
||||||
nv.lit,
|
}
|
||||||
"Attribute wrap expects type",
|
} else if nv.path.is_ident("method") {
|
||||||
));
|
if !is_route_macro {
|
||||||
}
|
return Err(syn::Error::new_spanned(
|
||||||
} else if nv.path.is_ident("method") {
|
|
||||||
if !is_route_macro {
|
|
||||||
return Err(syn::Error::new_spanned(
|
|
||||||
&nv,
|
&nv,
|
||||||
"HTTP method forbidden here. To handle multiple methods, use `route` instead",
|
"HTTP method forbidden here. To handle multiple methods, use `route` instead",
|
||||||
));
|
));
|
||||||
} else if let syn::Lit::Str(ref lit) = nv.lit {
|
} else if let syn::Expr::Lit(syn::ExprLit {
|
||||||
if !methods.insert(MethodTypeExt::try_from(lit)?) {
|
lit: syn::Lit::Str(lit),
|
||||||
return Err(syn::Error::new_spanned(
|
..
|
||||||
&nv.lit,
|
}) = nv.value.clone()
|
||||||
format!(
|
{
|
||||||
"HTTP method defined more than once: `{}`",
|
if !methods.insert(MethodTypeExt::try_from(&lit)?) {
|
||||||
lit.value()
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(syn::Error::new_spanned(
|
|
||||||
nv.lit,
|
|
||||||
"Attribute method expects literal string!",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(syn::Error::new_spanned(
|
return Err(syn::Error::new_spanned(
|
||||||
nv.path,
|
nv.value,
|
||||||
"Unknown attribute key is specified. Allowed: guard, method and wrap",
|
format!("HTTP method defined more than once: `{}`", lit.value()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return Err(syn::Error::new_spanned(
|
||||||
|
nv.value,
|
||||||
|
"Attribute method expects literal string!",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
arg => {
|
return Err(syn::Error::new_spanned(
|
||||||
return Err(syn::Error::new_spanned(arg, "Unknown attribute."));
|
nv.path,
|
||||||
}
|
"Unknown attribute key is specified. Allowed: guard, method and wrap",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Args {
|
Ok(Args {
|
||||||
path: path.unwrap(),
|
path: args.path,
|
||||||
resource_name,
|
resource_name,
|
||||||
guards,
|
guards,
|
||||||
wrappers,
|
wrappers,
|
||||||
|
@ -312,11 +338,7 @@ pub struct Route {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Route {
|
impl Route {
|
||||||
pub fn new(
|
pub fn new(args: RouteArgs, ast: syn::ItemFn, method: Option<MethodType>) -> syn::Result<Self> {
|
||||||
args: AttributeArgs,
|
|
||||||
ast: syn::ItemFn,
|
|
||||||
method: Option<MethodType>,
|
|
||||||
) -> syn::Result<Self> {
|
|
||||||
let name = ast.sig.ident.clone();
|
let name = ast.sig.ident.clone();
|
||||||
|
|
||||||
// Try and pull out the doc comments so that we can reapply them to the generated struct.
|
// Try and pull out the doc comments so that we can reapply them to the generated struct.
|
||||||
|
@ -324,7 +346,7 @@ impl Route {
|
||||||
let doc_attributes = ast
|
let doc_attributes = ast
|
||||||
.attrs
|
.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|attr| attr.path.is_ident("doc"))
|
.filter(|attr| attr.path().is_ident("doc"))
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -360,7 +382,7 @@ impl Route {
|
||||||
let doc_attributes = ast
|
let doc_attributes = ast
|
||||||
.attrs
|
.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|attr| attr.path.is_ident("doc"))
|
.filter(|attr| attr.path().is_ident("doc"))
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -455,7 +477,11 @@ pub(crate) fn with_method(
|
||||||
args: TokenStream,
|
args: TokenStream,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let args = parse_macro_input!(args as syn::AttributeArgs);
|
let args = match syn::parse(args) {
|
||||||
|
Ok(args) => args,
|
||||||
|
// on parse error, make IDEs happy; see fn docs
|
||||||
|
Err(err) => return input_and_compile_error(input, err),
|
||||||
|
};
|
||||||
|
|
||||||
let ast = match syn::parse::<syn::ItemFn>(input.clone()) {
|
let ast = match syn::parse::<syn::ItemFn>(input.clone()) {
|
||||||
Ok(ast) => ast,
|
Ok(ast) => ast,
|
||||||
|
@ -480,7 +506,7 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream {
|
||||||
let (methods, others) = ast
|
let (methods, others) = ast
|
||||||
.attrs
|
.attrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|attr| match MethodType::from_path(&attr.path) {
|
.map(|attr| match MethodType::from_path(attr.path()) {
|
||||||
Ok(method) => Ok((method, attr)),
|
Ok(method) => Ok((method, attr)),
|
||||||
Err(_) => Err(attr),
|
Err(_) => Err(attr),
|
||||||
})
|
})
|
||||||
|
@ -492,13 +518,8 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Result::unwrap)
|
.map(Result::unwrap)
|
||||||
.map(|(method, attr)| {
|
.map(|(method, attr)| {
|
||||||
attr.parse_meta().and_then(|args| {
|
attr.parse_args()
|
||||||
if let Meta::List(args) = args {
|
.and_then(|args| Args::new(args, Some(method)))
|
||||||
Args::new(args.nested.into_iter().collect(), Some(method))
|
|
||||||
} else {
|
|
||||||
Err(syn::Error::new_spanned(attr, "Invalid input for macro"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: invalid service definition, expected #[get("<path>")]
|
error: unexpected end of input, expected string literal
|
||||||
--> tests/trybuild/routes-missing-args-fail.rs:4:1
|
--> tests/trybuild/routes-missing-args-fail.rs:4:1
|
||||||
|
|
|
|
||||||
4 | #[get]
|
4 | #[get]
|
||||||
|
@ -6,11 +6,19 @@ error: invalid service definition, expected #[get("<path>")]
|
||||||
|
|
|
|
||||||
= note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: Invalid input for macro
|
error: invalid service definition, expected #[<method>("<path>")]
|
||||||
--> tests/trybuild/routes-missing-args-fail.rs:4:1
|
--> tests/trybuild/routes-missing-args-fail.rs:4:1
|
||||||
|
|
|
|
||||||
4 | #[get]
|
4 | #[get]
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: expected attribute arguments in parentheses: #[get(...)]
|
||||||
|
--> tests/trybuild/routes-missing-args-fail.rs:4:3
|
||||||
|
|
|
||||||
|
4 | #[get]
|
||||||
|
| ^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `fn() -> impl std::future::Future<Output = String> {index}: HttpServiceFactory` is not satisfied
|
error[E0277]: the trait bound `fn() -> impl std::future::Future<Output = String> {index}: HttpServiceFactory` is not satisfied
|
||||||
--> tests/trybuild/routes-missing-args-fail.rs:13:55
|
--> tests/trybuild/routes-missing-args-fail.rs:13:55
|
||||||
|
|
|
@ -1,26 +1,42 @@
|
||||||
error: Unknown attribute.
|
error: expected `=`
|
||||||
--> $DIR/simple-fail.rs:3:15
|
--> $DIR/simple-fail.rs:3:1
|
||||||
|
|
|
|
||||||
3 | #[get("/one", other)]
|
3 | #[get("/one", other)]
|
||||||
| ^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: expected identifier or literal
|
error: expected string literal
|
||||||
--> $DIR/simple-fail.rs:8:8
|
--> $DIR/simple-fail.rs:8:8
|
||||||
|
|
|
|
||||||
8 | #[post(/two)]
|
8 | #[post(/two)]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: Unknown attribute.
|
error: invalid service definition, expected #[<method>("<path>")]
|
||||||
|
--> $DIR/simple-fail.rs:8:8
|
||||||
|
|
|
||||||
|
8 | #[post(/two)]
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: expected string literal
|
||||||
--> $DIR/simple-fail.rs:15:9
|
--> $DIR/simple-fail.rs:15:9
|
||||||
|
|
|
|
||||||
15 | #[patch(PATCH_PATH)]
|
15 | #[patch(PATCH_PATH)]
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: Multiple paths specified! Should be only one!
|
error: invalid service definition, expected #[<method>("<path>")]
|
||||||
--> $DIR/simple-fail.rs:20:19
|
--> $DIR/simple-fail.rs:15:9
|
||||||
|
|
|
||||||
|
15 | #[patch(PATCH_PATH)]
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: Multiple paths specified! There should be only one.
|
||||||
|
--> $DIR/simple-fail.rs:20:1
|
||||||
|
|
|
|
||||||
20 | #[delete("/four", "/five")]
|
20 | #[delete("/four", "/five")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in the attribute macro `delete` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: HTTP method forbidden here. To handle multiple methods, use `route` instead
|
error: HTTP method forbidden here. To handle multiple methods, use `route` instead
|
||||||
--> $DIR/simple-fail.rs:25:19
|
--> $DIR/simple-fail.rs:25:19
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
- Add `HttpServer::{bind, listen}_auto_h2c()` method behind new `http2` crate feature.
|
- Add `HttpServer::{bind, listen}_auto_h2c()` method behind new `http2` crate feature.
|
||||||
- Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards.
|
- Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards.
|
||||||
- Add `web::Payload::to_bytes[_limited]()` helper methods.
|
- Add `web::Payload::to_bytes[_limited]()` helper methods.
|
||||||
|
- Add missing constructors on `HttpResponse` for several status codes.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ common_header! {
|
||||||
// Tests from the RFC
|
// Tests from the RFC
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test1,
|
test1,
|
||||||
vec![b"audio/*; q=0.2, audio/basic"],
|
[b"audio/*; q=0.2, audio/basic"],
|
||||||
Some(Accept(vec![
|
Some(Accept(vec![
|
||||||
QualityItem::new("audio/*".parse().unwrap(), q(0.2)),
|
QualityItem::new("audio/*".parse().unwrap(), q(0.2)),
|
||||||
QualityItem::max("audio/basic".parse().unwrap()),
|
QualityItem::max("audio/basic".parse().unwrap()),
|
||||||
|
@ -86,7 +86,7 @@ common_header! {
|
||||||
|
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test2,
|
test2,
|
||||||
vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"],
|
[b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"],
|
||||||
Some(Accept(vec![
|
Some(Accept(vec![
|
||||||
QualityItem::new(mime::TEXT_PLAIN, q(0.5)),
|
QualityItem::new(mime::TEXT_PLAIN, q(0.5)),
|
||||||
QualityItem::max(mime::TEXT_HTML),
|
QualityItem::max(mime::TEXT_HTML),
|
||||||
|
@ -99,13 +99,13 @@ common_header! {
|
||||||
// Custom tests
|
// Custom tests
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test3,
|
test3,
|
||||||
vec![b"text/plain; charset=utf-8"],
|
[b"text/plain; charset=utf-8"],
|
||||||
Some(Accept(vec![
|
Some(Accept(vec![
|
||||||
QualityItem::max(mime::TEXT_PLAIN_UTF_8),
|
QualityItem::max(mime::TEXT_PLAIN_UTF_8),
|
||||||
])));
|
])));
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test4,
|
test4,
|
||||||
vec![b"text/plain; charset=utf-8; q=0.5"],
|
[b"text/plain; charset=utf-8; q=0.5"],
|
||||||
Some(Accept(vec![
|
Some(Accept(vec![
|
||||||
QualityItem::new(mime::TEXT_PLAIN_UTF_8, q(0.5)),
|
QualityItem::new(mime::TEXT_PLAIN_UTF_8, q(0.5)),
|
||||||
])));
|
])));
|
||||||
|
|
|
@ -57,6 +57,6 @@ common_header! {
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
// Test case from RFC
|
// Test case from RFC
|
||||||
common_header_test!(test1, vec![b"iso-8859-5, unicode-1-1;q=0.8"]);
|
common_header_test!(test1, [b"iso-8859-5, unicode-1-1;q=0.8"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,31 +50,31 @@ common_header! {
|
||||||
(AcceptEncoding, header::ACCEPT_ENCODING) => (QualityItem<Preference<Encoding>>)*
|
(AcceptEncoding, header::ACCEPT_ENCODING) => (QualityItem<Preference<Encoding>>)*
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
common_header_test!(no_headers, vec![b""; 0], Some(AcceptEncoding(vec![])));
|
common_header_test!(no_headers, [b""; 0], Some(AcceptEncoding(vec![])));
|
||||||
common_header_test!(empty_header, vec![b""; 1], Some(AcceptEncoding(vec![])));
|
common_header_test!(empty_header, [b""; 1], Some(AcceptEncoding(vec![])));
|
||||||
|
|
||||||
common_header_test!(
|
common_header_test!(
|
||||||
order_of_appearance,
|
order_of_appearance,
|
||||||
vec![b"br, gzip"],
|
[b"br, gzip"],
|
||||||
Some(AcceptEncoding(vec![
|
Some(AcceptEncoding(vec![
|
||||||
QualityItem::max(Preference::Specific(Encoding::brotli())),
|
QualityItem::max(Preference::Specific(Encoding::brotli())),
|
||||||
QualityItem::max(Preference::Specific(Encoding::gzip())),
|
QualityItem::max(Preference::Specific(Encoding::gzip())),
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
|
|
||||||
common_header_test!(any, vec![b"*"], Some(AcceptEncoding(vec![
|
common_header_test!(any, [b"*"], Some(AcceptEncoding(vec![
|
||||||
QualityItem::max(Preference::Any),
|
QualityItem::max(Preference::Any),
|
||||||
])));
|
])));
|
||||||
|
|
||||||
// Note: Removed quality 1 from gzip
|
// Note: Removed quality 1 from gzip
|
||||||
common_header_test!(implicit_quality, vec![b"gzip, identity; q=0.5, *;q=0"]);
|
common_header_test!(implicit_quality, [b"gzip, identity; q=0.5, *;q=0"]);
|
||||||
|
|
||||||
// Note: Removed quality 1 from gzip
|
// Note: Removed quality 1 from gzip
|
||||||
common_header_test!(implicit_quality_out_of_order, vec![b"compress;q=0.5, gzip"]);
|
common_header_test!(implicit_quality_out_of_order, [b"compress;q=0.5, gzip"]);
|
||||||
|
|
||||||
common_header_test!(
|
common_header_test!(
|
||||||
only_gzip_no_identity,
|
only_gzip_no_identity,
|
||||||
vec![b"gzip, *; q=0"],
|
[b"gzip, *; q=0"],
|
||||||
Some(AcceptEncoding(vec![
|
Some(AcceptEncoding(vec![
|
||||||
QualityItem::max(Preference::Specific(Encoding::gzip())),
|
QualityItem::max(Preference::Specific(Encoding::gzip())),
|
||||||
QualityItem::zero(Preference::Any),
|
QualityItem::zero(Preference::Any),
|
||||||
|
|
|
@ -58,19 +58,19 @@ common_header! {
|
||||||
(AcceptLanguage, header::ACCEPT_LANGUAGE) => (QualityItem<Preference<LanguageTag>>)*
|
(AcceptLanguage, header::ACCEPT_LANGUAGE) => (QualityItem<Preference<LanguageTag>>)*
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
common_header_test!(no_headers, vec![b""; 0], Some(AcceptLanguage(vec![])));
|
common_header_test!(no_headers, [b""; 0], Some(AcceptLanguage(vec![])));
|
||||||
|
|
||||||
common_header_test!(empty_header, vec![b""; 1], Some(AcceptLanguage(vec![])));
|
common_header_test!(empty_header, [b""; 1], Some(AcceptLanguage(vec![])));
|
||||||
|
|
||||||
common_header_test!(
|
common_header_test!(
|
||||||
example_from_rfc,
|
example_from_rfc,
|
||||||
vec![b"da, en-gb;q=0.8, en;q=0.7"]
|
[b"da, en-gb;q=0.8, en;q=0.7"]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
common_header_test!(
|
common_header_test!(
|
||||||
not_ordered_by_weight,
|
not_ordered_by_weight,
|
||||||
vec![b"en-US, en; q=0.5, fr"],
|
[b"en-US, en; q=0.5, fr"],
|
||||||
Some(AcceptLanguage(vec![
|
Some(AcceptLanguage(vec![
|
||||||
QualityItem::max("en-US".parse().unwrap()),
|
QualityItem::max("en-US".parse().unwrap()),
|
||||||
QualityItem::new("en".parse().unwrap(), q(0.5)),
|
QualityItem::new("en".parse().unwrap(), q(0.5)),
|
||||||
|
@ -80,7 +80,7 @@ common_header! {
|
||||||
|
|
||||||
common_header_test!(
|
common_header_test!(
|
||||||
has_wildcard,
|
has_wildcard,
|
||||||
vec![b"fr-CH, fr; q=0.9, en; q=0.8, de; q=0.7, *; q=0.5"],
|
[b"fr-CH, fr; q=0.9, en; q=0.8, de; q=0.7, *; q=0.5"],
|
||||||
Some(AcceptLanguage(vec![
|
Some(AcceptLanguage(vec![
|
||||||
QualityItem::max("fr-CH".parse().unwrap()),
|
QualityItem::max("fr-CH".parse().unwrap()),
|
||||||
QualityItem::new("fr".parse().unwrap(), q(0.9)),
|
QualityItem::new("fr".parse().unwrap(), q(0.9)),
|
||||||
|
@ -137,7 +137,7 @@ impl AcceptLanguage {
|
||||||
b.quality.cmp(&a.quality)
|
b.quality.cmp(&a.quality)
|
||||||
});
|
});
|
||||||
|
|
||||||
types.into_iter().map(|qitem| qitem.item).collect()
|
types.into_iter().map(|q_item| q_item.item).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,12 +51,12 @@ crate::http::header::common_header! {
|
||||||
// From the RFC
|
// From the RFC
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test1,
|
test1,
|
||||||
vec![b"GET, HEAD, PUT"],
|
[b"GET, HEAD, PUT"],
|
||||||
Some(HeaderField(vec![Method::GET, Method::HEAD, Method::PUT])));
|
Some(HeaderField(vec![Method::GET, Method::HEAD, Method::PUT])));
|
||||||
// Own tests
|
// Own tests
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test2,
|
test2,
|
||||||
vec![b"OPTIONS, GET, PUT, POST, DELETE, HEAD, TRACE, CONNECT, PATCH"],
|
[b"OPTIONS, GET, PUT, POST, DELETE, HEAD, TRACE, CONNECT, PATCH"],
|
||||||
Some(HeaderField(vec![
|
Some(HeaderField(vec![
|
||||||
Method::OPTIONS,
|
Method::OPTIONS,
|
||||||
Method::GET,
|
Method::GET,
|
||||||
|
@ -69,7 +69,7 @@ crate::http::header::common_header! {
|
||||||
Method::PATCH])));
|
Method::PATCH])));
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test3,
|
test3,
|
||||||
vec![b""],
|
[b""],
|
||||||
Some(HeaderField(Vec::<Method>::new())));
|
Some(HeaderField(Vec::<Method>::new())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,13 +47,13 @@ common_header! {
|
||||||
(CacheControl, header::CACHE_CONTROL) => (CacheDirective)+
|
(CacheControl, header::CACHE_CONTROL) => (CacheDirective)+
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
common_header_test!(no_headers, vec![b""; 0], None);
|
common_header_test!(no_headers, [b""; 0], None);
|
||||||
common_header_test!(empty_header, vec![b""; 1], None);
|
common_header_test!(empty_header, [b""; 1], None);
|
||||||
common_header_test!(bad_syntax, vec![b"foo="], None);
|
common_header_test!(bad_syntax, [b"foo="], None);
|
||||||
|
|
||||||
common_header_test!(
|
common_header_test!(
|
||||||
multiple_headers,
|
multiple_headers,
|
||||||
vec![&b"no-cache"[..], &b"private"[..]],
|
[&b"no-cache"[..], &b"private"[..]],
|
||||||
Some(CacheControl(vec![
|
Some(CacheControl(vec![
|
||||||
CacheDirective::NoCache,
|
CacheDirective::NoCache,
|
||||||
CacheDirective::Private,
|
CacheDirective::Private,
|
||||||
|
@ -62,7 +62,7 @@ common_header! {
|
||||||
|
|
||||||
common_header_test!(
|
common_header_test!(
|
||||||
argument,
|
argument,
|
||||||
vec![b"max-age=100, private"],
|
[b"max-age=100, private"],
|
||||||
Some(CacheControl(vec![
|
Some(CacheControl(vec![
|
||||||
CacheDirective::MaxAge(100),
|
CacheDirective::MaxAge(100),
|
||||||
CacheDirective::Private,
|
CacheDirective::Private,
|
||||||
|
@ -71,7 +71,7 @@ common_header! {
|
||||||
|
|
||||||
common_header_test!(
|
common_header_test!(
|
||||||
extension,
|
extension,
|
||||||
vec![b"foo, bar=baz"],
|
[b"foo, bar=baz"],
|
||||||
Some(CacheControl(vec![
|
Some(CacheControl(vec![
|
||||||
CacheDirective::Extension("foo".to_owned(), None),
|
CacheDirective::Extension("foo".to_owned(), None),
|
||||||
CacheDirective::Extension("bar".to_owned(), Some("baz".to_owned())),
|
CacheDirective::Extension("bar".to_owned(), Some("baz".to_owned())),
|
||||||
|
|
|
@ -48,7 +48,7 @@ common_header! {
|
||||||
(ContentLanguage, CONTENT_LANGUAGE) => (QualityItem<LanguageTag>)+
|
(ContentLanguage, CONTENT_LANGUAGE) => (QualityItem<LanguageTag>)+
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
crate::http::header::common_header_test!(test1, vec![b"da"]);
|
crate::http::header::common_header_test!(test1, [b"da"]);
|
||||||
crate::http::header::common_header_test!(test2, vec![b"mi, en"]);
|
crate::http::header::common_header_test!(test2, [b"mi, en"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,59 +13,59 @@ crate::http::header::common_header! {
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
crate::http::header::common_header_test!(test_bytes,
|
crate::http::header::common_header_test!(test_bytes,
|
||||||
vec![b"bytes 0-499/500"],
|
[b"bytes 0-499/500"],
|
||||||
Some(ContentRange(ContentRangeSpec::Bytes {
|
Some(ContentRange(ContentRangeSpec::Bytes {
|
||||||
range: Some((0, 499)),
|
range: Some((0, 499)),
|
||||||
instance_length: Some(500)
|
instance_length: Some(500)
|
||||||
})));
|
})));
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_bytes_unknown_len,
|
crate::http::header::common_header_test!(test_bytes_unknown_len,
|
||||||
vec![b"bytes 0-499/*"],
|
[b"bytes 0-499/*"],
|
||||||
Some(ContentRange(ContentRangeSpec::Bytes {
|
Some(ContentRange(ContentRangeSpec::Bytes {
|
||||||
range: Some((0, 499)),
|
range: Some((0, 499)),
|
||||||
instance_length: None
|
instance_length: None
|
||||||
})));
|
})));
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_bytes_unknown_range,
|
crate::http::header::common_header_test!(test_bytes_unknown_range,
|
||||||
vec![b"bytes */500"],
|
[b"bytes */500"],
|
||||||
Some(ContentRange(ContentRangeSpec::Bytes {
|
Some(ContentRange(ContentRangeSpec::Bytes {
|
||||||
range: None,
|
range: None,
|
||||||
instance_length: Some(500)
|
instance_length: Some(500)
|
||||||
})));
|
})));
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_unregistered,
|
crate::http::header::common_header_test!(test_unregistered,
|
||||||
vec![b"seconds 1-2"],
|
[b"seconds 1-2"],
|
||||||
Some(ContentRange(ContentRangeSpec::Unregistered {
|
Some(ContentRange(ContentRangeSpec::Unregistered {
|
||||||
unit: "seconds".to_owned(),
|
unit: "seconds".to_owned(),
|
||||||
resp: "1-2".to_owned()
|
resp: "1-2".to_owned()
|
||||||
})));
|
})));
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_no_len,
|
crate::http::header::common_header_test!(test_no_len,
|
||||||
vec![b"bytes 0-499"],
|
[b"bytes 0-499"],
|
||||||
None::<ContentRange>);
|
None::<ContentRange>);
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_only_unit,
|
crate::http::header::common_header_test!(test_only_unit,
|
||||||
vec![b"bytes"],
|
[b"bytes"],
|
||||||
None::<ContentRange>);
|
None::<ContentRange>);
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_end_less_than_start,
|
crate::http::header::common_header_test!(test_end_less_than_start,
|
||||||
vec![b"bytes 499-0/500"],
|
[b"bytes 499-0/500"],
|
||||||
None::<ContentRange>);
|
None::<ContentRange>);
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_blank,
|
crate::http::header::common_header_test!(test_blank,
|
||||||
vec![b""],
|
[b""],
|
||||||
None::<ContentRange>);
|
None::<ContentRange>);
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_bytes_many_spaces,
|
crate::http::header::common_header_test!(test_bytes_many_spaces,
|
||||||
vec![b"bytes 1-2/500 3"],
|
[b"bytes 1-2/500 3"],
|
||||||
None::<ContentRange>);
|
None::<ContentRange>);
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_bytes_many_slashes,
|
crate::http::header::common_header_test!(test_bytes_many_slashes,
|
||||||
vec![b"bytes 1-2/500/600"],
|
[b"bytes 1-2/500/600"],
|
||||||
None::<ContentRange>);
|
None::<ContentRange>);
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test_bytes_many_dashes,
|
crate::http::header::common_header_test!(test_bytes_many_dashes,
|
||||||
vec![b"bytes 1-2-3/500"],
|
[b"bytes 1-2-3/500"],
|
||||||
None::<ContentRange>);
|
None::<ContentRange>);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -113,21 +113,13 @@ pub enum ContentRangeSpec {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_in_two(s: &str, separator: char) -> Option<(&str, &str)> {
|
|
||||||
let mut iter = s.splitn(2, separator);
|
|
||||||
match (iter.next(), iter.next()) {
|
|
||||||
(Some(a), Some(b)) => Some((a, b)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ContentRangeSpec {
|
impl FromStr for ContentRangeSpec {
|
||||||
type Err = ParseError;
|
type Err = ParseError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, ParseError> {
|
fn from_str(s: &str) -> Result<Self, ParseError> {
|
||||||
let res = match split_in_two(s, ' ') {
|
let res = match s.split_once(' ') {
|
||||||
Some(("bytes", resp)) => {
|
Some(("bytes", resp)) => {
|
||||||
let (range, instance_length) = split_in_two(resp, '/').ok_or(ParseError::Header)?;
|
let (range, instance_length) = resp.split_once('/').ok_or(ParseError::Header)?;
|
||||||
|
|
||||||
let instance_length = if instance_length == "*" {
|
let instance_length = if instance_length == "*" {
|
||||||
None
|
None
|
||||||
|
@ -139,7 +131,7 @@ impl FromStr for ContentRangeSpec {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let (first_byte, last_byte) =
|
let (first_byte, last_byte) =
|
||||||
split_in_two(range, '-').ok_or(ParseError::Header)?;
|
range.split_once('-').ok_or(ParseError::Header)?;
|
||||||
let first_byte = first_byte.parse().map_err(|_| ParseError::Header)?;
|
let first_byte = first_byte.parse().map_err(|_| ParseError::Header)?;
|
||||||
let last_byte = last_byte.parse().map_err(|_| ParseError::Header)?;
|
let last_byte = last_byte.parse().map_err(|_| ParseError::Header)?;
|
||||||
if last_byte < first_byte {
|
if last_byte < first_byte {
|
||||||
|
|
|
@ -45,11 +45,11 @@ crate::http::header::common_header! {
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test_text_html,
|
test_text_html,
|
||||||
vec![b"text/html"],
|
[b"text/html"],
|
||||||
Some(HeaderField(mime::TEXT_HTML)));
|
Some(HeaderField(mime::TEXT_HTML)));
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test_image_star,
|
test_image_star,
|
||||||
vec![b"image/*"],
|
[b"image/*"],
|
||||||
Some(HeaderField(mime::IMAGE_STAR)));
|
Some(HeaderField(mime::IMAGE_STAR)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ crate::http::header::common_header! {
|
||||||
(Date, DATE) => [HttpDate]
|
(Date, DATE) => [HttpDate]
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
crate::http::header::common_header_test!(test1, vec![b"Tue, 15 Nov 1994 08:12:31 GMT"]);
|
crate::http::header::common_header_test!(test1, [b"Tue, 15 Nov 1994 08:12:31 GMT"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,50 +49,50 @@ crate::http::header::common_header! {
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
// From the RFC
|
// From the RFC
|
||||||
crate::http::header::common_header_test!(test1,
|
crate::http::header::common_header_test!(test1,
|
||||||
vec![b"\"xyzzy\""],
|
[b"\"xyzzy\""],
|
||||||
Some(ETag(EntityTag::new_strong("xyzzy".to_owned()))));
|
Some(ETag(EntityTag::new_strong("xyzzy".to_owned()))));
|
||||||
crate::http::header::common_header_test!(test2,
|
crate::http::header::common_header_test!(test2,
|
||||||
vec![b"W/\"xyzzy\""],
|
[b"W/\"xyzzy\""],
|
||||||
Some(ETag(EntityTag::new_weak("xyzzy".to_owned()))));
|
Some(ETag(EntityTag::new_weak("xyzzy".to_owned()))));
|
||||||
crate::http::header::common_header_test!(test3,
|
crate::http::header::common_header_test!(test3,
|
||||||
vec![b"\"\""],
|
[b"\"\""],
|
||||||
Some(ETag(EntityTag::new_strong("".to_owned()))));
|
Some(ETag(EntityTag::new_strong("".to_owned()))));
|
||||||
// Own tests
|
// Own tests
|
||||||
crate::http::header::common_header_test!(test4,
|
crate::http::header::common_header_test!(test4,
|
||||||
vec![b"\"foobar\""],
|
[b"\"foobar\""],
|
||||||
Some(ETag(EntityTag::new_strong("foobar".to_owned()))));
|
Some(ETag(EntityTag::new_strong("foobar".to_owned()))));
|
||||||
crate::http::header::common_header_test!(test5,
|
crate::http::header::common_header_test!(test5,
|
||||||
vec![b"\"\""],
|
[b"\"\""],
|
||||||
Some(ETag(EntityTag::new_strong("".to_owned()))));
|
Some(ETag(EntityTag::new_strong("".to_owned()))));
|
||||||
crate::http::header::common_header_test!(test6,
|
crate::http::header::common_header_test!(test6,
|
||||||
vec![b"W/\"weak-etag\""],
|
[b"W/\"weak-etag\""],
|
||||||
Some(ETag(EntityTag::new_weak("weak-etag".to_owned()))));
|
Some(ETag(EntityTag::new_weak("weak-etag".to_owned()))));
|
||||||
crate::http::header::common_header_test!(test7,
|
crate::http::header::common_header_test!(test7,
|
||||||
vec![b"W/\"\x65\x62\""],
|
[b"W/\"\x65\x62\""],
|
||||||
Some(ETag(EntityTag::new_weak("\u{0065}\u{0062}".to_owned()))));
|
Some(ETag(EntityTag::new_weak("\u{0065}\u{0062}".to_owned()))));
|
||||||
crate::http::header::common_header_test!(test8,
|
crate::http::header::common_header_test!(test8,
|
||||||
vec![b"W/\"\""],
|
[b"W/\"\""],
|
||||||
Some(ETag(EntityTag::new_weak("".to_owned()))));
|
Some(ETag(EntityTag::new_weak("".to_owned()))));
|
||||||
crate::http::header::common_header_test!(test9,
|
crate::http::header::common_header_test!(test9,
|
||||||
vec![b"no-dquotes"],
|
[b"no-dquotes"],
|
||||||
None::<ETag>);
|
None::<ETag>);
|
||||||
crate::http::header::common_header_test!(test10,
|
crate::http::header::common_header_test!(test10,
|
||||||
vec![b"w/\"the-first-w-is-case-sensitive\""],
|
[b"w/\"the-first-w-is-case-sensitive\""],
|
||||||
None::<ETag>);
|
None::<ETag>);
|
||||||
crate::http::header::common_header_test!(test11,
|
crate::http::header::common_header_test!(test11,
|
||||||
vec![b""],
|
[b""],
|
||||||
None::<ETag>);
|
None::<ETag>);
|
||||||
crate::http::header::common_header_test!(test12,
|
crate::http::header::common_header_test!(test12,
|
||||||
vec![b"\"unmatched-dquotes1"],
|
[b"\"unmatched-dquotes1"],
|
||||||
None::<ETag>);
|
None::<ETag>);
|
||||||
crate::http::header::common_header_test!(test13,
|
crate::http::header::common_header_test!(test13,
|
||||||
vec![b"unmatched-dquotes2\""],
|
[b"unmatched-dquotes2\""],
|
||||||
None::<ETag>);
|
None::<ETag>);
|
||||||
crate::http::header::common_header_test!(test14,
|
crate::http::header::common_header_test!(test14,
|
||||||
vec![b"matched-\"dquotes\""],
|
[b"matched-\"dquotes\""],
|
||||||
None::<ETag>);
|
None::<ETag>);
|
||||||
crate::http::header::common_header_test!(test15,
|
crate::http::header::common_header_test!(test15,
|
||||||
vec![b"\""],
|
[b"\""],
|
||||||
None::<ETag>);
|
None::<ETag>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,6 @@ crate::http::header::common_header! {
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
// Test case from RFC
|
// Test case from RFC
|
||||||
crate::http::header::common_header_test!(test1, vec![b"Thu, 01 Dec 1994 16:00:00 GMT"]);
|
crate::http::header::common_header_test!(test1, [b"Thu, 01 Dec 1994 16:00:00 GMT"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,17 +52,17 @@ common_header! {
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test1,
|
test1,
|
||||||
vec![b"\"xyzzy\""],
|
[b"\"xyzzy\""],
|
||||||
Some(HeaderField::Items(
|
Some(HeaderField::Items(
|
||||||
vec![EntityTag::new_strong("xyzzy".to_owned())])));
|
vec![EntityTag::new_strong("xyzzy".to_owned())])));
|
||||||
|
|
||||||
crate::http::header::common_header_test!(
|
crate::http::header::common_header_test!(
|
||||||
test2,
|
test2,
|
||||||
vec![b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""],
|
[b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""],
|
||||||
Some(HeaderField::Items(
|
Some(HeaderField::Items(
|
||||||
vec![EntityTag::new_strong("xyzzy".to_owned()),
|
vec![EntityTag::new_strong("xyzzy".to_owned()),
|
||||||
EntityTag::new_strong("r2d2xxxx".to_owned()),
|
EntityTag::new_strong("r2d2xxxx".to_owned()),
|
||||||
EntityTag::new_strong("c3piozzzz".to_owned())])));
|
EntityTag::new_strong("c3piozzzz".to_owned())])));
|
||||||
crate::http::header::common_header_test!(test3, vec![b"*"], Some(IfMatch::Any));
|
crate::http::header::common_header_test!(test3, [b"*"], Some(IfMatch::Any));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,6 @@ crate::http::header::common_header! {
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
// Test case from RFC
|
// Test case from RFC
|
||||||
crate::http::header::common_header_test!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
crate::http::header::common_header_test!(test1, [b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,11 +52,11 @@ crate::http::header::common_header! {
|
||||||
(IfNoneMatch, IF_NONE_MATCH) => {Any / (EntityTag)+}
|
(IfNoneMatch, IF_NONE_MATCH) => {Any / (EntityTag)+}
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
crate::http::header::common_header_test!(test1, vec![b"\"xyzzy\""]);
|
crate::http::header::common_header_test!(test1, [b"\"xyzzy\""]);
|
||||||
crate::http::header::common_header_test!(test2, vec![b"W/\"xyzzy\""]);
|
crate::http::header::common_header_test!(test2, [b"W/\"xyzzy\""]);
|
||||||
crate::http::header::common_header_test!(test3, vec![b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""]);
|
crate::http::header::common_header_test!(test3, [b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""]);
|
||||||
crate::http::header::common_header_test!(test4, vec![b"W/\"xyzzy\", W/\"r2d2xxxx\", W/\"c3piozzzz\""]);
|
crate::http::header::common_header_test!(test4, [b"W/\"xyzzy\", W/\"r2d2xxxx\", W/\"c3piozzzz\""]);
|
||||||
crate::http::header::common_header_test!(test5, vec![b"*"]);
|
crate::http::header::common_header_test!(test5, [b"*"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ mod test_parse_and_format {
|
||||||
use super::IfRange as HeaderField;
|
use super::IfRange as HeaderField;
|
||||||
use crate::http::header::*;
|
use crate::http::header::*;
|
||||||
|
|
||||||
crate::http::header::common_header_test!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
crate::http::header::common_header_test!(test1, [b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
||||||
crate::http::header::common_header_test!(test2, vec![b"\"abc\""]);
|
crate::http::header::common_header_test!(test2, [b"\"abc\""]);
|
||||||
crate::http::header::common_header_test!(test3, vec![b"this-is-invalid"], None::<IfRange>);
|
crate::http::header::common_header_test!(test3, [b"this-is-invalid"], None::<IfRange>);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,6 @@ crate::http::header::common_header! {
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
// Test case from RFC
|
// Test case from RFC
|
||||||
crate::http::header::common_header_test!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
crate::http::header::common_header_test!(test1, [b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,6 @@ crate::http::header::common_header! {
|
||||||
|
|
||||||
test_parse_and_format {
|
test_parse_and_format {
|
||||||
// Test case from RFC
|
// Test case from RFC
|
||||||
crate::http::header::common_header_test!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
crate::http::header::common_header_test!(test1, [b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@ impl HttpResponse {
|
||||||
NonAuthoritativeInformation,
|
NonAuthoritativeInformation,
|
||||||
StatusCode::NON_AUTHORITATIVE_INFORMATION
|
StatusCode::NON_AUTHORITATIVE_INFORMATION
|
||||||
);
|
);
|
||||||
|
|
||||||
static_resp!(NoContent, StatusCode::NO_CONTENT);
|
static_resp!(NoContent, StatusCode::NO_CONTENT);
|
||||||
static_resp!(ResetContent, StatusCode::RESET_CONTENT);
|
static_resp!(ResetContent, StatusCode::RESET_CONTENT);
|
||||||
static_resp!(PartialContent, StatusCode::PARTIAL_CONTENT);
|
static_resp!(PartialContent, StatusCode::PARTIAL_CONTENT);
|
||||||
static_resp!(MultiStatus, StatusCode::MULTI_STATUS);
|
static_resp!(MultiStatus, StatusCode::MULTI_STATUS);
|
||||||
static_resp!(AlreadyReported, StatusCode::ALREADY_REPORTED);
|
static_resp!(AlreadyReported, StatusCode::ALREADY_REPORTED);
|
||||||
|
static_resp!(ImUsed, StatusCode::IM_USED);
|
||||||
|
|
||||||
static_resp!(MultipleChoices, StatusCode::MULTIPLE_CHOICES);
|
static_resp!(MultipleChoices, StatusCode::MULTIPLE_CHOICES);
|
||||||
static_resp!(MovedPermanently, StatusCode::MOVED_PERMANENTLY);
|
static_resp!(MovedPermanently, StatusCode::MOVED_PERMANENTLY);
|
||||||
|
@ -42,10 +42,10 @@ impl HttpResponse {
|
||||||
static_resp!(PermanentRedirect, StatusCode::PERMANENT_REDIRECT);
|
static_resp!(PermanentRedirect, StatusCode::PERMANENT_REDIRECT);
|
||||||
|
|
||||||
static_resp!(BadRequest, StatusCode::BAD_REQUEST);
|
static_resp!(BadRequest, StatusCode::BAD_REQUEST);
|
||||||
static_resp!(NotFound, StatusCode::NOT_FOUND);
|
|
||||||
static_resp!(Unauthorized, StatusCode::UNAUTHORIZED);
|
static_resp!(Unauthorized, StatusCode::UNAUTHORIZED);
|
||||||
static_resp!(PaymentRequired, StatusCode::PAYMENT_REQUIRED);
|
static_resp!(PaymentRequired, StatusCode::PAYMENT_REQUIRED);
|
||||||
static_resp!(Forbidden, StatusCode::FORBIDDEN);
|
static_resp!(Forbidden, StatusCode::FORBIDDEN);
|
||||||
|
static_resp!(NotFound, StatusCode::NOT_FOUND);
|
||||||
static_resp!(MethodNotAllowed, StatusCode::METHOD_NOT_ALLOWED);
|
static_resp!(MethodNotAllowed, StatusCode::METHOD_NOT_ALLOWED);
|
||||||
static_resp!(NotAcceptable, StatusCode::NOT_ACCEPTABLE);
|
static_resp!(NotAcceptable, StatusCode::NOT_ACCEPTABLE);
|
||||||
static_resp!(
|
static_resp!(
|
||||||
|
@ -57,13 +57,18 @@ impl HttpResponse {
|
||||||
static_resp!(Gone, StatusCode::GONE);
|
static_resp!(Gone, StatusCode::GONE);
|
||||||
static_resp!(LengthRequired, StatusCode::LENGTH_REQUIRED);
|
static_resp!(LengthRequired, StatusCode::LENGTH_REQUIRED);
|
||||||
static_resp!(PreconditionFailed, StatusCode::PRECONDITION_FAILED);
|
static_resp!(PreconditionFailed, StatusCode::PRECONDITION_FAILED);
|
||||||
static_resp!(PreconditionRequired, StatusCode::PRECONDITION_REQUIRED);
|
|
||||||
static_resp!(PayloadTooLarge, StatusCode::PAYLOAD_TOO_LARGE);
|
static_resp!(PayloadTooLarge, StatusCode::PAYLOAD_TOO_LARGE);
|
||||||
static_resp!(UriTooLong, StatusCode::URI_TOO_LONG);
|
static_resp!(UriTooLong, StatusCode::URI_TOO_LONG);
|
||||||
static_resp!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE);
|
static_resp!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE);
|
||||||
static_resp!(RangeNotSatisfiable, StatusCode::RANGE_NOT_SATISFIABLE);
|
static_resp!(RangeNotSatisfiable, StatusCode::RANGE_NOT_SATISFIABLE);
|
||||||
static_resp!(ExpectationFailed, StatusCode::EXPECTATION_FAILED);
|
static_resp!(ExpectationFailed, StatusCode::EXPECTATION_FAILED);
|
||||||
|
static_resp!(ImATeapot, StatusCode::IM_A_TEAPOT);
|
||||||
|
static_resp!(MisdirectedRequest, StatusCode::MISDIRECTED_REQUEST);
|
||||||
static_resp!(UnprocessableEntity, StatusCode::UNPROCESSABLE_ENTITY);
|
static_resp!(UnprocessableEntity, StatusCode::UNPROCESSABLE_ENTITY);
|
||||||
|
static_resp!(Locked, StatusCode::LOCKED);
|
||||||
|
static_resp!(FailedDependency, StatusCode::FAILED_DEPENDENCY);
|
||||||
|
static_resp!(UpgradeRequired, StatusCode::UPGRADE_REQUIRED);
|
||||||
|
static_resp!(PreconditionRequired, StatusCode::PRECONDITION_REQUIRED);
|
||||||
static_resp!(TooManyRequests, StatusCode::TOO_MANY_REQUESTS);
|
static_resp!(TooManyRequests, StatusCode::TOO_MANY_REQUESTS);
|
||||||
static_resp!(
|
static_resp!(
|
||||||
RequestHeaderFieldsTooLarge,
|
RequestHeaderFieldsTooLarge,
|
||||||
|
@ -83,6 +88,11 @@ impl HttpResponse {
|
||||||
static_resp!(VariantAlsoNegotiates, StatusCode::VARIANT_ALSO_NEGOTIATES);
|
static_resp!(VariantAlsoNegotiates, StatusCode::VARIANT_ALSO_NEGOTIATES);
|
||||||
static_resp!(InsufficientStorage, StatusCode::INSUFFICIENT_STORAGE);
|
static_resp!(InsufficientStorage, StatusCode::INSUFFICIENT_STORAGE);
|
||||||
static_resp!(LoopDetected, StatusCode::LOOP_DETECTED);
|
static_resp!(LoopDetected, StatusCode::LOOP_DETECTED);
|
||||||
|
static_resp!(NotExtended, StatusCode::NOT_EXTENDED);
|
||||||
|
static_resp!(
|
||||||
|
NetworkAuthenticationRequired,
|
||||||
|
StatusCode::NETWORK_AUTHENTICATION_REQUIRED
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in New Issue