mirror of https://github.com/fafhrd91/actix-web
fix tests and add docs
This commit is contained in:
parent
b1dfec2e87
commit
afc9aa4c92
|
@ -333,7 +333,7 @@ impl HeaderMap {
|
|||
}
|
||||
}
|
||||
|
||||
/// Inserts a name-value pair into the map.
|
||||
/// Inserts (overrides) a name-value pair in the map.
|
||||
///
|
||||
/// If the map already contained this key, the new value is associated with the key and all
|
||||
/// previous values are removed and returned as a `Removed` iterator. The key is not updated;
|
||||
|
@ -372,7 +372,7 @@ impl HeaderMap {
|
|||
Removed::new(value)
|
||||
}
|
||||
|
||||
/// Inserts a name-value pair into the map.
|
||||
/// Appends a name-value pair to the map.
|
||||
///
|
||||
/// If the map already contained this key, the new value is added to the list of values
|
||||
/// currently associated with the key. The key is not updated; this matters for types that can
|
||||
|
|
|
@ -22,14 +22,14 @@ async fn main() -> std::io::Result<()> {
|
|||
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.wrap(middleware::DefaultHeaders::new().insert(("X-Version", "0.2")))
|
||||
.wrap(middleware::DefaultHeaders::new().add(("X-Version", "0.2")))
|
||||
.wrap(middleware::Compress::default())
|
||||
.wrap(middleware::Logger::default())
|
||||
.service(index)
|
||||
.service(no_params)
|
||||
.service(
|
||||
web::resource("/resource2/index.html")
|
||||
.wrap(middleware::DefaultHeaders::new().insert(("X-Version-R2", "0.3")))
|
||||
.wrap(middleware::DefaultHeaders::new().add(("X-Version-R2", "0.3")))
|
||||
.default_service(web::route().to(HttpResponse::MethodNotAllowed))
|
||||
.route(web::get().to(index_async)),
|
||||
)
|
||||
|
|
|
@ -26,14 +26,14 @@ async fn main() -> std::io::Result<()> {
|
|||
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.wrap(middleware::DefaultHeaders::new().insert(("X-Version", "0.2")))
|
||||
.wrap(middleware::DefaultHeaders::new().add(("X-Version", "0.2")))
|
||||
.wrap(middleware::Compress::default())
|
||||
.wrap(middleware::Logger::default())
|
||||
.service(index)
|
||||
.service(no_params)
|
||||
.service(
|
||||
web::resource("/resource2/index.html")
|
||||
.wrap(middleware::DefaultHeaders::new().insert(("X-Version-R2", "0.3")))
|
||||
.wrap(middleware::DefaultHeaders::new().add(("X-Version-R2", "0.3")))
|
||||
.default_service(web::route().to(HttpResponse::MethodNotAllowed))
|
||||
.route(web::get().to(index_async)),
|
||||
)
|
||||
|
|
|
@ -602,7 +602,7 @@ mod tests {
|
|||
App::new()
|
||||
.wrap(
|
||||
DefaultHeaders::new()
|
||||
.insert((header::CONTENT_TYPE, HeaderValue::from_static("0001"))),
|
||||
.add((header::CONTENT_TYPE, HeaderValue::from_static("0001"))),
|
||||
)
|
||||
.route("/test", web::get().to(HttpResponse::Ok)),
|
||||
)
|
||||
|
@ -623,7 +623,7 @@ mod tests {
|
|||
.route("/test", web::get().to(HttpResponse::Ok))
|
||||
.wrap(
|
||||
DefaultHeaders::new()
|
||||
.insert((header::CONTENT_TYPE, HeaderValue::from_static("0001"))),
|
||||
.add((header::CONTENT_TYPE, HeaderValue::from_static("0001"))),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
|
|
@ -30,7 +30,7 @@ use crate::{
|
|||
/// use actix_web::{web, http, middleware, App, HttpResponse};
|
||||
///
|
||||
/// let app = App::new()
|
||||
/// .wrap(middleware::DefaultHeaders::new().insert("X-Version", "0.2"))
|
||||
/// .wrap(middleware::DefaultHeaders::new().add(("X-Version", "0.2")))
|
||||
/// .service(
|
||||
/// web::resource("/test")
|
||||
/// .route(web::get().to(|| HttpResponse::Ok()))
|
||||
|
@ -58,12 +58,14 @@ impl DefaultHeaders {
|
|||
///
|
||||
/// # Panics
|
||||
/// Panics when resolved header name or value is invalid.
|
||||
pub fn insert(mut self, header: impl TryIntoHeaderPair) -> Self {
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn add(mut self, header: impl TryIntoHeaderPair) -> Self {
|
||||
// standard header terminology `insert` or `append` for this method would make the behavior
|
||||
// of this middleware less obvious since it only adds the headers if they are not present
|
||||
|
||||
match header.try_into_header_pair() {
|
||||
Ok((key, value)) => Rc::get_mut(&mut self.inner)
|
||||
.expect(
|
||||
"DefaultHeaders has been cloned. Add all default headers before cloning.",
|
||||
)
|
||||
.expect("All default headers must be added before cloning.")
|
||||
.headers
|
||||
.append(key, value),
|
||||
Err(err) => panic!("Invalid header: {}", err.into()),
|
||||
|
@ -73,7 +75,7 @@ impl DefaultHeaders {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[deprecated(since = "4.0.0", note = "Prefer `insert`.")]
|
||||
#[deprecated(since = "4.0.0", note = "Prefer `add`.")]
|
||||
pub fn header<K, V>(self, key: K, value: V) -> Self
|
||||
where
|
||||
HeaderName: TryFrom<K>,
|
||||
|
@ -81,7 +83,7 @@ impl DefaultHeaders {
|
|||
HeaderValue: TryFrom<V>,
|
||||
<HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.insert((
|
||||
self.add((
|
||||
HeaderName::try_from(key)
|
||||
.map_err(Into::into)
|
||||
.expect("Invalid header name"),
|
||||
|
@ -94,18 +96,12 @@ impl DefaultHeaders {
|
|||
/// Adds a default *Content-Type* header if response does not contain one.
|
||||
///
|
||||
/// Default is `application/octet-stream`.
|
||||
pub fn insert_content_type(self) -> Self {
|
||||
self.insert((
|
||||
pub fn add_content_type(self) -> Self {
|
||||
self.add((
|
||||
CONTENT_TYPE,
|
||||
HeaderValue::from_static("application/octet-stream"),
|
||||
))
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[deprecated(since = "4.0.0", note = "Renamed to `insert_content_type`.")]
|
||||
pub fn add_content_type(self) -> Self {
|
||||
self.insert_content_type()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B> Transform<S, ServiceRequest> for DefaultHeaders
|
||||
|
@ -202,8 +198,8 @@ mod tests {
|
|||
#[actix_rt::test]
|
||||
async fn adding_default_headers() {
|
||||
let mw = DefaultHeaders::new()
|
||||
.insert(("X-TEST", "0001"))
|
||||
.insert(("X-TEST-TWO", HeaderValue::from_static("123")))
|
||||
.add(("X-TEST", "0001"))
|
||||
.add(("X-TEST-TWO", HeaderValue::from_static("123")))
|
||||
.new_transform(ok_service())
|
||||
.await
|
||||
.unwrap();
|
||||
|
@ -225,7 +221,7 @@ mod tests {
|
|||
))
|
||||
};
|
||||
let mw = DefaultHeaders::new()
|
||||
.insert((CONTENT_TYPE, "0001"))
|
||||
.add((CONTENT_TYPE, "0001"))
|
||||
.new_transform(srv.into_service())
|
||||
.await
|
||||
.unwrap();
|
||||
|
@ -237,7 +233,7 @@ mod tests {
|
|||
async fn adding_content_type() {
|
||||
let srv = |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish()));
|
||||
let mw = DefaultHeaders::new()
|
||||
.insert_content_type()
|
||||
.add_content_type()
|
||||
.new_transform(srv.into_service())
|
||||
.await
|
||||
.unwrap();
|
||||
|
@ -253,12 +249,12 @@ mod tests {
|
|||
#[test]
|
||||
#[should_panic]
|
||||
fn invalid_header_name() {
|
||||
DefaultHeaders::new().insert((":", "hello"));
|
||||
DefaultHeaders::new().add((":", "hello"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn invalid_header_value() {
|
||||
DefaultHeaders::new().insert(("x-test", "\n"));
|
||||
DefaultHeaders::new().add(("x-test", "\n"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ mod tests {
|
|||
let _ = App::new()
|
||||
.wrap(Compat::new(Logger::default()))
|
||||
.wrap(Condition::new(true, DefaultHeaders::new()))
|
||||
.wrap(DefaultHeaders::new().insert(("X-Test2", "X-Value2")))
|
||||
.wrap(DefaultHeaders::new().add(("X-Test2", "X-Value2")))
|
||||
.wrap(ErrorHandlers::new().handler(StatusCode::FORBIDDEN, |res| {
|
||||
Ok(ErrorHandlerResponse::Response(res))
|
||||
}))
|
||||
|
@ -46,7 +46,7 @@ mod tests {
|
|||
.wrap(ErrorHandlers::new().handler(StatusCode::FORBIDDEN, |res| {
|
||||
Ok(ErrorHandlerResponse::Response(res))
|
||||
}))
|
||||
.wrap(DefaultHeaders::new().insert(("X-Test2", "X-Value2")))
|
||||
.wrap(DefaultHeaders::new().add(("X-Test2", "X-Value2")))
|
||||
.wrap(Condition::new(true, DefaultHeaders::new()))
|
||||
.wrap(Compat::new(Logger::default()));
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ use crate::{dev::Payload, error::ErrorInternalServerError, Error, FromRequest, H
|
|||
/// # Mutating Request Data
|
||||
/// Note that since extractors must output owned data, only types that `impl Clone` can use this
|
||||
/// extractor. A clone is taken of the required request data and can, therefore, not be directly
|
||||
/// mutated in-place. To mutate request data, continue to use [`HttpRequest::extensions_mut`] or
|
||||
/// mutated in-place. To mutate request data, continue to use [`HttpRequest::req_data_mut`] or
|
||||
/// re-insert the cloned data back into the extensions map. A `DerefMut` impl is intentionally not
|
||||
/// provided to make this potential foot-gun more obvious.
|
||||
///
|
||||
|
|
|
@ -525,7 +525,7 @@ mod tests {
|
|||
.name("test")
|
||||
.wrap(
|
||||
DefaultHeaders::new()
|
||||
.insert((header::CONTENT_TYPE, HeaderValue::from_static("0001"))),
|
||||
.add((header::CONTENT_TYPE, HeaderValue::from_static("0001"))),
|
||||
)
|
||||
.route(web::get().to(HttpResponse::Ok)),
|
||||
),
|
||||
|
|
|
@ -8,7 +8,9 @@ use actix_http::{
|
|||
|
||||
use crate::{BoxError, HttpRequest, HttpResponse, Responder};
|
||||
|
||||
/// Allows overriding status code and headers for a responder.
|
||||
/// Allows overriding status code and headers for a [`Responder`].
|
||||
///
|
||||
/// Created by the [`Responder::customize`] method.
|
||||
pub struct CustomizeResponder<R> {
|
||||
inner: CustomizeResponderInner<R>,
|
||||
error: Option<HttpError>,
|
||||
|
@ -36,12 +38,15 @@ impl<R: Responder> CustomizeResponder<R> {
|
|||
|
||||
/// Override a status code for the Responder's response.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::{HttpRequest, Responder, http::StatusCode};
|
||||
/// use actix_web::{Responder, http::StatusCode, test::TestRequest};
|
||||
///
|
||||
/// fn index(req: HttpRequest) -> impl Responder {
|
||||
/// "Welcome!".with_status(StatusCode::OK)
|
||||
/// }
|
||||
/// let responder = "Welcome!".customize().with_status(StatusCode::ACCEPTED);
|
||||
///
|
||||
/// let request = TestRequest::default().to_http_request();
|
||||
/// let response = responder.respond_to(&request);
|
||||
/// assert_eq!(response.status(), StatusCode::ACCEPTED);
|
||||
/// ```
|
||||
pub fn with_status(mut self, status: StatusCode) -> Self {
|
||||
if let Some(inner) = self.inner() {
|
||||
|
@ -51,24 +56,26 @@ impl<R: Responder> CustomizeResponder<R> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Insert header to the final response.
|
||||
/// Insert (override) header in the final response.
|
||||
///
|
||||
/// Overrides other headers with the same name.
|
||||
/// See [`HeaderMap::insert`](crate::http::header::HeaderMap::insert).
|
||||
///
|
||||
/// Headers added with this method will be inserted before those added
|
||||
/// with [`append_header`](Self::append_header). As such, header(s) can be overridden with more
|
||||
/// than one new header by first calling `insert_header` followed by `append_header`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::{web, HttpRequest, Responder};
|
||||
/// use serde::Serialize;
|
||||
/// use actix_web::{Responder, test::TestRequest};
|
||||
///
|
||||
/// #[derive(Serialize)]
|
||||
/// struct MyObj {
|
||||
/// name: String,
|
||||
/// }
|
||||
/// let responder = "Hello world!"
|
||||
/// .customize()
|
||||
/// .insert_header(("x-version", "1.2.3"));
|
||||
///
|
||||
/// fn index(req: HttpRequest) -> impl Responder {
|
||||
/// web::Json(MyObj { name: "Name".to_string() })
|
||||
/// .with_header(("x-version", "1.2.3"))
|
||||
/// .with_header(("x-version", "1.2.3"))
|
||||
/// }
|
||||
/// let request = TestRequest::default().to_http_request();
|
||||
/// let response = responder.respond_to(&request);
|
||||
/// assert_eq!(response.headers().get("x-version").unwrap(), "1.2.3");
|
||||
/// ```
|
||||
pub fn insert_header(mut self, header: impl TryIntoHeaderPair) -> Self {
|
||||
if let Some(inner) = self.inner() {
|
||||
|
@ -83,6 +90,25 @@ impl<R: Responder> CustomizeResponder<R> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Append header to the final response.
|
||||
///
|
||||
/// Unlike [`insert_header`](Self::insert_header), this will not override existing headers.
|
||||
/// See [`HeaderMap::append`](crate::http::header::HeaderMap::append).
|
||||
///
|
||||
/// Headers added here are appended _after_ additions/overrides from `insert_header`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::{Responder, test::TestRequest};
|
||||
///
|
||||
/// let responder = "Hello world!"
|
||||
/// .customize()
|
||||
/// .append_header(("x-version", "1.2.3"));
|
||||
///
|
||||
/// let request = TestRequest::default().to_http_request();
|
||||
/// let response = responder.respond_to(&request);
|
||||
/// assert_eq!(response.headers().get("x-version").unwrap(), "1.2.3");
|
||||
/// ```
|
||||
pub fn append_header(mut self, header: impl TryIntoHeaderPair) -> Self {
|
||||
if let Some(inner) = self.inner() {
|
||||
match header.try_into_header_pair() {
|
||||
|
|
|
@ -21,24 +21,23 @@ pub trait Responder {
|
|||
/// Convert self to `HttpResponse`.
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<Self::Body>;
|
||||
|
||||
/// Wraps responder in [`CustomizeResponder`] that allows modification of response details.
|
||||
/// Wraps responder to allow alteration of its response.
|
||||
///
|
||||
/// See [`CustomizeResponder`] docs for more.
|
||||
/// See [`CustomizeResponder`] docs for its capabilities.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::{Responder, test};
|
||||
///
|
||||
/// let request = test::TestRequest::default().to_http_request();
|
||||
/// use actix_web::{Responder, http::StatusCode, test::TestRequest};
|
||||
///
|
||||
/// let responder = "Hello world!"
|
||||
/// .customize()
|
||||
/// .with_status(400)
|
||||
/// .insert_header(("x-hello", "world"))
|
||||
/// .with_status(StatusCode::BAD_REQUEST)
|
||||
/// .insert_header(("x-hello", "world"));
|
||||
///
|
||||
/// let response = res.respond_to(&req);
|
||||
/// assert_eq!(res.status(), 400);
|
||||
/// assert_eq!(res.headers().get("x-hello").unwrap(), "world");
|
||||
/// let request = TestRequest::default().to_http_request();
|
||||
/// let response = responder.respond_to(&request);
|
||||
/// assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
/// assert_eq!(response.headers().get("x-hello").unwrap(), "world");
|
||||
/// ```
|
||||
#[inline]
|
||||
fn customize(self) -> CustomizeResponder<Self>
|
||||
|
|
|
@ -935,7 +935,7 @@ mod tests {
|
|||
web::scope("app")
|
||||
.wrap(
|
||||
DefaultHeaders::new()
|
||||
.insert((header::CONTENT_TYPE, HeaderValue::from_static("0001"))),
|
||||
.add((header::CONTENT_TYPE, HeaderValue::from_static("0001"))),
|
||||
)
|
||||
.service(web::resource("/test").route(web::get().to(HttpResponse::Ok))),
|
||||
),
|
||||
|
|
Loading…
Reference in New Issue