1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 23:51:06 +01:00
This commit is contained in:
Nikolay Kim 2017-10-06 23:14:13 -07:00
parent 0b5f0c4f22
commit a505be9321
13 changed files with 106 additions and 65 deletions

View File

@ -1,7 +1,5 @@
language: rust language: rust
rust: rust:
- 1.18.0
- 1.19.0
- 1.20.0 - 1.20.0
- nightly - nightly

View File

@ -4,6 +4,7 @@ Actix http is a http framework for Actix framework.
* [API Documentation](http://fafhrd91.github.io/actix-http/actix_http/) * [API Documentation](http://fafhrd91.github.io/actix-http/actix_http/)
* Cargo package: [actix-http](https://crates.io/crates/actix-http) * Cargo package: [actix-http](https://crates.io/crates/actix-http)
* Minimum supported Rust version: 1.20 or later
--- ---

View File

@ -39,6 +39,8 @@ impl<S> HttpApplication<S> where S: 'static
} }
impl HttpApplication<()> { impl HttpApplication<()> {
/// Create `HttpApplication` with no state
pub fn no_state() -> Self { pub fn no_state() -> Self {
HttpApplication { HttpApplication {
state: (), state: (),
@ -50,6 +52,9 @@ impl HttpApplication<()> {
impl<S> HttpApplication<S> where S: 'static { impl<S> HttpApplication<S> where S: 'static {
/// Create http application with specific state. State is shared with all
/// routes within same application and could be
/// accessed with `HttpContext::state()` method.
pub fn new(state: S) -> HttpApplication<S> { pub fn new(state: S) -> HttpApplication<S> {
HttpApplication { HttpApplication {
state: state, state: state,
@ -58,6 +63,7 @@ impl<S> HttpApplication<S> where S: 'static {
} }
} }
/// Add resource by path.
pub fn add<P: ToString>(&mut self, path: P) -> &mut HttpResource<S> pub fn add<P: ToString>(&mut self, path: P) -> &mut HttpResource<S>
{ {
let path = path.to_string(); let path = path.to_string();
@ -70,7 +76,7 @@ impl<S> HttpApplication<S> where S: 'static {
self.resources.get_mut(&path).unwrap() self.resources.get_mut(&path).unwrap()
} }
/// Default resource /// Default resource is used if no matched route could be found.
pub fn default(&mut self) -> &mut HttpResource<S> { pub fn default(&mut self) -> &mut HttpResource<S> {
&mut self.default &mut self.default
} }

View File

@ -9,13 +9,13 @@ use actix::fut::ActorFuture;
use actix::dev::{AsyncContextApi, ActorAddressCell}; use actix::dev::{AsyncContextApi, ActorAddressCell};
use route::{Route, Frame}; use route::{Route, Frame};
use httpmessage::HttpMessage; use httpmessage::HttpResponse;
/// Actor execution context /// Actor execution context
pub struct HttpContext<A> where A: Actor<Context=HttpContext<A>> + Route, pub struct HttpContext<A> where A: Actor<Context=HttpContext<A>> + Route,
{ {
act: A, act: Option<A>,
state: ActorState, state: ActorState,
items: Vec<Box<ActorFuture<Item=(), Error=(), Actor=A>>>, items: Vec<Box<ActorFuture<Item=(), Error=(), Actor=A>>>,
address: ActorAddressCell<A>, address: ActorAddressCell<A>,
@ -60,6 +60,7 @@ impl<A> AsyncActorContext<A> for HttpContext<A> where A: Actor<Context=Self> + R
} }
} }
#[doc(hidden)]
impl<A> AsyncContextApi<A> for HttpContext<A> where A: Actor<Context=Self> + Route { impl<A> AsyncContextApi<A> for HttpContext<A> where A: Actor<Context=Self> + Route {
fn address_cell(&mut self) -> &mut ActorAddressCell<A> { fn address_cell(&mut self) -> &mut ActorAddressCell<A> {
&mut self.address &mut self.address
@ -68,10 +69,10 @@ impl<A> AsyncContextApi<A> for HttpContext<A> where A: Actor<Context=Self> + Rou
impl<A> HttpContext<A> where A: Actor<Context=Self> + Route { impl<A> HttpContext<A> where A: Actor<Context=Self> + Route {
pub(crate) fn new(act: A, state: Rc<<A as Route>::State>) -> HttpContext<A> pub(crate) fn new(state: Rc<<A as Route>::State>) -> HttpContext<A>
{ {
HttpContext { HttpContext {
act: act, act: None,
state: ActorState::Started, state: ActorState::Started,
items: Vec::new(), items: Vec::new(),
address: ActorAddressCell::new(), address: ActorAddressCell::new(),
@ -80,8 +81,8 @@ impl<A> HttpContext<A> where A: Actor<Context=Self> + Route {
} }
} }
pub(crate) fn replace_actor(&mut self, srv: A) -> A { pub(crate) fn set_actor(&mut self, act: A) {
std::mem::replace(&mut self.act, srv) self.act = Some(act)
} }
} }
@ -93,7 +94,7 @@ impl<A> HttpContext<A> where A: Actor<Context=Self> + Route {
} }
/// Start response processing /// Start response processing
pub fn start(&mut self, response: HttpMessage) { pub fn start(&mut self, response: HttpResponse) {
self.stream.push_back(Frame::Message(response)) self.stream.push_back(Frame::Message(response))
} }
@ -102,18 +103,26 @@ impl<A> HttpContext<A> where A: Actor<Context=Self> + Route {
self.stream.push_back(Frame::Payload(Some(data))) self.stream.push_back(Frame::Payload(Some(data)))
} }
/// Completed /// Indicate end of streamimng payload
pub fn write_eof(&mut self) { pub fn write_eof(&mut self) {
self.stream.push_back(Frame::Payload(None)) self.stream.push_back(Frame::Payload(None))
} }
} }
#[doc(hidden)]
impl<A> Stream for HttpContext<A> where A: Actor<Context=Self> + Route impl<A> Stream for HttpContext<A> where A: Actor<Context=Self> + Route
{ {
type Item = Frame; type Item = Frame;
type Error = std::io::Error; type Error = std::io::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
if self.act.is_none() {
return Ok(Async::NotReady)
}
let act: &mut A = unsafe {
std::mem::transmute(self.act.as_mut().unwrap() as &mut A)
};
let ctx: &mut HttpContext<A> = unsafe { let ctx: &mut HttpContext<A> = unsafe {
std::mem::transmute(self as &mut HttpContext<A>) std::mem::transmute(self as &mut HttpContext<A>)
}; };
@ -121,11 +130,11 @@ impl<A> Stream for HttpContext<A> where A: Actor<Context=Self> + Route
// update state // update state
match self.state { match self.state {
ActorState::Started => { ActorState::Started => {
Actor::started(&mut self.act, ctx); Actor::started(act, ctx);
self.state = ActorState::Running; self.state = ActorState::Running;
}, },
ActorState::Stopping => { ActorState::Stopping => {
Actor::stopping(&mut self.act, ctx); Actor::stopping(act, ctx);
} }
_ => () _ => ()
} }
@ -134,7 +143,7 @@ impl<A> Stream for HttpContext<A> where A: Actor<Context=Self> + Route
loop { loop {
let mut not_ready = true; let mut not_ready = true;
if let Ok(Async::Ready(_)) = self.address.poll(&mut self.act, ctx) { if let Ok(Async::Ready(_)) = self.address.poll(act, ctx) {
not_ready = false not_ready = false
} }
@ -146,7 +155,7 @@ impl<A> Stream for HttpContext<A> where A: Actor<Context=Self> + Route
break break
} }
let (drop, item) = match self.items[idx].poll(&mut self.act, ctx) { let (drop, item) = match self.items[idx].poll(act, ctx) {
Ok(val) => match val { Ok(val) => match val {
Async::Ready(_) => { Async::Ready(_) => {
not_ready = false; not_ready = false;
@ -194,7 +203,7 @@ impl<A> Stream for HttpContext<A> where A: Actor<Context=Self> + Route
match self.state { match self.state {
ActorState::Stopped => { ActorState::Stopped => {
self.state = ActorState::Stopped; self.state = ActorState::Stopped;
Actor::stopped(&mut self.act, ctx); Actor::stopped(act, ctx);
return Ok(Async::Ready(None)) return Ok(Async::Ready(None))
}, },
ActorState::Stopping => { ActorState::Stopping => {
@ -204,11 +213,11 @@ impl<A> Stream for HttpContext<A> where A: Actor<Context=Self> + Route
continue continue
} else { } else {
self.state = ActorState::Stopped; self.state = ActorState::Stopped;
Actor::stopped(&mut self.act, ctx); Actor::stopped(act, ctx);
return Ok(Async::Ready(None)) return Ok(Async::Ready(None))
} }
} else { } else {
Actor::stopping(&mut self.act, ctx); Actor::stopping(act, ctx);
prep_stop = true; prep_stop = true;
continue continue
} }
@ -216,7 +225,7 @@ impl<A> Stream for HttpContext<A> where A: Actor<Context=Self> + Route
ActorState::Running => { ActorState::Running => {
if !self.address.connected() && self.items.is_empty() { if !self.address.connected() && self.items.is_empty() {
self.state = ActorState::Stopping; self.state = ActorState::Stopping;
Actor::stopping(&mut self.act, ctx); Actor::stopping(act, ctx);
prep_stop = true; prep_stop = true;
continue continue
} }

View File

@ -5,7 +5,7 @@ use http::StatusCode;
use task::Task; use task::Task;
use route::{Payload, RouteHandler}; use route::{Payload, RouteHandler};
use httpmessage::{Body, HttpRequest, HttpMessage, IntoHttpMessage}; use httpmessage::{Body, HttpRequest, HttpResponse, IntoHttpResponse};
pub struct StaticResponse(StatusCode); pub struct StaticResponse(StatusCode);
@ -20,12 +20,12 @@ pub const HTTPMethodNotAllowed: StaticResponse = StaticResponse(StatusCode::METH
impl<S> RouteHandler<S> for StaticResponse { impl<S> RouteHandler<S> for StaticResponse {
fn handle(&self, req: HttpRequest, _: Option<Payload>, _: Rc<S>) -> Task fn handle(&self, req: HttpRequest, _: Option<Payload>, _: Rc<S>) -> Task
{ {
Task::reply(HttpMessage::new(req, self.0, Body::Empty), None) Task::reply(HttpResponse::new(req, self.0, Body::Empty), None)
} }
} }
impl IntoHttpMessage for StaticResponse { impl IntoHttpResponse for StaticResponse {
fn into_response(self, req: HttpRequest) -> HttpMessage { fn into_response(self, req: HttpRequest) -> HttpResponse {
HttpMessage::new(req, self.0, Body::Empty) HttpResponse::new(req, self.0, Body::Empty)
} }
} }

View File

@ -161,15 +161,22 @@ impl HttpRequest {
} }
} }
/// Represents various types of http message body.
#[derive(Debug)] #[derive(Debug)]
pub enum Body { pub enum Body {
/// Empty response. `Content-Length` header is set to `0`
Empty, Empty,
/// Specific response body. `Content-Length` header is set to length of bytes.
Binary(Bytes), Binary(Bytes),
/// Streaming response body with specified length.
Length(u64), Length(u64),
/// Unspecified streaming response. Developer is responsible for setting
/// right `Content-Length` or `Transfer-Encoding` headers.
Streaming, Streaming,
} }
impl Body { impl Body {
/// Does this body have payload.
pub fn has_body(&self) -> bool { pub fn has_body(&self) -> bool {
match *self { match *self {
Body::Length(_) | Body::Streaming => true, Body::Length(_) | Body::Streaming => true,
@ -178,13 +185,15 @@ impl Body {
} }
} }
pub trait IntoHttpMessage { /// Implements by something that can be converted to `HttpMessage`
fn into_response(self, req: HttpRequest) -> HttpMessage; pub trait IntoHttpResponse {
/// Convert into response.
fn into_response(self, req: HttpRequest) -> HttpResponse;
} }
#[derive(Debug)] #[derive(Debug)]
/// An HTTP Response /// An HTTP Response
pub struct HttpMessage { pub struct HttpResponse {
request: HttpRequest, request: HttpRequest,
pub version: Version, pub version: Version,
pub headers: Headers, pub headers: Headers,
@ -195,7 +204,7 @@ pub struct HttpMessage {
compression: Option<Encoding>, compression: Option<Encoding>,
} }
impl Message for HttpMessage { impl Message for HttpResponse {
fn version(&self) -> Version { fn version(&self) -> Version {
self.version self.version
} }
@ -204,12 +213,12 @@ impl Message for HttpMessage {
} }
} }
impl HttpMessage { impl HttpResponse {
/// Constructs a default response /// Constructs a response
#[inline] #[inline]
pub fn new(request: HttpRequest, status: StatusCode, body: Body) -> HttpMessage { pub fn new(request: HttpRequest, status: StatusCode, body: Body) -> HttpResponse {
let version = request.version; let version = request.version;
HttpMessage { HttpResponse {
request: request, request: request,
version: version, version: version,
headers: Default::default(), headers: Default::default(),
@ -296,10 +305,12 @@ impl HttpMessage {
} }
} }
/// Get body os this response
pub fn body(&self) -> &Body { pub fn body(&self) -> &Body {
&self.body &self.body
} }
/// Set a body and return previous body value
pub fn set_body<B: Into<Body>>(&mut self, body: B) -> Body { pub fn set_body<B: Into<Body>>(&mut self, body: B) -> Body {
mem::replace(&mut self.body, body.into()) mem::replace(&mut self.body, body.into())
} }

View File

@ -30,10 +30,10 @@ mod server;
pub mod httpcodes; pub mod httpcodes;
pub use application::HttpApplication; pub use application::HttpApplication;
pub use route::{Route, RouteFactory, Payload, PayloadItem, Frame}; pub use route::{Route, RouteFactory, RouteHandler, Payload, PayloadItem};
pub use resource::{HttpResource, HttpResponse}; pub use resource::{HttpMessage, HttpResource};
pub use server::HttpServer; pub use server::HttpServer;
pub use context::HttpContext; pub use context::HttpContext;
pub use router::RoutingMap; pub use router::RoutingMap;
pub use route_recognizer::Params; pub use route_recognizer::Params;
pub use httpmessage::{HttpRequest, HttpMessage, IntoHttpMessage}; pub use httpmessage::{HttpRequest, HttpResponse, IntoHttpResponse};

View File

@ -21,13 +21,13 @@ impl Route for MyRoute {
fn request(req: HttpRequest, fn request(req: HttpRequest,
payload: Option<Payload>, payload: Option<Payload>,
ctx: &mut HttpContext<Self>) -> HttpResponse<Self> ctx: &mut HttpContext<Self>) -> HttpMessage<Self>
{ {
if let Some(pl) = payload { if let Some(pl) = payload {
ctx.add_stream(pl); ctx.add_stream(pl);
HttpResponse::Stream(MyRoute{req: Some(req)}) HttpMessage::Stream(MyRoute{req: Some(req)})
} else { } else {
HttpResponse::Reply(req, httpcodes::HTTPOk) HttpMessage::Reply(req, httpcodes::HTTPOk)
} }
} }
} }

View File

@ -1,4 +1,3 @@
use std::mem;
use std::rc::Rc; use std::rc::Rc;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::collections::HashMap; use std::collections::HashMap;
@ -11,7 +10,7 @@ use task::Task;
use route::{Route, Payload, RouteHandler}; use route::{Route, Payload, RouteHandler};
use context::HttpContext; use context::HttpContext;
use httpcodes::HTTPMethodNotAllowed; use httpcodes::HTTPMethodNotAllowed;
use httpmessage::{HttpRequest, HttpMessage, IntoHttpMessage}; use httpmessage::{HttpRequest, HttpResponse, IntoHttpResponse};
/// Resource /// Resource
pub struct HttpResource<S=()> { pub struct HttpResource<S=()> {
@ -32,6 +31,7 @@ impl<S> Default for HttpResource<S> {
impl<S> HttpResource<S> where S: 'static { impl<S> HttpResource<S> where S: 'static {
/// Register handler for specified method.
pub fn handler<H>(&mut self, method: Method, handler: H) -> &mut Self pub fn handler<H>(&mut self, method: Method, handler: H) -> &mut Self
where H: RouteHandler<S> where H: RouteHandler<S>
{ {
@ -39,6 +39,8 @@ impl<S> HttpResource<S> where S: 'static {
self self
} }
/// Default handler is used if no matched route found.
/// By default `HTTPMethodNotAllowed` is used.
pub fn default_handler<H>(&mut self, handler: H) -> &mut Self pub fn default_handler<H>(&mut self, handler: H) -> &mut Self
where H: RouteHandler<S> where H: RouteHandler<S>
{ {
@ -46,21 +48,25 @@ impl<S> HttpResource<S> where S: 'static {
self self
} }
/// Handler for `GET` method.
pub fn get<A>(&mut self) -> &mut Self where A: Route<State=S> pub fn get<A>(&mut self) -> &mut Self where A: Route<State=S>
{ {
self.handler(Method::GET, A::factory()) self.handler(Method::GET, A::factory())
} }
/// Handler for `POST` method.
pub fn post<A>(&mut self) -> &mut Self where A: Route<State=S> pub fn post<A>(&mut self) -> &mut Self where A: Route<State=S>
{ {
self.handler(Method::POST, A::factory()) self.handler(Method::POST, A::factory())
} }
/// Handler for `PUR` method.
pub fn put<A>(&mut self) -> &mut Self where A: Route<State=S> pub fn put<A>(&mut self) -> &mut Self where A: Route<State=S>
{ {
self.handler(Method::PUT, A::factory()) self.handler(Method::PUT, A::factory())
} }
/// Handler for `METHOD` method.
pub fn delete<A>(&mut self) -> &mut Self where A: Route<State=S> pub fn delete<A>(&mut self) -> &mut Self where A: Route<State=S>
{ {
self.handler(Method::DELETE, A::factory()) self.handler(Method::DELETE, A::factory())
@ -81,40 +87,40 @@ impl<S: 'static> RouteHandler<S> for HttpResource<S> {
#[cfg_attr(feature="cargo-clippy", allow(large_enum_variant))] #[cfg_attr(feature="cargo-clippy", allow(large_enum_variant))]
enum HttpResponseItem<A> where A: Actor<Context=HttpContext<A>> + Route { enum HttpMessageItem<A> where A: Actor<Context=HttpContext<A>> + Route {
Message(HttpMessage, Option<Bytes>), Message(HttpResponse, Option<Bytes>),
Actor(A), Actor(A),
} }
pub struct HttpResponse<A: Actor<Context=HttpContext<A>> + Route> (HttpResponseItem<A>); pub struct HttpMessage<A: Actor<Context=HttpContext<A>> + Route> (HttpMessageItem<A>);
impl<A> HttpResponse<A> where A: Actor<Context=HttpContext<A>> + Route impl<A> HttpMessage<A> where A: Actor<Context=HttpContext<A>> + Route
{ {
/// Create async response /// Create async response
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn Stream(act: A) -> Self { pub fn Stream(act: A) -> Self {
HttpResponse(HttpResponseItem::Actor(act)) HttpMessage(HttpMessageItem::Actor(act))
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn Reply<I>(req: HttpRequest, msg: I) -> Self pub fn Reply<I>(req: HttpRequest, msg: I) -> Self
where I: IntoHttpMessage where I: IntoHttpResponse
{ {
HttpResponse(HttpResponseItem::Message(msg.into_response(req), None)) HttpMessage(HttpMessageItem::Message(msg.into_response(req), None))
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn ReplyMessage(msg: HttpMessage, body: Option<Bytes>) -> Self { pub fn ReplyMessage(msg: HttpResponse, body: Option<Bytes>) -> Self {
HttpResponse(HttpResponseItem::Message(msg, body)) HttpMessage(HttpMessageItem::Message(msg, body))
} }
pub(crate) fn into(self, mut ctx: HttpContext<A>) -> Task { pub(crate) fn into(self, mut ctx: HttpContext<A>) -> Task {
match self.0 { match self.0 {
HttpResponseItem::Message(msg, body) => HttpMessageItem::Message(msg, body) => {
Task::reply(msg, body), Task::reply(msg, body)
HttpResponseItem::Actor(act) => { },
let old = ctx.replace_actor(act); HttpMessageItem::Actor(act) => {
mem::forget(old); ctx.set_actor(act);
Task::with_stream(ctx) Task::with_stream(ctx)
} }
} }

View File

@ -1,4 +1,3 @@
use std;
use std::rc::Rc; use std::rc::Rc;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -8,34 +7,41 @@ use futures::unsync::mpsc::Receiver;
use task::Task; use task::Task;
use context::HttpContext; use context::HttpContext;
use resource::HttpResponse; use resource::HttpMessage;
use httpmessage::{HttpRequest, HttpMessage}; use httpmessage::{HttpRequest, HttpResponse};
/// Stream of `PayloadItem`'s
pub type Payload = Receiver<PayloadItem>; pub type Payload = Receiver<PayloadItem>;
/// `PayloadItem` represents one payload item
#[derive(Debug)] #[derive(Debug)]
pub enum PayloadItem { pub enum PayloadItem {
/// Indicates end of payload stream
Eof, Eof,
/// Chunk of bytes
Chunk(Bytes) Chunk(Bytes)
} }
impl PayloadItem { impl PayloadItem {
/// Is item an eof
pub fn is_eof(&self) -> bool { pub fn is_eof(&self) -> bool {
match *self { match *self {
PayloadItem::Eof => true, PayloadItem::Eof => true,
_ => false, _ => false,
} }
} }
/// Is item a chunk
pub fn is_chunk(&self) -> bool { pub fn is_chunk(&self) -> bool {
!self.is_eof() !self.is_eof()
} }
} }
#[doc(hidden)]
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature="cargo-clippy", allow(large_enum_variant))] #[cfg_attr(feature="cargo-clippy", allow(large_enum_variant))]
pub enum Frame { pub enum Frame {
Message(HttpMessage), Message(HttpResponse),
Payload(Option<Bytes>), Payload(Option<Bytes>),
} }
@ -43,12 +49,13 @@ pub trait RouteHandler<S>: 'static {
fn handle(&self, req: HttpRequest, payload: Option<Payload>, state: Rc<S>) -> Task; fn handle(&self, req: HttpRequest, payload: Option<Payload>, state: Rc<S>) -> Task;
} }
/// Actors with ability to handle http requests
pub trait Route: Actor<Context=HttpContext<Self>> { pub trait Route: Actor<Context=HttpContext<Self>> {
type State; type State;
fn request(req: HttpRequest, fn request(req: HttpRequest,
payload: Option<Payload>, payload: Option<Payload>,
ctx: &mut HttpContext<Self>) -> HttpResponse<Self>; ctx: &mut HttpContext<Self>) -> HttpMessage<Self>;
fn factory() -> RouteFactory<Self, Self::State> { fn factory() -> RouteFactory<Self, Self::State> {
RouteFactory(PhantomData) RouteFactory(PhantomData)
@ -64,7 +71,7 @@ impl<A, S> RouteHandler<S> for RouteFactory<A, S>
{ {
fn handle(&self, req: HttpRequest, payload: Option<Payload>, state: Rc<A::State>) -> Task fn handle(&self, req: HttpRequest, payload: Option<Payload>, state: Rc<A::State>) -> Task
{ {
let mut ctx = HttpContext::new(unsafe{std::mem::uninitialized()}, state); let mut ctx = HttpContext::new(state);
A::request(req, payload, &mut ctx).into(ctx) A::request(req, payload, &mut ctx).into(ctx)
} }
} }

View File

@ -8,7 +8,7 @@ use route::{Payload, RouteHandler};
use resource::HttpResource; use resource::HttpResource;
use application::HttpApplication; use application::HttpApplication;
use httpcodes::HTTPNotFound; use httpcodes::HTTPNotFound;
use httpmessage::{HttpRequest, IntoHttpMessage}; use httpmessage::{HttpRequest, IntoHttpResponse};
pub trait HttpHandler: 'static { pub trait HttpHandler: 'static {
fn handle(&self, req: HttpRequest, payload: Option<Payload>) -> Task; fn handle(&self, req: HttpRequest, payload: Option<Payload>) -> Task;
@ -91,7 +91,7 @@ impl Router {
} }
} }
Task::reply(IntoHttpMessage::into_response(HTTPNotFound, req), None) Task::reply(IntoHttpResponse::into_response(HTTPNotFound, req), None)
} }
} }
} }

View File

@ -10,6 +10,7 @@ use task::Task;
use reader::Reader; use reader::Reader;
use router::{Router, RoutingMap}; use router::{Router, RoutingMap};
/// An HTTP Server.
pub struct HttpServer { pub struct HttpServer {
router: Rc<Router>, router: Rc<Router>,
} }
@ -19,10 +20,12 @@ impl Actor for HttpServer {
} }
impl HttpServer { impl HttpServer {
/// Create new http server with specified `RoutingMap`
pub fn new(routes: RoutingMap) -> Self { pub fn new(routes: RoutingMap) -> Self {
HttpServer {router: Rc::new(routes.into_router())} HttpServer {router: Rc::new(routes.into_router())}
} }
/// Start listening for incomming connections.
pub fn serve<Addr>(self, addr: &net::SocketAddr) -> io::Result<Addr> pub fn serve<Addr>(self, addr: &net::SocketAddr) -> io::Result<Addr>
where Self: ActorAddress<Self, Addr> where Self: ActorAddress<Self, Addr>
{ {

View File

@ -13,7 +13,7 @@ use hyper::header::{Date, Connection, ContentType,
use date; use date;
use route::Frame; use route::Frame;
use httpmessage::{Body, HttpMessage}; use httpmessage::{Body, HttpResponse};
type FrameStream = Stream<Item=Frame, Error=io::Error>; type FrameStream = Stream<Item=Frame, Error=io::Error>;
const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
@ -57,7 +57,7 @@ pub struct Task {
impl Task { impl Task {
pub(crate) fn reply(msg: HttpMessage, body: Option<Bytes>) -> Self { pub(crate) fn reply(msg: HttpResponse, body: Option<Bytes>) -> Self {
let mut frames = VecDeque::new(); let mut frames = VecDeque::new();
if let Some(body) = body { if let Some(body) = body {
frames.push_back(Frame::Message(msg)); frames.push_back(Frame::Message(msg));
@ -90,7 +90,7 @@ impl Task {
} }
} }
fn prepare(&mut self, mut msg: HttpMessage) fn prepare(&mut self, mut msg: HttpResponse)
{ {
trace!("Prepare message status={:?}", msg.status); trace!("Prepare message status={:?}", msg.status);