Skip to content

Commit

Permalink
introduce response and builder types to web
Browse files Browse the repository at this point in the history
  • Loading branch information
robjtede committed Apr 8, 2021
1 parent d1e5025 commit a811494
Show file tree
Hide file tree
Showing 24 changed files with 861 additions and 326 deletions.
6 changes: 3 additions & 3 deletions actix-files/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use actix_web::{http::StatusCode, HttpResponse, ResponseError};
use actix_web::{http::StatusCode, ResponseError};
use derive_more::Display;

/// Errors which can occur when serving static files.
Expand All @@ -16,8 +16,8 @@ pub enum FilesError {

/// Return `NotFound` for `FilesError`
impl ResponseError for FilesError {
fn error_response(&self) -> HttpResponse {
HttpResponse::new(StatusCode::NOT_FOUND)
fn status_code(&self) -> StatusCode {
StatusCode::NOT_FOUND
}
}

Expand Down
8 changes: 4 additions & 4 deletions actix-http/examples/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::{
};

use actix_codec::Encoder;
use actix_http::{error::Error, ws, HttpService, Request, Response};
use actix_http::{body::BodyStream, error::Error, ws, HttpService, Request, Response};
use actix_rt::time::{interval, Interval};
use actix_server::Server;
use bytes::{Bytes, BytesMut};
Expand All @@ -34,14 +34,14 @@ async fn main() -> io::Result<()> {
.await
}

async fn handler(req: Request) -> Result<Response, Error> {
async fn handler(req: Request) -> Result<Response<BodyStream<Heartbeat>>, Error> {
log::info!("handshaking");
let mut res = ws::handshake(req.head())?;
let res = ws::handshake(req.head())?;

// handshake will always fail under HTTP/2

log::info!("responding");
Ok(res.streaming(Heartbeat::new(ws::Codec::new())))
Ok(res.set_body(BodyStream::new(Heartbeat::new(ws::Codec::new()))))
}

struct Heartbeat {
Expand Down
14 changes: 7 additions & 7 deletions actix-http/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use serde_urlencoded::ser::Error as FormError;

use crate::body::Body;
use crate::helpers::Writer;
use crate::response::{Response, ResponseBuilder};
use crate::response::Response;

/// A specialized [`std::result::Result`]
/// for actix web operations
Expand Down Expand Up @@ -135,12 +135,12 @@ impl From<Response> for Error {
}
}

/// Convert ResponseBuilder to a Error
impl From<ResponseBuilder> for Error {
fn from(mut res: ResponseBuilder) -> Error {
InternalError::from_response("", res.finish()).into()
}
}
// /// Convert ResponseBuilder to a Error
// impl From<ResponseBuilder> for Error {
// fn from(mut res: ResponseBuilder) -> Error {
// InternalError::from_response("", res.finish()).into()
// }
// }

#[derive(Debug, Display)]
#[display(fmt = "UnknownError")]
Expand Down
4 changes: 3 additions & 1 deletion actix-http/src/h1/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,15 @@ where
StateProj::ServiceCall(fut) => match fut.poll(cx) {
// service call resolved. send response.
Poll::Ready(Ok(res)) => {
eprintln!("dispatcher ok!");
let (res, body) = res.into().replace_body(());
self.as_mut().send_response(res, body)?;
}

// send service call error as response
Poll::Ready(Err(err)) => {
let res: Response = err.into().into();
eprintln!("dispatcher err");
let res = Response::from_error(err.into());
let (res, body) = res.replace_body(());
self.as_mut().send_response(res, body.into_body())?;
}
Expand Down
4 changes: 2 additions & 2 deletions actix-http/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ impl ResponseHead {
}

pub struct Message<T: Head> {
// Rc here should not be cloned by anyone.
// It's used to reuse allocation of T and no shared ownership is allowed.
/// Rc here should not be cloned by anyone.
/// It's used to reuse allocation of T and no shared ownership is allowed.
head: Rc<T>,
}

Expand Down
1 change: 0 additions & 1 deletion actix-http/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use std::{
use cookie::{Cookie, ParseError as CookieParseError};
use http::{header, Method, Uri, Version};


use crate::{
extensions::Extensions,
header::HeaderMap,
Expand Down
72 changes: 6 additions & 66 deletions actix-http/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,6 @@ pub struct Response<B = Body> {
}

impl Response<Body> {
/// Create HTTP response builder with specific status.
#[inline]
pub fn build(status: StatusCode) -> ResponseBuilder {
ResponseBuilder::new(status)
}

/// Create HTTP response builder
#[inline]
pub fn build_from<T: Into<ResponseBuilder>>(source: T) -> ResponseBuilder {
source.into()
}

/// Constructs a response
#[inline]
pub fn new(status: StatusCode) -> Response {
Expand Down Expand Up @@ -139,54 +127,6 @@ impl<B> Response<B> {
&mut self.head.headers
}

/// Get an iterator for the cookies set by this response
#[cfg(feature = "cookies")]
#[inline]
pub fn cookies(&self) -> CookieIter<'_> {
CookieIter {
iter: self.head.headers.get_all(header::SET_COOKIE),
}
}

/// Add a cookie to this response
#[cfg(feature = "cookies")]
#[inline]
pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
let h = &mut self.head.headers;
HeaderValue::from_str(&cookie.to_string())
.map(|c| {
h.append(header::SET_COOKIE, c);
})
.map_err(|e| e.into())
}

/// Remove all cookies with the given name from this response. Returns
/// the number of cookies removed.
#[cfg(feature = "cookies")]
#[inline]
pub fn del_cookie(&mut self, name: &str) -> usize {
let h = &mut self.head.headers;
let vals: Vec<HeaderValue> = h
.get_all(header::SET_COOKIE)
.map(|v| v.to_owned())
.collect();
h.remove(header::SET_COOKIE);

let mut count: usize = 0;
for v in vals {
if let Ok(s) = v.to_str() {
if let Ok(c) = Cookie::parse_encoded(s) {
if c.name() == name {
count += 1;
continue;
}
}
}
h.append(header::SET_COOKIE, v);
}
count
}

/// Connection upgrade status
#[inline]
pub fn upgrade(&self) -> bool {
Expand Down Expand Up @@ -732,7 +672,7 @@ impl<B> From<Response<B>> for ResponseBuilder {
head: Some(res.head),
err: None,
#[cfg(feature = "cookies")]
cookies: None
cookies: None,
}
}
}
Expand Down Expand Up @@ -876,7 +816,7 @@ mod tests {

#[test]
fn test_upgrade() {
let resp = Response::build(StatusCode::OK)
let resp = ResponseBuilder::new(StatusCode::OK)
.upgrade("websocket")
.finish();
assert!(resp.upgrade());
Expand All @@ -888,13 +828,13 @@ mod tests {

#[test]
fn test_force_close() {
let resp = Response::build(StatusCode::OK).force_close().finish();
let resp = ResponseBuilder::new(StatusCode::OK).force_close().finish();
assert!(!resp.keep_alive())
}

#[test]
fn test_content_type() {
let resp = Response::build(StatusCode::OK)
let resp = ResponseBuilder::new(StatusCode::OK)
.content_type("text/plain")
.body(Body::Empty);
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "text/plain")
Expand All @@ -915,7 +855,7 @@ mod tests {

#[test]
fn test_json_ct() {
let resp = Response::build(StatusCode::OK)
let resp = ResponseBuilder::new(StatusCode::OK)
.insert_header((CONTENT_TYPE, "text/json"))
.json(&vec!["v1", "v2", "v3"]);
let ct = resp.headers().get(CONTENT_TYPE).unwrap();
Expand All @@ -927,7 +867,7 @@ mod tests {
fn test_serde_json_in_body() {
use serde_json::json;
let resp =
Response::build(StatusCode::OK).body(json!({"test-key":"test-value"}));
ResponseBuilder::new(StatusCode::OK).body(json!({"test-key":"test-value"}));
assert_eq!(resp.body().get_ref(), br#"{"test-key":"test-value"}"#);
}

Expand Down
46 changes: 32 additions & 14 deletions actix-http/src/ws/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use http::{header, Method, StatusCode};
use crate::{
error::ResponseError,
header::HeaderValue,
message::RequestHead,
response::{Response, ResponseBuilder},
message::{ConnectionType, RequestHead},
response::Response,
};

mod codec;
Expand Down Expand Up @@ -131,7 +131,7 @@ impl ResponseError for HandshakeError {
}

/// Verify WebSocket handshake request and create handshake response.
pub fn handshake(req: &RequestHead) -> Result<ResponseBuilder, HandshakeError> {
pub fn handshake(req: &RequestHead) -> Result<Response, HandshakeError> {
verify_handshake(req)?;
Ok(handshake_response(req))
}
Expand Down Expand Up @@ -187,21 +187,39 @@ pub fn verify_handshake(req: &RequestHead) -> Result<(), HandshakeError> {
/// Create WebSocket handshake response.
///
/// This function returns handshake `Response`, ready to send to peer.
pub fn handshake_response(req: &RequestHead) -> ResponseBuilder {
pub fn handshake_response(req: &RequestHead) -> Response {
let key = {
let key = req.headers().get(header::SEC_WEBSOCKET_KEY).unwrap();
proto::hash_key(key.as_ref())
};

Response::build(StatusCode::SWITCHING_PROTOCOLS)
.upgrade("websocket")
.insert_header((header::TRANSFER_ENCODING, "chunked"))
.insert_header((
header::SEC_WEBSOCKET_ACCEPT,
// key is known to be header value safe ascii
HeaderValue::from_bytes(&key).unwrap(),
))
.take()
let mut res = Response::new(StatusCode::SWITCHING_PROTOCOLS);

res.head_mut().set_connection_type(ConnectionType::Upgrade);
let headers = res.headers_mut();

headers.insert(header::UPGRADE, HeaderValue::from_static("websocket"));

headers.insert(
header::TRANSFER_ENCODING,
HeaderValue::from_static("chunked"),
);
headers.insert(
header::SEC_WEBSOCKET_ACCEPT,
// key is known to be header value safe ascii
HeaderValue::from_bytes(&key).unwrap(),
);

res

// Response::build(StatusCode::SWITCHING_PROTOCOLS)
// .upgrade("websocket")
// .insert_header((header::TRANSFER_ENCODING, "chunked"))
// .insert_header((
// header::SEC_WEBSOCKET_ACCEPT,
// // key is known to be header value safe ascii
// HeaderValue::from_bytes(&key).unwrap(),
// ))
}

#[cfg(test)]
Expand Down Expand Up @@ -316,7 +334,7 @@ mod tests {
.finish();
assert_eq!(
StatusCode::SWITCHING_PROTOCOLS,
handshake_response(req.head()).finish().status()
handshake_response(req.head()).status()
);
}

Expand Down
2 changes: 1 addition & 1 deletion actix-http/tests/test_ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ where

fn call(&self, (req, mut framed): (Request, Framed<T, h1::Codec>)) -> Self::Future {
let fut = async move {
let res = ws::handshake(req.head()).unwrap().message_body(());
let res = ws::handshake(req.head()).unwrap().set_body(());

framed
.send((res, body::BodySize::None).into())
Expand Down
3 changes: 1 addition & 2 deletions actix-multipart/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,10 @@ impl ResponseError for MultipartError {
#[cfg(test)]
mod tests {
use super::*;
use actix_web::HttpResponse;

#[test]
fn test_multipart_error() {
let resp: HttpResponse = MultipartError::Boundary.error_response();
let resp = MultipartError::Boundary.error_response();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
}
}
8 changes: 4 additions & 4 deletions actix-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ use actix_codec::{AsyncRead, AsyncWrite, Framed};
pub use actix_http::test::TestBuffer;
use actix_http::{
http::{HeaderMap, Method},
ws, HttpService, Request,
ws, HttpService, Request, Response,
};
use actix_service::{map_config, IntoServiceFactory, ServiceFactory};
use actix_web::{
dev::{AppConfig, MessageBody, Server, Service},
rt, web, Error, HttpResponse,
rt, web, Error,
};
use awc::{error::PayloadError, Client, ClientRequest, ClientResponse, Connector};
use futures_core::Stream;
Expand Down Expand Up @@ -83,7 +83,7 @@ where
S: ServiceFactory<Request, Config = AppConfig> + 'static,
S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug,
S::Response: Into<HttpResponse<B>> + 'static,
S::Response: Into<Response<B>> + 'static,
<S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static,
{
Expand Down Expand Up @@ -122,7 +122,7 @@ where
S: ServiceFactory<Request, Config = AppConfig> + 'static,
S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug,
S::Response: Into<HttpResponse<B>> + 'static,
S::Response: Into<Response<B>> + 'static,
<S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static,
{
Expand Down
2 changes: 1 addition & 1 deletion actix-web-actors/src/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ use actix_http::{
http::HeaderValue,
ws::{hash_key, Codec},
};
use actix_web::HttpResponseBuilder;
use actix_web::error::{Error, PayloadError};
use actix_web::http::{header, Method, StatusCode};
use actix_web::HttpResponseBuilder;
use actix_web::{HttpRequest, HttpResponse};
use bytes::{Bytes, BytesMut};
use bytestring::ByteString;
Expand Down

0 comments on commit a811494

Please sign in to comment.