mirror of
https://github.com/actix/actix-web.git
synced 2024-11-26 03:21:08 +00:00
parent
ed0516d724
commit
083ee05d50
6 changed files with 128 additions and 13 deletions
|
@ -4,7 +4,8 @@
|
|||
### Added
|
||||
* Add `ServiceRequest::parts_mut`. [#2177]
|
||||
* Add extractors for `Uri` and `Method`. [#2263]
|
||||
* Add extractor for `ConnectionInfo` and `PeerAddr`. [#2263]
|
||||
* Add extractors for `ConnectionInfo` and `PeerAddr`. [#2263]
|
||||
* Add `Route::service` for using hand-written services as handlers. [#2262]
|
||||
|
||||
### Changed
|
||||
* Change compression algorithm features flags. [#2250]
|
||||
|
@ -13,6 +14,7 @@
|
|||
[#2177]: https://github.com/actix/actix-web/pull/2177
|
||||
[#2250]: https://github.com/actix/actix-web/pull/2250
|
||||
[#2271]: https://github.com/actix/actix-web/pull/2271
|
||||
[#2262]: https://github.com/actix/actix-web/pull/2262
|
||||
[#2263]: https://github.com/actix/actix-web/pull/2263
|
||||
|
||||
|
||||
|
|
|
@ -113,7 +113,6 @@ flate2 = "1.0.13"
|
|||
zstd = "0.7"
|
||||
rand = "0.8"
|
||||
rcgen = "0.8"
|
||||
serde_derive = "1.0"
|
||||
tls-openssl = { package = "openssl", version = "0.10.9" }
|
||||
tls-rustls = { package = "rustls", version = "0.19.0" }
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ pub trait FromRequest: Sized {
|
|||
/// use actix_web::{web, dev, App, Error, HttpRequest, FromRequest};
|
||||
/// use actix_web::error::ErrorBadRequest;
|
||||
/// use futures_util::future::{ok, err, Ready};
|
||||
/// use serde_derive::Deserialize;
|
||||
/// use serde::Deserialize;
|
||||
/// use rand;
|
||||
///
|
||||
/// #[derive(Debug, Deserialize)]
|
||||
|
@ -145,7 +145,7 @@ where
|
|||
/// use actix_web::{web, dev, App, Result, Error, HttpRequest, FromRequest};
|
||||
/// use actix_web::error::ErrorBadRequest;
|
||||
/// use futures_util::future::{ok, err, Ready};
|
||||
/// use serde_derive::Deserialize;
|
||||
/// use serde::Deserialize;
|
||||
/// use rand;
|
||||
///
|
||||
/// #[derive(Debug, Deserialize)]
|
||||
|
@ -265,7 +265,7 @@ impl FromRequest for Method {
|
|||
#[doc(hidden)]
|
||||
impl FromRequest for () {
|
||||
type Error = Infallible;
|
||||
type Future = Ready<Result<(), Infallible>>;
|
||||
type Future = Ready<Result<Self, Self::Error>>;
|
||||
type Config = ();
|
||||
|
||||
fn from_request(_: &HttpRequest, _: &mut Payload) -> Self::Future {
|
||||
|
@ -376,7 +376,7 @@ mod m {
|
|||
mod tests {
|
||||
use actix_http::http::header;
|
||||
use bytes::Bytes;
|
||||
use serde_derive::Deserialize;
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::*;
|
||||
use crate::test::TestRequest;
|
||||
|
|
|
@ -149,7 +149,9 @@ pub mod dev {
|
|||
pub use actix_http::{Extensions, Payload, PayloadStream, RequestHead, ResponseHead};
|
||||
pub use actix_router::{Path, ResourceDef, ResourcePath, Url};
|
||||
pub use actix_server::Server;
|
||||
pub use actix_service::{always_ready, forward_ready, Service, Transform};
|
||||
pub use actix_service::{
|
||||
always_ready, fn_factory, fn_service, forward_ready, Service, Transform,
|
||||
};
|
||||
|
||||
pub(crate) fn insert_slash(mut patterns: Vec<String>) -> Vec<String> {
|
||||
for path in &mut patterns {
|
||||
|
|
|
@ -347,7 +347,7 @@ impl Drop for HttpRequest {
|
|||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::{web, App, HttpRequest};
|
||||
/// use serde_derive::Deserialize;
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
/// /// extract `Thing` from request
|
||||
/// async fn index(req: HttpRequest) -> String {
|
||||
|
|
122
src/route.rs
122
src/route.rs
|
@ -5,7 +5,7 @@ use std::{future::Future, rc::Rc};
|
|||
use actix_http::http::Method;
|
||||
use actix_service::{
|
||||
boxed::{self, BoxService, BoxServiceFactory},
|
||||
Service, ServiceFactory,
|
||||
Service, ServiceFactory, ServiceFactoryExt,
|
||||
};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
|
||||
|
@ -128,9 +128,10 @@ impl Route {
|
|||
|
||||
/// Set handler function, use request extractors for parameters.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::{web, http, App};
|
||||
/// use serde_derive::Deserialize;
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// struct Info {
|
||||
|
@ -154,7 +155,7 @@ impl Route {
|
|||
///
|
||||
/// ```
|
||||
/// # use std::collections::HashMap;
|
||||
/// # use serde_derive::Deserialize;
|
||||
/// # use serde::Deserialize;
|
||||
/// use actix_web::{web, App};
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
|
@ -184,6 +185,53 @@ impl Route {
|
|||
self.service = boxed::factory(HandlerService::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set raw service to be constructed and called as the request handler.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use std::convert::Infallible;
|
||||
/// # use futures_util::future::LocalBoxFuture;
|
||||
/// # use actix_web::{*, dev::*, http::header};
|
||||
/// struct HelloWorld;
|
||||
///
|
||||
/// impl Service<ServiceRequest> for HelloWorld {
|
||||
/// type Response = ServiceResponse;
|
||||
/// type Error = Infallible;
|
||||
/// type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
///
|
||||
/// always_ready!();
|
||||
///
|
||||
/// fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||
/// let (req, _) = req.into_parts();
|
||||
///
|
||||
/// let res = HttpResponse::Ok()
|
||||
/// .insert_header(header::ContentType::plaintext())
|
||||
/// .body("Hello world!");
|
||||
///
|
||||
/// Box::pin(async move { Ok(ServiceResponse::new(req, res)) })
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// App::new().route(
|
||||
/// "/",
|
||||
/// web::get().service(fn_factory(|| async { Ok(HelloWorld) })),
|
||||
/// );
|
||||
/// ```
|
||||
pub fn service<S, E>(mut self, service_factory: S) -> Self
|
||||
where
|
||||
S: ServiceFactory<
|
||||
ServiceRequest,
|
||||
Response = ServiceResponse,
|
||||
Error = E,
|
||||
InitError = (),
|
||||
Config = (),
|
||||
> + 'static,
|
||||
E: Into<Error> + 'static,
|
||||
{
|
||||
self.service = boxed::factory(service_factory.map_err(Into::into));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -192,9 +240,12 @@ mod tests {
|
|||
|
||||
use actix_rt::time::sleep;
|
||||
use bytes::Bytes;
|
||||
use serde_derive::Serialize;
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::http::{Method, StatusCode};
|
||||
use crate::dev::{always_ready, fn_factory, fn_service, Service};
|
||||
use crate::http::{header, Method, StatusCode};
|
||||
use crate::service::{ServiceRequest, ServiceResponse};
|
||||
use crate::test::{call_service, init_service, read_body, TestRequest};
|
||||
use crate::{error, web, App, HttpResponse};
|
||||
|
||||
|
@ -268,4 +319,65 @@ mod tests {
|
|||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"{\"name\":\"test\"}"));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service_handler() {
|
||||
struct HelloWorld;
|
||||
|
||||
impl Service<ServiceRequest> for HelloWorld {
|
||||
type Response = ServiceResponse;
|
||||
type Error = crate::Error;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
always_ready!();
|
||||
|
||||
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||
let (req, _) = req.into_parts();
|
||||
|
||||
let res = HttpResponse::Ok()
|
||||
.insert_header(header::ContentType::plaintext())
|
||||
.body("Hello world!");
|
||||
|
||||
Box::pin(async move { Ok(ServiceResponse::new(req, res)) })
|
||||
}
|
||||
}
|
||||
|
||||
let srv = init_service(
|
||||
App::new()
|
||||
.route(
|
||||
"/hello",
|
||||
web::get().service(fn_factory(|| async { Ok(HelloWorld) })),
|
||||
)
|
||||
.route(
|
||||
"/bye",
|
||||
web::get().service(fn_factory(|| async {
|
||||
Ok::<_, ()>(fn_service(|req: ServiceRequest| async {
|
||||
let (req, _) = req.into_parts();
|
||||
|
||||
let res = HttpResponse::Ok()
|
||||
.insert_header(header::ContentType::plaintext())
|
||||
.body("Goodbye, and thanks for all the fish!");
|
||||
|
||||
Ok::<_, Infallible>(ServiceResponse::new(req, res))
|
||||
}))
|
||||
})),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::get().uri("/hello").to_request();
|
||||
let resp = call_service(&srv, req).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"Hello world!"));
|
||||
|
||||
let req = TestRequest::get().uri("/bye").to_request();
|
||||
let resp = call_service(&srv, req).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(
|
||||
body,
|
||||
Bytes::from_static(b"Goodbye, and thanks for all the fish!")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue