Add type aliases for Response/Request with a fixed body type

Simplifies correct usage of the API.
pull/93/head
Sebastian Dröge 5 years ago
parent 1ecc4f900d
commit 07d4721ffd
  1. 41
      src/client.rs
  2. 20
      src/handshake/client.rs
  3. 41
      src/handshake/server.rs

@ -4,11 +4,12 @@ use std::io::{Read, Write};
use std::net::{SocketAddr, TcpStream, ToSocketAddrs}; use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use std::result::Result as StdResult; use std::result::Result as StdResult;
use http::{Request, Response, Uri}; use http::Uri;
use log::*; use log::*;
use url::Url; use url::Url;
use crate::handshake::client::{Request, Response};
use crate::protocol::WebSocketConfig; use crate::protocol::WebSocketConfig;
#[cfg(feature = "tls")] #[cfg(feature = "tls")]
@ -88,8 +89,8 @@ use crate::stream::{Mode, NoDelay};
pub fn connect_with_config<Req: IntoClientRequest>( pub fn connect_with_config<Req: IntoClientRequest>(
request: Req, request: Req,
config: Option<WebSocketConfig>, config: Option<WebSocketConfig>,
) -> Result<(WebSocket<AutoStream>, Response<()>)> { ) -> Result<(WebSocket<AutoStream>, Response)> {
let request: Request<()> = request.into_client_request()?; let request: Request = request.into_client_request()?;
let uri = request.uri(); let uri = request.uri();
let mode = uri_mode(uri)?; let mode = uri_mode(uri)?;
let host = request let host = request
@ -121,9 +122,7 @@ pub fn connect_with_config<Req: IntoClientRequest>(
/// This function uses `native_tls` to do TLS. If you want to use other TLS libraries, /// This function uses `native_tls` to do TLS. If you want to use other TLS libraries,
/// use `client` instead. There is no need to enable the "tls" feature if you don't call /// use `client` instead. There is no need to enable the "tls" feature if you don't call
/// `connect` since it's the only function that uses native_tls. /// `connect` since it's the only function that uses native_tls.
pub fn connect<Req: IntoClientRequest>( pub fn connect<Req: IntoClientRequest>(request: Req) -> Result<(WebSocket<AutoStream>, Response)> {
request: Req,
) -> Result<(WebSocket<AutoStream>, Response<()>)> {
connect_with_config(request, None) connect_with_config(request, None)
} }
@ -164,7 +163,7 @@ pub fn client_with_config<Stream, Req>(
request: Req, request: Req,
stream: Stream, stream: Stream,
config: Option<WebSocketConfig>, config: Option<WebSocketConfig>,
) -> StdResult<(WebSocket<Stream>, Response<()>), HandshakeError<ClientHandshake<Stream>>> ) -> StdResult<(WebSocket<Stream>, Response), HandshakeError<ClientHandshake<Stream>>>
where where
Stream: Read + Write, Stream: Read + Write,
Req: IntoClientRequest, Req: IntoClientRequest,
@ -180,7 +179,7 @@ where
pub fn client<Stream, Req>( pub fn client<Stream, Req>(
request: Req, request: Req,
stream: Stream, stream: Stream,
) -> StdResult<(WebSocket<Stream>, Response<()>), HandshakeError<ClientHandshake<Stream>>> ) -> StdResult<(WebSocket<Stream>, Response), HandshakeError<ClientHandshake<Stream>>>
where where
Stream: Read + Write, Stream: Read + Write,
Req: IntoClientRequest, Req: IntoClientRequest,
@ -193,12 +192,12 @@ where
/// This trait is implemented by default for string slices, strings, `url::Url`, `http::Uri` and /// This trait is implemented by default for string slices, strings, `url::Url`, `http::Uri` and
/// `http::Request<()>`. /// `http::Request<()>`.
pub trait IntoClientRequest { pub trait IntoClientRequest {
/// Convert into a `Request<()>` that can be used for a client connection. /// Convert into a `Request` that can be used for a client connection.
fn into_client_request(self) -> Result<Request<()>>; fn into_client_request(self) -> Result<Request>;
} }
impl<'a> IntoClientRequest for &'a str { impl<'a> IntoClientRequest for &'a str {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
let uri: Uri = self.parse()?; let uri: Uri = self.parse()?;
Ok(Request::get(uri).body(())?) Ok(Request::get(uri).body(())?)
@ -206,7 +205,7 @@ impl<'a> IntoClientRequest for &'a str {
} }
impl<'a> IntoClientRequest for &'a String { impl<'a> IntoClientRequest for &'a String {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
let uri: Uri = self.parse()?; let uri: Uri = self.parse()?;
Ok(Request::get(uri).body(())?) Ok(Request::get(uri).body(())?)
@ -214,7 +213,7 @@ impl<'a> IntoClientRequest for &'a String {
} }
impl IntoClientRequest for String { impl IntoClientRequest for String {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
let uri: Uri = self.parse()?; let uri: Uri = self.parse()?;
Ok(Request::get(uri).body(())?) Ok(Request::get(uri).body(())?)
@ -222,19 +221,19 @@ impl IntoClientRequest for String {
} }
impl<'a> IntoClientRequest for &'a Uri { impl<'a> IntoClientRequest for &'a Uri {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
Ok(Request::get(self.clone()).body(())?) Ok(Request::get(self.clone()).body(())?)
} }
} }
impl IntoClientRequest for Uri { impl IntoClientRequest for Uri {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
Ok(Request::get(self).body(())?) Ok(Request::get(self).body(())?)
} }
} }
impl<'a> IntoClientRequest for &'a Url { impl<'a> IntoClientRequest for &'a Url {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
let uri: Uri = self.as_str().parse()?; let uri: Uri = self.as_str().parse()?;
Ok(Request::get(uri).body(())?) Ok(Request::get(uri).body(())?)
@ -242,22 +241,22 @@ impl<'a> IntoClientRequest for &'a Url {
} }
impl IntoClientRequest for Url { impl IntoClientRequest for Url {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
let uri: Uri = self.as_str().parse()?; let uri: Uri = self.as_str().parse()?;
Ok(Request::get(uri).body(())?) Ok(Request::get(uri).body(())?)
} }
} }
impl IntoClientRequest for Request<()> { impl IntoClientRequest for Request {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
Ok(self) Ok(self)
} }
} }
impl<'h, 'b> IntoClientRequest for httparse::Request<'h, 'b> { impl<'h, 'b> IntoClientRequest for httparse::Request<'h, 'b> {
fn into_client_request(self) -> Result<Request<()>> { fn into_client_request(self) -> Result<Request> {
use crate::handshake::headers::FromHttparse; use crate::handshake::headers::FromHttparse;
Request::<()>::from_httparse(self) Request::from_httparse(self)
} }
} }

