@ -90,40 +90,60 @@ 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 mut request : Request = request . into_client_request ( ) ? ;
// Copy all the fields from the initial reqeust **except** the URI. This will be used in the event of a redirection code
// Have to manually clone Method because there is one field that contains a Box,
fn inner ( request : Request , config : Option < WebSocketConfig > ) -> Result < ( WebSocket < AutoStream > , Response ) > {
// but in the case of normal request methods it is Copy
let uri = request . uri ( ) ;
let request2 = Request ::builder ( )
let mode = uri_mode ( uri ) ? ;
. method ( request . method ( ) . clone ( ) )
let host = request
. version ( request . version ( ) ) ;
. uri ( )
let uri = request . uri ( ) ;
. host ( )
let mode = uri_mode ( uri ) ? ;
. ok_or_else ( | | Error ::Url ( "No host name in the URL" . into ( ) ) ) ? ;
let host = request
let port = uri . port_u16 ( ) . unwrap_or ( match mode {
. uri ( )
Mode ::Plain = > 80 ,
. host ( )
Mode ::Tls = > 443 ,
. ok_or_else ( | | Error ::Url ( "No host name in the URL" . into ( ) ) ) ? ;
} ) ;
let port = uri . port_u16 ( ) . unwrap_or ( match mode {
let addrs = ( host , port ) . to_socket_addrs ( ) ? ;
Mode ::Plain = > 80 ,
let mut stream = connect_to_some ( addrs . as_slice ( ) , & request . uri ( ) , mode ) ? ;
Mode ::Tls = > 443 ,
NoDelay ::set_nodelay ( & mut stream , true ) ? ;
} ) ;
client_with_config ( request , stream , config ) . map_err ( | e | match e {
let addrs = ( host , port ) . to_socket_addrs ( ) ? ;
HandshakeError ::Failure ( f ) = > f ,
let mut stream = connect_to_some ( addrs . as_slice ( ) , & request . uri ( ) , mode ) ? ;
HandshakeError ::Interrupted ( _ ) = > panic! ( "Bug: blocking handshake not blocked" ) ,
NoDelay ::set_nodelay ( & mut stream , true ) ? ;
} )
match client_with_config ( request , stream , config ) . map_err ( | e | match e {
}
HandshakeError ::Failure ( f ) = > f ,
HandshakeError ::Interrupted ( _ ) = > panic! ( "Bug: blocking handshake not blocked" ) ,
let max_redirects = config . as_ref ( ) . and_then ( | c | c . max_redirects ) . unwrap_or ( 0 ) ;
} ) {
let mut redirects = 0 ;
Ok ( r ) = > Ok ( r ) ,
Err ( e ) = > match e {
loop {
Error ::Redirection ( uri ) = > {
// Copy all the fields from the initial reqeust **except** the URI. This will be used in the event of a redirection code
debug ! ( "Redirecting to {}" , uri ) ;
// Have to manually clone Method because there is one field that contains a Box,
let request = request2 . uri ( uri ) . body ( ( ) ) . unwrap ( ) ;
// but in the case of normal request methods it is Copy
connect_with_config ( request , config )
let request2 = Request ::builder ( )
. method ( request . method ( ) . clone ( ) )
. version ( request . version ( ) ) ;
match inner ( request , config ) {
Ok ( r ) = > return Ok ( r ) ,
Err ( e ) = > match e {
Error ::Http ( res ) = > {
if res . status ( ) . is_redirection ( ) {
let uri = res . headers ( ) . get ( "Location" ) . ok_or ( Error ::NoLocation ) ? ;
debug ! ( "Redirecting to {:?}" , uri ) ;
request = request2 . uri ( uri . to_str ( ) ? . parse ::< Uri > ( ) ? ) . body ( ( ) ) . unwrap ( ) ;
redirects + = 1 ;
if redirects > max_redirects {
return Err ( Error ::Http ( res ) ) ;
}
} else {
return Err ( Error ::Http ( res ) ) ;
}
}
_ = > return Err ( e ) ,
}
}
_ = > Err ( e ) ,
}
}
}
}
}
}
/// Connect to the given WebSocket in blocking mode.
/// Connect to the given WebSocket in blocking mode.