1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-12-01 02:44:37 +01:00

ws/context: Increase write() visibility to public (#402)

This type is introduced to avoid confusion between the `.binary()` and `.write_raw()` methods on WebSocket contexts
This commit is contained in:
Tobias Bieniek 2018-07-19 19:04:13 +02:00 committed by Douman
parent 2988a84e5f
commit 0925a7691a
4 changed files with 31 additions and 20 deletions

View File

@ -27,7 +27,7 @@ use client::{
Pipeline, SendRequest, SendRequestError, Pipeline, SendRequest, SendRequestError,
}; };
use super::frame::Frame; use super::frame::{Frame, FramedMessage};
use super::proto::{CloseReason, OpCode}; use super::proto::{CloseReason, OpCode};
use super::{Message, ProtocolError, WsWriter}; use super::{Message, ProtocolError, WsWriter};
@ -529,10 +529,10 @@ pub struct ClientWriter {
impl ClientWriter { impl ClientWriter {
/// Write payload /// Write payload
#[inline] #[inline]
fn write(&mut self, mut data: Binary) { fn write(&mut self, mut data: FramedMessage) {
let inner = self.inner.borrow_mut(); let inner = self.inner.borrow_mut();
if !inner.closed { if !inner.closed {
let _ = inner.tx.unbounded_send(data.take()); let _ = inner.tx.unbounded_send(data.0.take());
} else { } else {
warn!("Trying to write to disconnected response"); warn!("Trying to write to disconnected response");
} }

View File

@ -20,7 +20,7 @@ use context::{ActorHttpContext, Drain, Frame as ContextFrame};
use error::{Error, ErrorInternalServerError, PayloadError}; use error::{Error, ErrorInternalServerError, PayloadError};
use httprequest::HttpRequest; use httprequest::HttpRequest;
use ws::frame::Frame; use ws::frame::{Frame, FramedMessage};
use ws::proto::{CloseReason, OpCode}; use ws::proto::{CloseReason, OpCode};
use ws::{Message, ProtocolError, WsStream, WsWriter}; use ws::{Message, ProtocolError, WsStream, WsWriter};
@ -132,14 +132,19 @@ where
A: Actor<Context = Self>, A: Actor<Context = Self>,
{ {
/// Write payload /// Write payload
///
/// This is a low-level function that accepts framed messages that should
/// be created using `Frame::message()`. If you want to send text or binary
/// data you should prefer the `text()` or `binary()` convenience functions
/// that handle the framing for you.
#[inline] #[inline]
fn write(&mut self, data: Binary) { pub fn write_raw(&mut self, data: FramedMessage) {
if !self.disconnected { if !self.disconnected {
if self.stream.is_none() { if self.stream.is_none() {
self.stream = Some(SmallVec::new()); self.stream = Some(SmallVec::new());
} }
let stream = self.stream.as_mut().unwrap(); let stream = self.stream.as_mut().unwrap();
stream.push(ContextFrame::Chunk(Some(data))); stream.push(ContextFrame::Chunk(Some(data.0)));
} else { } else {
warn!("Trying to write to disconnected response"); warn!("Trying to write to disconnected response");
} }
@ -167,19 +172,19 @@ where
/// Send text frame /// Send text frame
#[inline] #[inline]
pub fn text<T: Into<Binary>>(&mut self, text: T) { pub fn text<T: Into<Binary>>(&mut self, text: T) {
self.write(Frame::message(text.into(), OpCode::Text, true, false)); self.write_raw(Frame::message(text.into(), OpCode::Text, true, false));
} }
/// Send binary frame /// Send binary frame
#[inline] #[inline]
pub fn binary<B: Into<Binary>>(&mut self, data: B) { pub fn binary<B: Into<Binary>>(&mut self, data: B) {
self.write(Frame::message(data, OpCode::Binary, true, false)); self.write_raw(Frame::message(data, OpCode::Binary, true, false));
} }
/// Send ping frame /// Send ping frame
#[inline] #[inline]
pub fn ping(&mut self, message: &str) { pub fn ping(&mut self, message: &str) {
self.write(Frame::message( self.write_raw(Frame::message(
Vec::from(message), Vec::from(message),
OpCode::Ping, OpCode::Ping,
true, true,
@ -190,7 +195,7 @@ where
/// Send pong frame /// Send pong frame
#[inline] #[inline]
pub fn pong(&mut self, message: &str) { pub fn pong(&mut self, message: &str) {
self.write(Frame::message( self.write_raw(Frame::message(
Vec::from(message), Vec::from(message),
OpCode::Pong, OpCode::Pong,
true, true,
@ -201,7 +206,7 @@ where
/// Send close frame /// Send close frame
#[inline] #[inline]
pub fn close(&mut self, reason: Option<CloseReason>) { pub fn close(&mut self, reason: Option<CloseReason>) {
self.write(Frame::close(reason, false)); self.write_raw(Frame::close(reason, false));
} }
/// Check if connection still open /// Check if connection still open

View File

@ -28,7 +28,7 @@ impl Frame {
/// Create a new Close control frame. /// Create a new Close control frame.
#[inline] #[inline]
pub fn close(reason: Option<CloseReason>, genmask: bool) -> Binary { pub fn close(reason: Option<CloseReason>, genmask: bool) -> FramedMessage {
let payload = match reason { let payload = match reason {
None => Vec::new(), None => Vec::new(),
Some(reason) => { Some(reason) => {
@ -295,7 +295,7 @@ impl Frame {
/// Generate binary representation /// Generate binary representation
pub fn message<B: Into<Binary>>( pub fn message<B: Into<Binary>>(
data: B, code: OpCode, finished: bool, genmask: bool, data: B, code: OpCode, finished: bool, genmask: bool,
) -> Binary { ) -> FramedMessage {
let payload = data.into(); let payload = data.into();
let one: u8 = if finished { let one: u8 = if finished {
0x80 | Into::<u8>::into(code) 0x80 | Into::<u8>::into(code)
@ -325,7 +325,7 @@ impl Frame {
buf buf
}; };
if genmask { let binary = if genmask {
let mask = rand::random::<u32>(); let mask = rand::random::<u32>();
buf.put_u32_le(mask); buf.put_u32_le(mask);
buf.extend_from_slice(payload.as_ref()); buf.extend_from_slice(payload.as_ref());
@ -335,7 +335,9 @@ impl Frame {
} else { } else {
buf.put_slice(payload.as_ref()); buf.put_slice(payload.as_ref());
buf.into() buf.into()
} };
FramedMessage(binary)
} }
} }
@ -372,6 +374,10 @@ impl fmt::Display for Frame {
} }
} }
/// `WebSocket` message with framing.
#[derive(Debug)]
pub struct FramedMessage(pub(crate) Binary);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -502,7 +508,7 @@ mod tests {
let mut v = vec![137u8, 4u8]; let mut v = vec![137u8, 4u8];
v.extend(b"data"); v.extend(b"data");
assert_eq!(frame, v.into()); assert_eq!(frame.0, v.into());
} }
#[test] #[test]
@ -511,7 +517,7 @@ mod tests {
let mut v = vec![138u8, 4u8]; let mut v = vec![138u8, 4u8];
v.extend(b"data"); v.extend(b"data");
assert_eq!(frame, v.into()); assert_eq!(frame.0, v.into());
} }
#[test] #[test]
@ -521,12 +527,12 @@ mod tests {
let mut v = vec![136u8, 6u8, 3u8, 232u8]; let mut v = vec![136u8, 6u8, 3u8, 232u8];
v.extend(b"data"); v.extend(b"data");
assert_eq!(frame, v.into()); assert_eq!(frame.0, v.into());
} }
#[test] #[test]
fn test_empty_close_frame() { fn test_empty_close_frame() {
let frame = Frame::close(None, false); let frame = Frame::close(None, false);
assert_eq!(frame, vec![0x88, 0x00].into()); assert_eq!(frame.0, vec![0x88, 0x00].into());
} }
} }

View File

@ -64,7 +64,7 @@ pub use self::client::{
Client, ClientError, ClientHandshake, ClientReader, ClientWriter, Client, ClientError, ClientHandshake, ClientReader, ClientWriter,
}; };
pub use self::context::WebsocketContext; pub use self::context::WebsocketContext;
pub use self::frame::Frame; pub use self::frame::{Frame, FramedMessage};
pub use self::proto::{CloseCode, CloseReason, OpCode}; pub use self::proto::{CloseCode, CloseReason, OpCode};
/// Websocket protocol errors /// Websocket protocol errors