H3: make server receive a Request struct

This commit is contained in:
stammw
2019-05-18 11:16:21 +02:00
committed by Dirkjan Ochtman
parent 8bf597db68
commit 3b79240e44
5 changed files with 72 additions and 9 deletions
+1 -1
View File
@@ -187,7 +187,7 @@ fn handle_connection(
}
fn handle_request(request: RequestReady) -> impl Future<Item = (), Error = Error> {
println!("received request: {:?}", request.headers());
println!("received request: {:?}", request.request());
futures::future::ok(())
}
+6
View File
@@ -83,3 +83,9 @@ impl From<frame::Error> for Error {
}
}
}
impl From<proto::headers::Error> for Error {
fn from(err: proto::headers::Error) -> Error {
Error::Peer(format!("invalid headers: {:?}", err))
}
}
+3
View File
@@ -96,6 +96,7 @@ pub enum Error {
HeaderListTooLarge,
InvalidHeaderName(String),
InvalidHeaderValue(String),
InvalidRequest(String),
Settings { reason: String },
EncodeError { reason: EncoderError },
DecodeError { reason: DecoderError },
@@ -120,6 +121,8 @@ impl From<headers::Error> for Error {
match err {
headers::Error::InvalidHeaderName(s) => Error::InvalidHeaderName(s),
headers::Error::InvalidHeaderValue(s) => Error::InvalidHeaderValue(s),
headers::Error::InvalidRequest(e) => Error::InvalidRequest(format!("{:?}", e)),
headers::Error::MissingMethod => Error::InvalidRequest("missing method".into()),
}
}
}
+25
View File
@@ -29,6 +29,28 @@ impl Header {
}
}
pub fn into_request_parts(self) -> Result<(Method, Uri, HeaderMap), Error> {
let mut uri = Uri::builder();
if let Some(path) = self.pseudo.path {
uri.path_and_query(path.as_bytes());
}
if let Some(scheme) = self.pseudo.scheme {
uri.scheme(scheme.as_bytes());
}
if let Some(authority) = self.pseudo.authority {
uri.authority(authority.as_bytes());
}
Ok((
self.pseudo.method.ok_or(Error::MissingMethod)?,
uri.build().map_err(|e| Error::InvalidRequest(e))?,
self.fields,
))
}
pub fn len(&self) -> usize {
self.pseudo.len() + self.fields.len()
}
@@ -271,9 +293,12 @@ fn to_string(src: Bytes) -> String<Bytes> {
unsafe { String::from_utf8_unchecked(src) }
}
#[derive(Debug)]
pub enum Error {
InvalidHeaderName(std::string::String),
InvalidHeaderValue(std::string::String),
InvalidRequest(http::Error),
MissingMethod,
}
impl Error {
+37 -8
View File
@@ -3,6 +3,7 @@ use std::net::ToSocketAddrs;
use futures::task;
use futures::{try_ready, Async, Future, Poll, Stream};
use http::Request;
use quinn::{EndpointBuilder, EndpointDriver, EndpointError, RecvStream, SendStream};
use quinn_proto::StreamId;
use slog::{self, o, Logger};
@@ -186,12 +187,12 @@ impl Future for RecvRequest {
Some(x) => x,
None => return Err(Error::Internal("Recv request invalid state")),
};
return Ok(Async::Ready(RequestReady {
headers: decoded,
return Ok(Async::Ready(RequestReady::build(
decoded,
frame_stream,
send: Some(send),
conn: self.conn.clone(),
}));
send,
self.conn.clone(),
)?));
}
}
}
@@ -202,14 +203,42 @@ impl Future for RecvRequest {
}
pub struct RequestReady {
headers: Header,
request: Request<()>,
frame_stream: FrameStream<RecvStream>,
send: Option<SendStream>,
conn: ConnectionRef,
}
impl RequestReady {
pub fn headers<'a>(&'a self) -> &'a Header {
&self.headers
fn build(
headers: Header,
frame_stream: FrameStream<RecvStream>,
send: SendStream,
conn: ConnectionRef,
) -> Result<Self, Error> {
let (method, uri, headers) = headers.into_request_parts()?;
let mut request = Request::builder();
request.method(method);
request.uri(uri);
request.version(http::version::Version::HTTP_2); // TODO change once available
match request.headers_mut() {
Some(h) => *h = headers,
None => return Err(Error::peer("invalid header")),
}
let request = request
.body(())
.map_err(|e| Error::Peer(format!("invalid request: {:?}", e)))?;
Ok(Self {
request,
frame_stream,
conn,
send: Some(send),
})
}
pub fn request<'a>(&'a self) -> &'a Request<()> {
&self.request
}
}