mirror of
https://github.com/fafhrd91/actix-web
synced 2025-07-08 20:06:32 +02:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
e58b38fd13 | |||
b043c34632 | |||
b748bf3b0d | |||
be12d5e6fc | |||
7c4941f868 | |||
d1f5c457c4 | |||
c26c5fd9a4 | |||
4a73d1c8c1 | |||
7c395fcc83 | |||
54c33a7aff | |||
47d80382b2 | |||
ba816a8562 | |||
6f75b0e95e | |||
b3cc43bb9b |
16
CHANGES.md
16
CHANGES.md
@ -1,5 +1,21 @@
|
||||
# Changes
|
||||
|
||||
## 0.6.2 (2018-05-09)
|
||||
|
||||
* WsWriter trait is optional.
|
||||
|
||||
|
||||
## 0.6.1 (2018-05-08)
|
||||
|
||||
* Fix http/2 payload streaming #215
|
||||
|
||||
* Fix connector's default `keep-alive` and `lifetime` settings #212
|
||||
|
||||
* Send `ErrorNotFound` instead of `ErrorBadRequest` when path extractor fails #214
|
||||
|
||||
* Allow to exclude certain endpoints from logging #211
|
||||
|
||||
|
||||
## 0.6.0 (2018-05-08)
|
||||
|
||||
* Add route scopes #202
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-web"
|
||||
version = "0.6.0"
|
||||
version = "0.6.2"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust."
|
||||
readme = "README.md"
|
||||
|
16
MIGRATION.md
16
MIGRATION.md
@ -1,5 +1,7 @@
|
||||
## Migration from 0.5 to 0.6
|
||||
|
||||
* `Path<T>` extractor return `ErrorNotFound` on failure instead of `ErrorBadRequest`
|
||||
|
||||
* `ws::Message::Close` now includes optional close reason.
|
||||
`ws::CloseCode::Status` and `ws::CloseCode::Empty` have been removed.
|
||||
|
||||
@ -11,6 +13,17 @@
|
||||
* `HttpRequest::extensions()` returns read only reference to the request's Extension
|
||||
`HttpRequest::extensions_mut()` returns mutable reference.
|
||||
|
||||
* Instead of
|
||||
|
||||
`use actix_web::middleware::{
|
||||
CookieSessionBackend, CookieSessionError, RequestSession,
|
||||
Session, SessionBackend, SessionImpl, SessionStorage};`
|
||||
|
||||
use `actix_web::middleware::session`
|
||||
|
||||
`use actix_web::middleware::session{CookieSessionBackend, CookieSessionError,
|
||||
RequestSession, Session, SessionBackend, SessionImpl, SessionStorage};`
|
||||
|
||||
* `FromRequest::from_request()` accepts mutable reference to a request
|
||||
|
||||
* `FromRequest::Result` has to implement `Into<Reply<Self>>`
|
||||
@ -33,6 +46,9 @@
|
||||
let q = Query::<HashMap<String, String>>::extract(req);
|
||||
```
|
||||
|
||||
* Websocket operations are implemented as `WsWriter` trait.
|
||||
you need to use `use actix_web::ws::WsWriter`
|
||||
|
||||
|
||||
## Migration from 0.4 to 0.5
|
||||
|
||||
|
@ -223,8 +223,8 @@ impl Default for ClientConnector {
|
||||
pool: Rc::new(Pool::new(Rc::clone(&_modified))),
|
||||
pool_modified: _modified,
|
||||
connector: builder.build().unwrap(),
|
||||
conn_lifetime: Duration::from_secs(15),
|
||||
conn_keep_alive: Duration::from_secs(75),
|
||||
conn_lifetime: Duration::from_secs(75),
|
||||
conn_keep_alive: Duration::from_secs(15),
|
||||
limit: 100,
|
||||
limit_per_host: 0,
|
||||
acquired: 0,
|
||||
@ -243,8 +243,8 @@ impl Default for ClientConnector {
|
||||
subscriber: None,
|
||||
pool: Rc::new(Pool::new(Rc::clone(&_modified))),
|
||||
pool_modified: _modified,
|
||||
conn_lifetime: Duration::from_secs(15),
|
||||
conn_keep_alive: Duration::from_secs(75),
|
||||
conn_lifetime: Duration::from_secs(75),
|
||||
conn_keep_alive: Duration::from_secs(15),
|
||||
limit: 100,
|
||||
limit_per_host: 0,
|
||||
acquired: 0,
|
||||
|
@ -11,7 +11,7 @@ use serde::de::{self, DeserializeOwned};
|
||||
use serde_urlencoded;
|
||||
|
||||
use de::PathDeserializer;
|
||||
use error::{Error, ErrorBadRequest};
|
||||
use error::{Error, ErrorNotFound, ErrorBadRequest};
|
||||
use handler::{AsyncResult, FromRequest};
|
||||
use httpmessage::{HttpMessage, MessageBody, UrlEncoded};
|
||||
use httprequest::HttpRequest;
|
||||
@ -108,7 +108,7 @@ where
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
let req = req.clone();
|
||||
de::Deserialize::deserialize(PathDeserializer::new(&req))
|
||||
.map_err(|e| e.into())
|
||||
.map_err(ErrorNotFound)
|
||||
.map(|inner| Path { inner })
|
||||
}
|
||||
}
|
||||
|
@ -175,6 +175,9 @@ pub use httprequest::HttpRequest;
|
||||
pub use httpresponse::HttpResponse;
|
||||
pub use json::Json;
|
||||
pub use scope::Scope;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[deprecated(since = "0.6.2", note = "please use `use actix_web::ws::WsWriter`")]
|
||||
pub use ws::WsWriter;
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Request logging middleware
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use libc;
|
||||
use regex::Regex;
|
||||
@ -74,6 +74,7 @@ use middleware::{Finished, Middleware, Started};
|
||||
///
|
||||
pub struct Logger {
|
||||
format: Format,
|
||||
exclude: HashSet<String>,
|
||||
}
|
||||
|
||||
impl Logger {
|
||||
@ -81,8 +82,15 @@ impl Logger {
|
||||
pub fn new(format: &str) -> Logger {
|
||||
Logger {
|
||||
format: Format::new(format),
|
||||
exclude: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Ignore and do not log access info for specified path.
|
||||
pub fn exclude<T: Into<String>>(mut self, path: T) -> Self {
|
||||
self.exclude.insert(path.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Logger {
|
||||
@ -94,6 +102,7 @@ impl Default for Logger {
|
||||
fn default() -> Logger {
|
||||
Logger {
|
||||
format: Format::default(),
|
||||
exclude: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,21 +111,23 @@ struct StartTime(time::Tm);
|
||||
|
||||
impl Logger {
|
||||
fn log<S>(&self, req: &mut HttpRequest<S>, resp: &HttpResponse) {
|
||||
let entry_time = req.extensions().get::<StartTime>().unwrap().0;
|
||||
|
||||
let render = |fmt: &mut Formatter| {
|
||||
for unit in &self.format.0 {
|
||||
unit.render(fmt, req, resp, entry_time)?;
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
info!("{}", FormatDisplay(&render));
|
||||
if let Some(entry_time) = req.extensions().get::<StartTime>() {
|
||||
let render = |fmt: &mut Formatter| {
|
||||
for unit in &self.format.0 {
|
||||
unit.render(fmt, req, resp, entry_time.0)?;
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
info!("{}", FormatDisplay(&render));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Middleware<S> for Logger {
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
req.extensions_mut().insert(StartTime(time::now()));
|
||||
if !self.exclude.contains(req.path()) {
|
||||
req.extensions_mut().insert(StartTime(time::now()));
|
||||
}
|
||||
Ok(Started::Done)
|
||||
}
|
||||
|
||||
|
@ -492,8 +492,8 @@ impl<S: 'static, H> ProcessResponse<S, H> {
|
||||
if let Some(err) = self.resp.error() {
|
||||
if self.resp.status().is_server_error() {
|
||||
error!(
|
||||
"Error occured during request handling: {}",
|
||||
err
|
||||
"Error occured during request handling, status: {} {}",
|
||||
self.resp.status(), err
|
||||
);
|
||||
} else {
|
||||
warn!(
|
||||
|
@ -76,7 +76,7 @@ impl<S: 'static> Scope<S> {
|
||||
mem::replace(&mut self.filters, Vec::new())
|
||||
}
|
||||
|
||||
/// Add match predicate to scoupe.
|
||||
/// Add match predicate to scope.
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate actix_web;
|
||||
@ -787,10 +787,10 @@ mod tests {
|
||||
let mut app = App::new()
|
||||
.scope("app", |scope| {
|
||||
scope
|
||||
.route("/path1", Method::GET, |r: HttpRequest<_>| {
|
||||
.route("/path1", Method::GET, |_: HttpRequest<_>| {
|
||||
HttpResponse::Ok()
|
||||
})
|
||||
.route("/path1", Method::DELETE, |r: HttpRequest<_>| {
|
||||
.route("/path1", Method::DELETE, |_: HttpRequest<_>| {
|
||||
HttpResponse::Ok()
|
||||
})
|
||||
})
|
||||
|
@ -343,24 +343,27 @@ impl<H: 'static> Entry<H> {
|
||||
}
|
||||
|
||||
fn poll_payload(&mut self) {
|
||||
if !self.flags.contains(EntryFlags::REOF) {
|
||||
if self.payload.need_read() == PayloadStatus::Read {
|
||||
if let Err(err) = self.recv.release_capacity().release_capacity(32_768) {
|
||||
self.payload.set_error(PayloadError::Http2(err))
|
||||
}
|
||||
} else if let Err(err) = self.recv.release_capacity().release_capacity(0) {
|
||||
self.payload.set_error(PayloadError::Http2(err))
|
||||
}
|
||||
|
||||
while !self.flags.contains(EntryFlags::REOF)
|
||||
&& self.payload.need_read() == PayloadStatus::Read
|
||||
{
|
||||
match self.recv.poll() {
|
||||
Ok(Async::Ready(Some(chunk))) => {
|
||||
let l = chunk.len();
|
||||
self.payload.feed_data(chunk);
|
||||
if let Err(err) = self.recv.release_capacity().release_capacity(l) {
|
||||
self.payload.set_error(PayloadError::Http2(err));
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(Async::Ready(None)) => {
|
||||
self.flags.insert(EntryFlags::REOF);
|
||||
self.payload.feed_eof();
|
||||
}
|
||||
Ok(Async::NotReady) => break,
|
||||
Err(err) => {
|
||||
self.payload.set_error(PayloadError::Http2(err));
|
||||
break;
|
||||
}
|
||||
Ok(Async::NotReady) => (),
|
||||
Err(err) => self.payload.set_error(PayloadError::Http2(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -518,24 +518,22 @@ impl ClientWriter {
|
||||
fn as_mut(&mut self) -> &mut Inner {
|
||||
unsafe { &mut *self.inner.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl WsWriter for ClientWriter {
|
||||
/// Send text frame
|
||||
#[inline]
|
||||
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, true));
|
||||
}
|
||||
|
||||
/// Send binary frame
|
||||
#[inline]
|
||||
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, true));
|
||||
}
|
||||
|
||||
/// Send ping frame
|
||||
#[inline]
|
||||
fn ping(&mut self, message: &str) {
|
||||
pub fn ping(&mut self, message: &str) {
|
||||
self.write(Frame::message(
|
||||
Vec::from(message),
|
||||
OpCode::Ping,
|
||||
@ -546,7 +544,7 @@ impl WsWriter for ClientWriter {
|
||||
|
||||
/// Send pong frame
|
||||
#[inline]
|
||||
fn pong(&mut self, message: &str) {
|
||||
pub fn pong(&mut self, message: &str) {
|
||||
self.write(Frame::message(
|
||||
Vec::from(message),
|
||||
OpCode::Pong,
|
||||
@ -557,7 +555,39 @@ impl WsWriter for ClientWriter {
|
||||
|
||||
/// Send close frame
|
||||
#[inline]
|
||||
fn close(&mut self, reason: Option<CloseReason>) {
|
||||
pub fn close(&mut self, reason: Option<CloseReason>) {
|
||||
self.write(Frame::close(reason, true));
|
||||
}
|
||||
}
|
||||
|
||||
impl WsWriter for ClientWriter {
|
||||
/// Send text frame
|
||||
#[inline]
|
||||
fn send_text<T: Into<Binary>>(&mut self, text: T) {
|
||||
self.text(text)
|
||||
}
|
||||
|
||||
/// Send binary frame
|
||||
#[inline]
|
||||
fn send_binary<B: Into<Binary>>(&mut self, data: B) {
|
||||
self.binary(data)
|
||||
}
|
||||
|
||||
/// Send ping frame
|
||||
#[inline]
|
||||
fn send_ping(&mut self, message: &str) {
|
||||
self.ping(message)
|
||||
}
|
||||
|
||||
/// Send pong frame
|
||||
#[inline]
|
||||
fn send_pong(&mut self, message: &str) {
|
||||
self.pong(message)
|
||||
}
|
||||
|
||||
/// Send close frame
|
||||
#[inline]
|
||||
fn send_close(&mut self, reason: Option<CloseReason>) {
|
||||
self.close(reason);
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +149,46 @@ where
|
||||
Drain::new(rx)
|
||||
}
|
||||
|
||||
/// Send text frame
|
||||
#[inline]
|
||||
pub fn text<T: Into<Binary>>(&mut self, text: T) {
|
||||
self.write(Frame::message(text.into(), OpCode::Text, true, false));
|
||||
}
|
||||
|
||||
/// Send binary frame
|
||||
#[inline]
|
||||
pub fn binary<B: Into<Binary>>(&mut self, data: B) {
|
||||
self.write(Frame::message(data, OpCode::Binary, true, false));
|
||||
}
|
||||
|
||||
/// Send ping frame
|
||||
#[inline]
|
||||
pub fn ping(&mut self, message: &str) {
|
||||
self.write(Frame::message(
|
||||
Vec::from(message),
|
||||
OpCode::Ping,
|
||||
true,
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
||||
/// Send pong frame
|
||||
#[inline]
|
||||
pub fn pong(&mut self, message: &str) {
|
||||
self.write(Frame::message(
|
||||
Vec::from(message),
|
||||
OpCode::Pong,
|
||||
true,
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
||||
/// Send close frame
|
||||
#[inline]
|
||||
pub fn close(&mut self, reason: Option<CloseReason>) {
|
||||
self.write(Frame::close(reason, false));
|
||||
}
|
||||
|
||||
/// Check if connection still open
|
||||
#[inline]
|
||||
pub fn connected(&self) -> bool {
|
||||
@ -181,42 +221,32 @@ where
|
||||
{
|
||||
/// Send text frame
|
||||
#[inline]
|
||||
fn text<T: Into<Binary>>(&mut self, text: T) {
|
||||
self.write(Frame::message(text.into(), OpCode::Text, true, false));
|
||||
fn send_text<T: Into<Binary>>(&mut self, text: T) {
|
||||
self.text(text)
|
||||
}
|
||||
|
||||
/// Send binary frame
|
||||
#[inline]
|
||||
fn binary<B: Into<Binary>>(&mut self, data: B) {
|
||||
self.write(Frame::message(data, OpCode::Binary, true, false));
|
||||
fn send_binary<B: Into<Binary>>(&mut self, data: B) {
|
||||
self.binary(data)
|
||||
}
|
||||
|
||||
/// Send ping frame
|
||||
#[inline]
|
||||
fn ping(&mut self, message: &str) {
|
||||
self.write(Frame::message(
|
||||
Vec::from(message),
|
||||
OpCode::Ping,
|
||||
true,
|
||||
false,
|
||||
));
|
||||
fn send_ping(&mut self, message: &str) {
|
||||
self.ping(message)
|
||||
}
|
||||
|
||||
/// Send pong frame
|
||||
#[inline]
|
||||
fn pong(&mut self, message: &str) {
|
||||
self.write(Frame::message(
|
||||
Vec::from(message),
|
||||
OpCode::Pong,
|
||||
true,
|
||||
false,
|
||||
));
|
||||
fn send_pong(&mut self, message: &str) {
|
||||
self.pong(message)
|
||||
}
|
||||
|
||||
/// Send close frame
|
||||
#[inline]
|
||||
fn close(&mut self, reason: Option<CloseReason>) {
|
||||
self.write(Frame::close(reason, false));
|
||||
fn send_close(&mut self, reason: Option<CloseReason>) {
|
||||
self.close(reason)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,15 +343,15 @@ where
|
||||
/// Common writing methods for a websocket.
|
||||
pub trait WsWriter {
|
||||
/// Send a text
|
||||
fn text<T: Into<Binary>>(&mut self, text: T);
|
||||
fn send_text<T: Into<Binary>>(&mut self, text: T);
|
||||
/// Send a binary
|
||||
fn binary<B: Into<Binary>>(&mut self, data: B);
|
||||
fn send_binary<B: Into<Binary>>(&mut self, data: B);
|
||||
/// Send a ping message
|
||||
fn ping(&mut self, message: &str);
|
||||
fn send_ping(&mut self, message: &str);
|
||||
/// Send a pong message
|
||||
fn pong(&mut self, message: &str);
|
||||
fn send_pong(&mut self, message: &str);
|
||||
/// Close the connection
|
||||
fn close(&mut self, reason: Option<CloseReason>);
|
||||
fn send_close(&mut self, reason: Option<CloseReason>);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -809,7 +809,7 @@ fn test_h2() {
|
||||
})
|
||||
});
|
||||
let _res = core.run(tcp);
|
||||
// assert_eq!(res.unwrap(), Bytes::from_static(STR.as_ref()));
|
||||
// assert_eq!(_res.unwrap(), Bytes::from_static(STR.as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Reference in New Issue
Block a user