@ -3,7 +3,7 @@
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::marker::PhantomData; use std::marker::PhantomData;
use http::{HeaderMap, Request, Response, StatusCode}; use http::{HeaderMap, Request as HttpRequest, Response as HttpResponse, StatusCode};
use httparse::Status; use httparse::Status;
use log::*; use log::*;
@ -13,6 +13,12 @@ use super::{convert_key, HandshakeRole, MidHandshake, ProcessingResult};
use crate::error::{Error, Result}; use crate::error::{Error, Result};
use crate::protocol::{Role, WebSocket, WebSocketConfig}; use crate::protocol::{Role, WebSocket, WebSocketConfig};
/// Client request type.
pub type Request = HttpRequest<()>;
/// Client response type.
pub type Response = HttpResponse<()>;
/// Client handshake role. /// Client handshake role.
#[derive(Debug)] #[derive(Debug)]
pub struct ClientHandshake<S> { pub struct ClientHandshake<S> {
@ -25,7 +31,7 @@ impl<S: Read + Write> ClientHandshake<S> {
/// Initiate a client handshake. /// Initiate a client handshake.
pub fn start( pub fn start(
stream: S, stream: S,
request: Request<()>, request: Request,
config: Option<WebSocketConfig>, config: Option<WebSocketConfig>,
) -> Result<MidHandshake<Self>> { ) -> Result<MidHandshake<Self>> {
if request.method() != http::Method::GET { if request.method() != http::Method::GET {
@ -93,9 +99,9 @@ impl<S: Read + Write> ClientHandshake<S> {
} }
impl<S: Read + Write> HandshakeRole for ClientHandshake<S> { impl<S: Read + Write> HandshakeRole for ClientHandshake<S> {
type IncomingData = Response<()>; type IncomingData = Response;
type InternalStream = S; type InternalStream = S;
type FinalResult = (WebSocket<S>, Response<()>); type FinalResult = (WebSocket<S>, Response);
fn stage_finished( fn stage_finished(
&mut self, &mut self,
finish: StageResult<Self::IncomingData, Self::InternalStream>, finish: StageResult<Self::IncomingData, Self::InternalStream>,
@ -127,7 +133,7 @@ struct VerifyData {
} }
impl VerifyData { impl VerifyData {
pub fn verify_response(&self, response: &Response<()>) -> Result<()> { pub fn verify_response(&self, response: &Response) -> Result<()> {
// 1. If the status code received from the server is not 101, the // 1. If the status code received from the server is not 101, the
// client handles the response per HTTP [RFC2616] procedures. (RFC 6455) // client handles the response per HTTP [RFC2616] procedures. (RFC 6455)
if response.status() != StatusCode::SWITCHING_PROTOCOLS { if response.status() != StatusCode::SWITCHING_PROTOCOLS {
@ -194,7 +200,7 @@ impl VerifyData {
} }
} }
impl TryParse for Response<()> { impl TryParse for Response {
fn try_parse(buf: &[u8]) -> Result<Option<(usize, Self)>> { fn try_parse(buf: &[u8]) -> Result<Option<(usize, Self)>> {
let mut hbuffer = [httparse::EMPTY_HEADER; MAX_HEADERS]; let mut hbuffer = [httparse::EMPTY_HEADER; MAX_HEADERS];
let mut req = httparse::Response::new(&mut hbuffer); let mut req = httparse::Response::new(&mut hbuffer);
@ -205,7 +211,7 @@ impl TryParse for Response<()> {
} }
} }
impl<'h, 'b: 'h> FromHttparse<httparse::Response<'h, 'b>> for Response<()> { impl<'h, 'b: 'h> FromHttparse<httparse::Response<'h, 'b>> for Response {
fn from_httparse(raw: httparse::Response<'h, 'b>) -> Result<Self> { fn from_httparse(raw: httparse::Response<'h, 'b>) -> Result<Self> {
if raw.version.expect("Bug: no HTTP version") < /*1.*/1 { if raw.version.expect("Bug: no HTTP version") < /*1.*/1 {
return Err(Error::Protocol( return Err(Error::Protocol(

@ -4,7 +4,7 @@ use std::io::{self, Read, Write};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::result::Result as StdResult; use std::result::Result as StdResult;
use http::{HeaderMap, Request, Response, StatusCode}; use http::{HeaderMap, Request as HttpRequest, Response as HttpResponse, StatusCode};
use httparse::Status; use httparse::Status;
use log::*; use log::*;
@ -14,8 +14,17 @@ use super::{convert_key, HandshakeRole, MidHandshake, ProcessingResult};
use crate::error::{Error, Result}; use crate::error::{Error, Result};
use crate::protocol::{Role, WebSocket, WebSocketConfig}; use crate::protocol::{Role, WebSocket, WebSocketConfig};
/// Server request type.
pub type Request = HttpRequest<()>;
/// Server response type.
pub type Response = HttpResponse<()>;
/// Server error response type.
pub type ErrorResponse = HttpResponse<Option<String>>;
/// Create a response for the request. /// Create a response for the request.
pub fn create_response(request: &Request<()>) -> Result<Response<()>> { pub fn create_response(request: &Request) -> Result<Response> {
if request.method() != http::Method::GET { if request.method() != http::Method::GET {
return Err(Error::Protocol("Method is not GET".into())); return Err(Error::Protocol("Method is not GET".into()));
} }
@ -78,7 +87,7 @@ pub fn create_response(request: &Request<()>) -> Result<Response<()>> {
} }
// Assumes that this is a valid response // Assumes that this is a valid response
fn write_response<T>(w: &mut dyn io::Write, response: &Response<T>) -> Result<()> { fn write_response<T>(w: &mut dyn io::Write, response: &HttpResponse<T>) -> Result<()> {
writeln!( writeln!(
w, w,
"{version:?} {status} {reason}\r", "{version:?} {status} {reason}\r",
@ -96,7 +105,7 @@ fn write_response<T>(w: &mut dyn io::Write, response: &Response<T>) -> Result<()
Ok(()) Ok(())
} }
impl TryParse for Request<()> { impl TryParse for Request {
fn try_parse(buf: &[u8]) -> Result<Option<(usize, Self)>> { fn try_parse(buf: &[u8]) -> Result<Option<(usize, Self)>> {
let mut hbuffer = [httparse::EMPTY_HEADER; MAX_HEADERS]; let mut hbuffer = [httparse::EMPTY_HEADER; MAX_HEADERS];
let mut req = httparse::Request::new(&mut hbuffer); let mut req = httparse::Request::new(&mut hbuffer);
@ -107,7 +116,7 @@ impl TryParse for Request<()> {
} }
} }
impl<'h, 'b: 'h> FromHttparse<httparse::Request<'h, 'b>> for Request<()> { impl<'h, 'b: 'h> FromHttparse<httparse::Request<'h, 'b>> for Request {
fn from_httparse(raw: httparse::Request<'h, 'b>) -> Result<Self> { fn from_httparse(raw: httparse::Request<'h, 'b>) -> Result<Self> {
if raw.method.expect("Bug: no method in header") != "GET" { if raw.method.expect("Bug: no method in header") != "GET" {
return Err(Error::Protocol("Method is not GET".into())); return Err(Error::Protocol("Method is not GET".into()));
@ -145,20 +154,20 @@ pub trait Callback: Sized {
/// Returning an error resulting in rejecting the incoming connection. /// Returning an error resulting in rejecting the incoming connection.
fn on_request( fn on_request(
self, self,
request: &Request<()>, request: &Request,
response: Response<()>, response: Response,
) -> StdResult<Response<()>, Response<Option<String>>>; ) -> StdResult<Response, ErrorResponse>;
} }
impl<F> Callback for F impl<F> Callback for F
where where
F: FnOnce(&Request<()>, Response<()>) -> StdResult<Response<()>, Response<Option<String>>>, F: FnOnce(&Request, Response) -> StdResult<Response, ErrorResponse>,
{ {
fn on_request( fn on_request(
self, self,
request: &Request<()>, request: &Request,
response: Response<()>, response: Response,
) -> StdResult<Response<()>, Response<Option<String>>> { ) -> StdResult<Response, ErrorResponse> {
self(request, response) self(request, response)
} }
} }
@ -170,9 +179,9 @@ pub struct NoCallback;
impl Callback for NoCallback { impl Callback for NoCallback {
fn on_request( fn on_request(
self, self,
_request: &Request<()>, _request: &Request,
response: Response<()>, response: Response,
) -> StdResult<Response<()>, Response<Option<String>>> { ) -> StdResult<Response, ErrorResponse> {
Ok(response) Ok(response)
} }
} }
@ -213,7 +222,7 @@ impl<S: Read + Write, C: Callback> ServerHandshake<S, C> {
} }
impl<S: Read + Write, C: Callback> HandshakeRole for ServerHandshake<S, C> { impl<S: Read + Write, C: Callback> HandshakeRole for ServerHandshake<S, C> {
type IncomingData = Request<()>; type IncomingData = Request;
type InternalStream = S; type InternalStream = S;
type FinalResult = WebSocket<S>; type FinalResult = WebSocket<S>;

Loading…
Cancel
Save