Compare commits
4 Commits
5a608098fe
...
36dd18d7ee
Author | SHA1 | Date |
---|---|---|
Ragan Christensen | 36dd18d7ee | |
Bartel Sielski | 60c50cdea2 | |
Ragan Christensen | d4120b49af | |
Ragan Christensen | 747a425ebc |
|
@ -86,10 +86,10 @@ pub fn create_response(request: &Request) -> Result<Response> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a response for the request with a custom body.
|
/// Create a response for the request with a custom body.
|
||||||
pub fn create_response_with_body<T>(
|
pub fn create_response_with_body<T1, T2>(
|
||||||
request: &HttpRequest<T>,
|
request: &HttpRequest<T1>,
|
||||||
generate_body: impl FnOnce() -> T,
|
generate_body: impl FnOnce() -> T2,
|
||||||
) -> Result<HttpResponse<T>> {
|
) -> Result<HttpResponse<T2>> {
|
||||||
Ok(create_parts(request)?.body(generate_body())?)
|
Ok(create_parts(request)?.body(generate_body())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,8 @@ pub enum Message {
|
||||||
Pong(Vec<u8>),
|
Pong(Vec<u8>),
|
||||||
/// A close message with the optional close frame.
|
/// A close message with the optional close frame.
|
||||||
Close(Option<CloseFrame<'static>>),
|
Close(Option<CloseFrame<'static>>),
|
||||||
/// Raw frame. Note, that you're not going to get this value while reading the message.
|
/// Raw frame. These will be returned from the socket only if the `read_as_frames` option
|
||||||
|
/// in [WebSocketConfig] is set to `true`.
|
||||||
Frame(Frame),
|
Frame(Frame),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ use std::{
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
mem::replace,
|
mem::replace,
|
||||||
};
|
};
|
||||||
|
use crate::protocol::frame::coding::Control;
|
||||||
|
|
||||||
/// Indicates a Client or Server role of the websocket
|
/// Indicates a Client or Server role of the websocket
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
@ -70,6 +71,12 @@ pub struct WebSocketConfig {
|
||||||
/// some popular libraries that are sending unmasked frames, ignoring the RFC.
|
/// some popular libraries that are sending unmasked frames, ignoring the RFC.
|
||||||
/// By default this option is set to `false`, i.e. according to RFC 6455.
|
/// By default this option is set to `false`, i.e. according to RFC 6455.
|
||||||
pub accept_unmasked_frames: bool,
|
pub accept_unmasked_frames: bool,
|
||||||
|
/// When set to `true`, all well-formed frames read by the socket will be returned as-is
|
||||||
|
/// with minimal processing. Close frames and masked frames will still be handled,
|
||||||
|
/// as they affect control flow, but fragmented or incomplete frames will be returned without
|
||||||
|
/// reassembly.
|
||||||
|
/// Set to `false` by default
|
||||||
|
pub read_as_frames: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WebSocketConfig {
|
impl Default for WebSocketConfig {
|
||||||
|
@ -82,6 +89,7 @@ impl Default for WebSocketConfig {
|
||||||
max_message_size: Some(64 << 20),
|
max_message_size: Some(64 << 20),
|
||||||
max_frame_size: Some(16 << 20),
|
max_frame_size: Some(16 << 20),
|
||||||
accept_unmasked_frames: false,
|
accept_unmasked_frames: false,
|
||||||
|
read_as_frames: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,7 +445,6 @@ impl WebSocketContext {
|
||||||
if !self.state.is_active() {
|
if !self.state.is_active() {
|
||||||
return Err(Error::Protocol(ProtocolError::SendAfterClosing));
|
return Err(Error::Protocol(ProtocolError::SendAfterClosing));
|
||||||
}
|
}
|
||||||
|
|
||||||
let frame = match message {
|
let frame = match message {
|
||||||
Message::Text(data) => Frame::message(data.into(), OpCode::Data(OpData::Text), true),
|
Message::Text(data) => Frame::message(data.into(), OpCode::Data(OpData::Text), true),
|
||||||
Message::Binary(data) => Frame::message(data, OpCode::Data(OpData::Binary), true),
|
Message::Binary(data) => Frame::message(data, OpCode::Data(OpData::Binary), true),
|
||||||
|
@ -553,6 +560,18 @@ impl WebSocketContext {
|
||||||
if !self.state.can_read() {
|
if !self.state.can_read() {
|
||||||
return Err(Error::Protocol(ProtocolError::ReceivedAfterClosing));
|
return Err(Error::Protocol(ProtocolError::ReceivedAfterClosing));
|
||||||
}
|
}
|
||||||
|
if self.config.read_as_frames {
|
||||||
|
if frame.header().opcode == OpCode::Control(Control::Close) &&
|
||||||
|
self.state.is_active() {
|
||||||
|
// Do close, but ignore the output
|
||||||
|
self.do_close(frame.clone().into_close()?);
|
||||||
|
}
|
||||||
|
if frame.is_masked() {
|
||||||
|
frame.apply_mask();
|
||||||
|
}
|
||||||
|
// Always return the original frame
|
||||||
|
return Ok(Some(Message::Frame(frame)));
|
||||||
|
}
|
||||||
// MUST be 0 unless an extension is negotiated that defines meanings
|
// MUST be 0 unless an extension is negotiated that defines meanings
|
||||||
// for non-zero values. If a nonzero value is received and none of
|
// for non-zero values. If a nonzero value is received and none of
|
||||||
// the negotiated extensions defines the meaning of such a nonzero
|
// the negotiated extensions defines the meaning of such a nonzero
|
||||||
|
@ -800,6 +819,8 @@ mod tests {
|
||||||
use crate::error::{CapacityError, Error};
|
use crate::error::{CapacityError, Error};
|
||||||
|
|
||||||
use std::{io, io::Cursor};
|
use std::{io, io::Cursor};
|
||||||
|
use crate::protocol::frame::{Frame, FrameHeader};
|
||||||
|
use crate::protocol::frame::coding::{Data, OpCode};
|
||||||
|
|
||||||
struct WriteMoc<Stream>(Stream);
|
struct WriteMoc<Stream>(Stream);
|
||||||
|
|
||||||
|
@ -832,6 +853,23 @@ mod tests {
|
||||||
assert_eq!(socket.read().unwrap(), Message::Binary(vec![0x01, 0x02, 0x03]));
|
assert_eq!(socket.read().unwrap(), Message::Binary(vec![0x01, 0x02, 0x03]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn read_extended_frame() {
|
||||||
|
let raw = vec![
|
||||||
|
0xc1, 0x0b, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64
|
||||||
|
];
|
||||||
|
let mut config = WebSocketConfig::default();
|
||||||
|
config.read_as_frames = true;
|
||||||
|
let cursor = Cursor::new(raw.clone());
|
||||||
|
let mut frame_header = FrameHeader::default();
|
||||||
|
frame_header.is_final = true;
|
||||||
|
frame_header.rsv1 = true;
|
||||||
|
frame_header.opcode = OpCode::Data(Data::Text);
|
||||||
|
let expected_frame = Frame::from_payload(frame_header, raw[2..].to_vec());
|
||||||
|
let mut socket = WebSocket::from_raw_socket(WriteMoc(cursor), Role::Client, Some(config));
|
||||||
|
assert_eq!(socket.read().unwrap(), Message::Frame(expected_frame));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn size_limiting_text_fragmented() {
|
fn size_limiting_text_fragmented() {
|
||||||
let incoming = Cursor::new(vec![
|
let incoming = Cursor::new(vec![
|
||||||
|
|
Loading…
Reference in New Issue