committed by
Sean McArthur
parent
0527f5b72a
commit
fac165e451
@@ -1,10 +1,10 @@
|
||||
use super::*;
|
||||
use crate::codec::{RecvError, UserError};
|
||||
use crate::frame::{Reason, DEFAULT_INITIAL_WINDOW_SIZE};
|
||||
use crate::frame::{PushPromiseHeaderError, Reason, DEFAULT_INITIAL_WINDOW_SIZE};
|
||||
use crate::{frame, proto};
|
||||
use std::task::Context;
|
||||
|
||||
use http::{HeaderMap, Method, Request, Response};
|
||||
use http::{HeaderMap, Request, Response};
|
||||
|
||||
use std::io;
|
||||
use std::task::{Poll, Waker};
|
||||
@@ -178,7 +178,7 @@ impl Recv {
|
||||
use http::header;
|
||||
|
||||
if let Some(content_length) = frame.fields().get(header::CONTENT_LENGTH) {
|
||||
let content_length = match parse_u64(content_length.as_bytes()) {
|
||||
let content_length = match frame::parse_u64(content_length.as_bytes()) {
|
||||
Ok(v) => v,
|
||||
Err(()) => {
|
||||
proto_err!(stream: "could not parse content-length; stream={:?}", stream.id);
|
||||
@@ -632,44 +632,31 @@ impl Recv {
|
||||
}
|
||||
|
||||
let promised_id = frame.promised_id();
|
||||
use http::header;
|
||||
let (pseudo, fields) = frame.into_parts();
|
||||
let req = crate::server::Peer::convert_poll_message(pseudo, fields, promised_id)?;
|
||||
// The spec has some requirements for promised request headers
|
||||
// [https://httpwg.org/specs/rfc7540.html#PushRequests]
|
||||
|
||||
// A promised request "that indicates the presence of a request body
|
||||
// MUST reset the promised stream with a stream error"
|
||||
if let Some(content_length) = req.headers().get(header::CONTENT_LENGTH) {
|
||||
match parse_u64(content_length.as_bytes()) {
|
||||
Ok(0) => {}
|
||||
otherwise => {
|
||||
proto_err!(stream:
|
||||
"recv_push_promise; promised request has content-length {:?}; promised_id={:?}",
|
||||
otherwise,
|
||||
promised_id,
|
||||
);
|
||||
return Err(RecvError::Stream {
|
||||
id: promised_id,
|
||||
reason: Reason::PROTOCOL_ERROR,
|
||||
});
|
||||
}
|
||||
if let Err(e) = frame::PushPromise::validate_request(&req) {
|
||||
use PushPromiseHeaderError::*;
|
||||
match e {
|
||||
NotSafeAndCacheable => proto_err!(
|
||||
stream:
|
||||
"recv_push_promise: method {} is not safe and cacheable; promised_id={:?}",
|
||||
req.method(),
|
||||
promised_id,
|
||||
),
|
||||
InvalidContentLength(e) => proto_err!(
|
||||
stream:
|
||||
"recv_push_promise; promised request has invalid content-length {:?}; promised_id={:?}",
|
||||
e,
|
||||
promised_id,
|
||||
),
|
||||
}
|
||||
}
|
||||
// "The server MUST include a method in the :method pseudo-header field
|
||||
// that is safe and cacheable"
|
||||
if !Self::safe_and_cacheable(req.method()) {
|
||||
proto_err!(
|
||||
stream:
|
||||
"recv_push_promise: method {} is not safe and cacheable; promised_id={:?}",
|
||||
req.method(),
|
||||
promised_id,
|
||||
);
|
||||
return Err(RecvError::Stream {
|
||||
id: promised_id,
|
||||
reason: Reason::PROTOCOL_ERROR,
|
||||
});
|
||||
}
|
||||
|
||||
use super::peer::PollMessage::*;
|
||||
stream
|
||||
.pending_recv
|
||||
@@ -678,12 +665,6 @@ impl Recv {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn safe_and_cacheable(method: &Method) -> bool {
|
||||
// Cacheable: https://httpwg.org/specs/rfc7231.html#cacheable.methods
|
||||
// Safe: https://httpwg.org/specs/rfc7231.html#safe.methods
|
||||
method == Method::GET || method == Method::HEAD
|
||||
}
|
||||
|
||||
/// Ensures that `id` is not in the `Idle` state.
|
||||
pub fn ensure_not_idle(&self, id: StreamId) -> Result<(), Reason> {
|
||||
if let Ok(next) = self.next_stream_id {
|
||||
@@ -1057,25 +1038,3 @@ impl<T> From<RecvError> for RecvHeaderBlockError<T> {
|
||||
RecvHeaderBlockError::State(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ===== util =====
|
||||
|
||||
fn parse_u64(src: &[u8]) -> Result<u64, ()> {
|
||||
if src.len() > 19 {
|
||||
// At danger for overflow...
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let mut ret = 0;
|
||||
|
||||
for &d in src {
|
||||
if d < b'0' || d > b'9' {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
ret *= 10;
|
||||
ret += u64::from(d - b'0');
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user