-
The default
NormalizePathbehavior 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 thenewmethod be used instead.Before:
#[get("/test/")]
After:#[get("/test")]Alternatively, explicitly require trailing slashes:
NormalizePath::new(TrailingSlash::Always). -
The
type ConfigofFromRequestwas removed. -
Feature flag
compresshas been split into its supported algorithm (brotli, gzip, zstd). By default all compression algorithms are enabled. To select algorithm you want to include withmiddleware::Compressuse following flags:compress-brotlicompress-gzipcompress-zstdIf you have set in yourCargo.tomldedicatedactix-webfeatures and you still want to have compression enabled. Please change features selection like bellow:
Before:
"compress"After:"compress-brotli", "compress-gzip", "compress-zstd"
-
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
cookiecrate:USERINFO_ENCODE_SETis 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-webmethod previously expecting a time v0.1 input. -
Setting a cookie's SameSite property, explicitly, to
SameSite::Nonewill now result inSameSite=Nonebeing 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::Sized64variant has been removed.BodySize::Sizednow receives au64instead 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::NormalizePathcan now also be configured to trim trailing slashes instead of always keeping one. It will needmiddleware::normalize::TrailingSlashwhen being constructed withNormalizePath::new(...), or for an easier migration you can replacewrap(middleware::NormalizePath)withwrap(middleware::NormalizePath::new(TrailingSlash::MergeOnly)). -
HttpServer::maxconnis renamed to the more expressiveHttpServer::max_connections. -
HttpServer::maxconnrateis renamed to the more expressiveHttpServer::max_connection_rate.
-
HttpServer::start()renamed toHttpServer::run(). It also possible to.awaitonrunmethod 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()replacefnwithasync fnto convert sync handler to async -
actix_http_test::TestServermoved toactix_web::testmodule. To start test server usetest::start()ortest_start_with_config()methods -
ResponseErrortrait has been reafctored.ResponseError::error_response()renders http response. -
Feature
rust-tlsrenamed torustlsinstead of
actix-web = { version = "2.0.0", features = ["rust-tls"] }
use
actix-web = { version = "2.0.0", features = ["rustls"] }
-
Feature
sslrenamed toopensslinstead of
actix-web = { version = "2.0.0", features = ["ssl"] }
use
actix-web = { version = "2.0.0", features = ["openssl"] }
-
Corsbuilder now requires that you call.finish()to construct the middleware
-
Cors middleware has been moved to
actix-corscrateinstead of
use actix_web::middleware::cors::Cors;
use
use actix_cors::Cors;
-
Identity middleware has been moved to
actix-identitycrateinstead of
use actix_web::middleware::identity::{Identity, CookieIdentityPolicy, IdentityService};
use
use actix_identity::{Identity, CookieIdentityPolicy, IdentityService};
-
Extractor configuration. In version 1.0 this is handled with the new
Datamechanism 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
Datawithreq.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 implementsHttpServiceFactorytrait. By default actix-web providesResourceandScopeservices.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))
-
HttpRequestdoes 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
Payloadextractorfn index(stream: web::Payload) -> impl Future<Item=HttpResponse, Error=Error> { stream .from_err() .fold((), |_, chunk| { ... }) .map(|_| HttpResponse::Ok().finish()) }
-
Stateis 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
datamethodApp.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,Multipartextractors instead.instead of
fn index(req: &HttpRequest) -> Responder { req.body() .and_then(|body| { ... }) }
use
fn index(body: Bytes) -> Responder { ... }
-
actix_web::servermodule has been removed. To start http server useactix_web::HttpServertype -
StaticFiles and NamedFile have been moved to a separate crate.
instead of
use actix_web::fs::StaticFileuse
use actix_files::Filesinstead of
use actix_web::fs::Namedfileuse
use actix_files::NamedFile -
Multipart has been moved to a separate crate.
instead of
use actix_web::multipart::Multipartuse
use actix_multipart::Multipart -
Response compression is not enabled by default. To enable, use
Compressmiddleware,App::new().wrap(Compress::default()). -
Session middleware moved to actix-session crate
-
Actors support have been moved to
actix-web-actorscrate -
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() }
-
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::asyncyou need to replace it withAsyncResult::future
Route::with_config()/Route::with_async_config()always passes configuration objects as tuple even for handler with one parameter.
-
HttpRequestdoes not implementStreamanymore. 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
&HttpRequestinstead 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&selfinstead of&mut self -
Handler::handle()accepts reference toHttpRequest<_>instead of value -
Removed deprecated
HttpServer::threads(), use HttpServer::workers() instead. -
Renamed
client::ClientConnectorError::Connectortoclient::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()
-
Path<T>extractor returnErrorNotFoundon failure instead ofErrorBadRequest -
ws::Message::Closenow includes optional close reason.ws::CloseCode::Statusandws::CloseCode::Emptyhave 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::sessionuse actix_web::middleware::session{CookieSessionBackend, CookieSessionError, RequestSession, Session, SessionBackend, SessionImpl, SessionStorage}; -
FromRequest::from_request()accepts mutable reference to a request -
FromRequest::Resulthas to implementInto<Reply<Self>> -
Responder::respond_to()is generic overS -
Use
Queryextractor 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
WsWritertrait. you need to useuse actix_web::ws::WsWriter
-
HttpResponseBuilder::body(),.finish(),.json()methods returnHttpResponseinstead ofResult<HttpResponse> -
actix_web::Method,actix_web::StatusCode,actix_web::Versionmoved toactix_web::httpmodule -
actix_web::headermoved toactix_web::http::header -
NormalizePathmoved toactix_web::httpmodule -
HttpServermoved toactix_web::server, added newactix_web::server::new()function, shortcut foractix_web::server::HttpServer::new() -
DefaultHeadersmiddleware does not use separate builder, all builder methods moved to type itself -
StaticFiles::new()'s show_index parameter removed, useshow_files_listing()method instead. -
CookieSessionBackendBuilderremoved, all methods moved toCookieSessionBackendtype -
actix_web::httpcodesmodule is deprecated,HttpResponse::Ok(),HttpResponse::Found()and otherHttpResponse::XXX()functions should be used instead -
ClientRequestBuilder::body()returnsResult<_, actix_web::Error>instead ofResult<_, http::Error> -
Applicationrenamed to aApp -
actix_web::Reply,actix_web::Resourcemoved toactix_web::dev