mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-23 23:51:06 +01:00
docs
This commit is contained in:
parent
0b5f0c4f22
commit
a505be9321
@ -1,7 +1,5 @@
|
|||||||
language: rust
|
language: rust
|
||||||
rust:
|
rust:
|
||||||
- 1.18.0
|
|
||||||
- 1.19.0
|
|
||||||
- 1.20.0
|
- 1.20.0
|
||||||
- nightly
|
- nightly
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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};
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
src/route.rs
19
src/route.rs
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user