Co-authored-by: Jonas Platte <jplatte@users.noreply.github.com> Co-authored-by: Igor Aleksanov <popzxc@yandex.ru> Co-authored-by: Rob Ede <robjtede@icloud.com>
18 KiB
Unreleased
-
The default
NormalizePath
behavior now strips trailing slashes by default. This was previously documented to be the case in v3 but the behavior now matches. The effect is that routes defined with trailing slashes will become inaccessible when usingNormalizePath::default()
. As such, callingNormalizePath::default()
will log a warning. It is advised that thenew
method be used instead.Before:
#[get("/test/")]
After:#[get("/test")]
Alternatively, explicitly require trailing slashes:
NormalizePath::new(TrailingSlash::Always)
. -
The
type Config
ofFromRequest
was removed. -
Feature flag
compress
has been split into its supported algorithm (brotli, gzip, zstd). By default all compression algorithms are enabled. To select algorithm you want to include withmiddleware::Compress
use following flags:compress-brotli
compress-gzip
compress-zstd
If you have set in yourCargo.toml
dedicatedactix-web
features and you still want to have compression enabled. Please change features selection like bellow:
Before:
"compress"
After:"compress-brotli", "compress-gzip", "compress-zstd"
3.0.0
-
The return type for
ServiceRequest::app_data::<T>()
was changed from returning aData<T>
to simply aT
. To access aData<T>
useServiceRequest::app_data::<Data<T>>()
. -
Cookie handling has been offloaded to the
cookie
crate:USERINFO_ENCODE_SET
is no longer exposed. Percent-encoding is still supported; check docs.- Some types now require lifetime parameters.
-
The time crate was updated to
v0.2
, a major breaking change to the time crate, which affects anyactix-web
method previously expecting a time v0.1 input. -
Setting a cookie's SameSite property, explicitly, to
SameSite::None
will now result inSameSite=None
being sent with the response Set-Cookie header. To create a cookie without a SameSite attribute, remove any calls setting same_site. -
actix-http support for Actors messages was moved to actix-http crate and is enabled with feature
actors
-
content_length function is removed from actix-http. You can set Content-Length by normally setting the response body or calling no_chunking function.
-
BodySize::Sized64
variant has been removed.BodySize::Sized
now receives au64
instead of ausize
. -
Code that was using
path.<index>
to access aweb::Path<(A, B, C)>
s elements now needs to use destructuring or.into_inner()
. For example:// Previously: async fn some_route(path: web::Path<(String, String)>) -> String { format!("Hello, {} {}", path.0, path.1) } // Now (this also worked before): async fn some_route(path: web::Path<(String, String)>) -> String { let (first_name, last_name) = path.into_inner(); format!("Hello, {} {}", first_name, last_name) } // Or (this wasn't previously supported): async fn some_route(web::Path((first_name, last_name)): web::Path<(String, String)>) -> String { format!("Hello, {} {}", first_name, last_name) }
-
middleware::NormalizePath
can now also be configured to trim trailing slashes instead of always keeping one. It will needmiddleware::normalize::TrailingSlash
when being constructed withNormalizePath::new(...)
, or for an easier migration you can replacewrap(middleware::NormalizePath)
withwrap(middleware::NormalizePath::new(TrailingSlash::MergeOnly))
. -
HttpServer::maxconn
is renamed to the more expressiveHttpServer::max_connections
. -
HttpServer::maxconnrate
is renamed to the more expressiveHttpServer::max_connection_rate
.
2.0.0
-
HttpServer::start()
renamed toHttpServer::run()
. It also possible to.await
onrun
method result, in that case it awaits server exit. -
App::register_data()
renamed toApp::app_data()
and accepts any typeT: 'static
. Stored data is available viaHttpRequest::app_data()
method at runtime. -
Extractor configuration must be registered with
App::app_data()
instead ofApp::data()
-
Sync handlers has been removed.
.to_async()
method has been renamed to.to()
replacefn
withasync fn
to convert sync handler to async -
actix_http_test::TestServer
moved toactix_web::test
module. To start test server usetest::start()
ortest_start_with_config()
methods -
ResponseError
trait has been reafctored.ResponseError::error_response()
renders http response. -
Feature
rust-tls
renamed torustls
instead of
actix-web = { version = "2.0.0", features = ["rust-tls"] }
use
actix-web = { version = "2.0.0", features = ["rustls"] }
-
Feature
ssl
renamed toopenssl
instead of
actix-web = { version = "2.0.0", features = ["ssl"] }
use
actix-web = { version = "2.0.0", features = ["openssl"] }
-
Cors
builder now requires that you call.finish()
to construct the middleware
1.0.1
-
Cors middleware has been moved to
actix-cors
crateinstead of
use actix_web::middleware::cors::Cors;
use
use actix_cors::Cors;
-
Identity middleware has been moved to
actix-identity
crateinstead of
use actix_web::middleware::identity::{Identity, CookieIdentityPolicy, IdentityService};
use
use actix_identity::{Identity, CookieIdentityPolicy, IdentityService};
1.0.0
-
Extractor configuration. In version 1.0 this is handled with the new
Data
mechanism for both setting and retrieving the configurationinstead of
#[derive(Default)] struct ExtractorConfig { config: String, } impl FromRequest for YourExtractor { type Config = ExtractorConfig; type Result = Result<YourExtractor, Error>; fn from_request(req: &HttpRequest, cfg: &Self::Config) -> Self::Result { println!("use the config: {:?}", cfg.config); ... } } App::new().resource("/route_with_config", |r| { r.post().with_config(handler_fn, |cfg| { cfg.0.config = "test".to_string(); }) })
use the HttpRequest to get the configuration like any other
Data
withreq.app_data::<C>()
and set it with thedata()
method on theresource
#[derive(Default)] struct ExtractorConfig { config: String, } impl FromRequest for YourExtractor { type Error = Error; type Future = Result<Self, Self::Error>; type Config = ExtractorConfig; fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { let cfg = req.app_data::<ExtractorConfig>(); println!("config data?: {:?}", cfg.unwrap().role); ... } } App::new().service( resource("/route_with_config") .data(ExtractorConfig { config: "test".to_string(), }) .route(post().to(handler_fn)), )
-
Resource registration. 1.0 version uses generalized resource registration via
.service()
method.instead of
App.new().resource("/welcome", |r| r.f(welcome))
use App's or Scope's
.service()
method..service()
method accepts object that implementsHttpServiceFactory
trait. By default actix-web providesResource
andScope
services.App.new().service( web::resource("/welcome") .route(web::get().to(welcome)) .route(web::post().to(post_handler))
-
Scope registration.
instead of
let app = App::new().scope("/{project_id}", |scope| { scope .resource("/path1", |r| r.f(|_| HttpResponse::Ok())) .resource("/path2", |r| r.f(|_| HttpResponse::Ok())) .resource("/path3", |r| r.f(|_| HttpResponse::MethodNotAllowed())) });
use
.service()
for registration andweb::scope()
as scope object factory.let app = App::new().service( web::scope("/{project_id}") .service(web::resource("/path1").to(|| HttpResponse::Ok())) .service(web::resource("/path2").to(|| HttpResponse::Ok())) .service(web::resource("/path3").to(|| HttpResponse::MethodNotAllowed())) );
-
.with()
,.with_async()
registration methods have been renamed to.to()
and.to_async()
.instead of
App.new().resource("/welcome", |r| r.with(welcome))
use
.to()
or.to_async()
methodsApp.new().service(web::resource("/welcome").to(welcome))
-
Passing arguments to handler with extractors, multiple arguments are allowed
instead of
fn welcome((body, req): (Bytes, HttpRequest)) -> ... { ... }
use multiple arguments
fn welcome(body: Bytes, req: HttpRequest) -> ... { ... }
-
.f()
,.a()
and.h()
handler registration methods have been removed. Use.to()
for handlers and.to_async()
for async handlers. Handler function must use extractors.instead of
App.new().resource("/welcome", |r| r.f(welcome))
use App's
to()
orto_async()
methodsApp.new().service(web::resource("/welcome").to(welcome))
-
HttpRequest
does not provide access to request's payload stream.instead of
fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> { req .payload() .from_err() .fold((), |_, chunk| { ... }) .map(|_| HttpResponse::Ok().finish()) .responder() }
use
Payload
extractorfn index(stream: web::Payload) -> impl Future<Item=HttpResponse, Error=Error> { stream .from_err() .fold((), |_, chunk| { ... }) .map(|_| HttpResponse::Ok().finish()) }
-
State
is nowData
. You register Data during the App initialization process and then access it from handlers either using a Data extractor or using HttpRequest's api.instead of
App.with_state(T)
use App's
data
methodApp.new() .data(T)
and either use the Data extractor within your handler
use actix_web::web::Data; fn endpoint_handler(Data<T>)){ ... }
.. or access your Data element from the HttpRequest
fn endpoint_handler(req: HttpRequest) { let data: Option<Data<T>> = req.app_data::<T>(); }
-
AsyncResponder is removed, use
.to_async()
registration method andimpl Future<>
as result type.instead of
use actix_web::AsyncResponder; fn endpoint_handler(...) -> impl Future<Item=HttpResponse, Error=Error>{ ... .responder() }
.. simply omit AsyncResponder and the corresponding responder() finish method
-
Middleware
instead of
let app = App::new() .middleware(middleware::Logger::default())
use
.wrap()
methodlet app = App::new() .wrap(middleware::Logger::default()) .route("/index.html", web::get().to(index));
-
HttpRequest::body()
,HttpRequest::urlencoded()
,HttpRequest::json()
,HttpRequest::multipart()
method have been removed. UseBytes
,String
,Form
,Json
,Multipart
extractors instead.instead of
fn index(req: &HttpRequest) -> Responder { req.body() .and_then(|body| { ... }) }
use
fn index(body: Bytes) -> Responder { ... }
-
actix_web::server
module has been removed. To start http server useactix_web::HttpServer
type -
StaticFiles and NamedFile have been moved to a separate crate.
instead of
use actix_web::fs::StaticFile
use
use actix_files::Files
instead of
use actix_web::fs::Namedfile
use
use actix_files::NamedFile
-
Multipart has been moved to a separate crate.
instead of
use actix_web::multipart::Multipart
use
use actix_multipart::Multipart
-
Response compression is not enabled by default. To enable, use
Compress
middleware,App::new().wrap(Compress::default())
. -
Session middleware moved to actix-session crate
-
Actors support have been moved to
actix-web-actors
crate -
Custom Error
Instead of error_response method alone, ResponseError now provides two methods: error_response and render_response respectively. Where, error_response creates the error response and render_response returns the error response to the caller.
Simplest migration from 0.7 to 1.0 shall include below method to the custom implementation of ResponseError:
fn render_response(&self) -> HttpResponse { self.error_response() }
0.7.15
-
The
' '
character is not percent decoded anymore before matching routes. If you need to use it in your routes, you should use%20
.instead of
fn main() { let app = App::new().resource("/my index", |r| { r.method(http::Method::GET) .with(index); }); }
use
fn main() { let app = App::new().resource("/my%20index", |r| { r.method(http::Method::GET) .with(index); }); }
-
If you used
AsyncResult::async
you need to replace it withAsyncResult::future
0.7.4
Route::with_config()
/Route::with_async_config()
always passes configuration objects as tuple even for handler with one parameter.
0.7
-
HttpRequest
does not implementStream
anymore. If you need to read request payload useHttpMessage::payload()
method.instead of
fn index(req: HttpRequest) -> impl Responder { req .from_err() .fold(...) .... }
use
.payload()
fn index(req: HttpRequest) -> impl Responder { req .payload() // <- get request payload stream .from_err() .fold(...) .... }
-
Middleware trait uses
&HttpRequest
instead of&mut HttpRequest
. -
Removed
Route::with2()
andRoute::with3()
use tuple of extractors instead.instead of
fn index(query: Query<..>, info: Json<MyStruct) -> impl Responder {}
use tuple of extractors and use
.with()
for registration:fn index((query, json): (Query<..>, Json<MyStruct)) -> impl Responder {}
-
Handler::handle()
uses&self
instead of&mut self
-
Handler::handle()
accepts reference toHttpRequest<_>
instead of value -
Removed deprecated
HttpServer::threads()
, use HttpServer::workers() instead. -
Renamed
client::ClientConnectorError::Connector
toclient::ClientConnectorError::Resolver
-
Route::with()
does not returnExtractorConfig
, to configure extractor useRoute::with_config()
instead of
fn main() { let app = App::new().resource("/index.html", |r| { r.method(http::Method::GET) .with(index) .limit(4096); // <- limit size of the payload }); }
use
fn main() { let app = App::new().resource("/index.html", |r| { r.method(http::Method::GET) .with_config(index, |cfg| { // <- register handler cfg.limit(4096); // <- limit size of the payload }) }); }
-
Route::with_async()
does not returnExtractorConfig
, to configure extractor useRoute::with_async_config()
0.6
-
Path<T>
extractor returnErrorNotFound
on failure instead ofErrorBadRequest
-
ws::Message::Close
now includes optional close reason.ws::CloseCode::Status
andws::CloseCode::Empty
have been removed. -
HttpServer::threads()
renamed toHttpServer::workers()
. -
HttpServer::start_ssl()
andHttpServer::start_tls()
deprecated. UseHttpServer::bind_ssl()
andHttpServer::bind_tls()
instead. -
HttpRequest::extensions()
returns read only reference to the request's ExtensionHttpRequest::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 implementInto<Reply<Self>>
-
Responder::respond_to()
is generic overS
-
Use
Query
extractor instead of HttpRequest::query()`.fn index(q: Query<HashMap<String, String>>) -> Result<..> { ... }
or
let q = Query::<HashMap<String, String>>::extract(req);
-
Websocket operations are implemented as
WsWriter
trait. you need to useuse actix_web::ws::WsWriter
0.5
-
HttpResponseBuilder::body()
,.finish()
,.json()
methods returnHttpResponse
instead ofResult<HttpResponse>
-
actix_web::Method
,actix_web::StatusCode
,actix_web::Version
moved toactix_web::http
module -
actix_web::header
moved toactix_web::http::header
-
NormalizePath
moved toactix_web::http
module -
HttpServer
moved toactix_web::server
, added newactix_web::server::new()
function, shortcut foractix_web::server::HttpServer::new()
-
DefaultHeaders
middleware does not use separate builder, all builder methods moved to type itself -
StaticFiles::new()
's show_index parameter removed, useshow_files_listing()
method instead. -
CookieSessionBackendBuilder
removed, all methods moved toCookieSessionBackend
type -
actix_web::httpcodes
module is deprecated,HttpResponse::Ok()
,HttpResponse::Found()
and otherHttpResponse::XXX()
functions should be used instead -
ClientRequestBuilder::body()
returnsResult<_, actix_web::Error>
instead ofResult<_, http::Error>
-
Application
renamed to aApp
-
actix_web::Reply
,actix_web::Resource
moved toactix_web::dev