mirror of
https://github.com/fafhrd91/actix-web
synced 2025-07-10 04:46:00 +02:00
Compare commits
7 Commits
multipart-
...
web-v3.0.2
Author | SHA1 | Date | |
---|---|---|---|
d707704556 | |||
a429ee6646 | |||
7f8073233a | |||
4b4c9d1b93 | |||
3fde3be3d8 | |||
f861508789 | |||
a4546f02d2 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -13,3 +13,6 @@ guide/build/
|
|||||||
|
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Configuration directory generated by CLion
|
||||||
|
.idea
|
||||||
|
14
CHANGES.md
14
CHANGES.md
@ -3,6 +3,20 @@
|
|||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 3.0.2 - 2020-09-15
|
||||||
|
### Fixed
|
||||||
|
* `NormalizePath` when used with `TrailingSlash::Trim` no longer trims the root path "/". [#1678]
|
||||||
|
|
||||||
|
[#1678]: https://github.com/actix/actix-web/pull/1678
|
||||||
|
|
||||||
|
|
||||||
|
## 3.0.1 - 2020-09-13
|
||||||
|
### Changed
|
||||||
|
* `middleware::normalize::TrailingSlash` enum is now accessible. [#1673]
|
||||||
|
|
||||||
|
[#1673]: https://github.com/actix/actix-web/pull/1673
|
||||||
|
|
||||||
|
|
||||||
## 3.0.0 - 2020-09-11
|
## 3.0.0 - 2020-09-11
|
||||||
* No significant changes from `3.0.0-beta.4`.
|
* No significant changes from `3.0.0-beta.4`.
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-web"
|
name = "actix-web"
|
||||||
version = "3.0.0"
|
version = "3.0.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust."
|
description = "Actix web is a powerful, pragmatic, and extremely fast web framework for Rust."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["actix", "http", "web", "framework", "async"]
|
keywords = ["actix", "http", "web", "framework", "async"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
|
11
MIGRATION.md
11
MIGRATION.md
@ -3,12 +3,23 @@
|
|||||||
|
|
||||||
## 3.0.0
|
## 3.0.0
|
||||||
|
|
||||||
|
* The return type for `ServiceRequest::app_data::<T>()` was changed from returning a `Data<T>` to
|
||||||
|
simply a `T`. To access a `Data<T>` use `ServiceRequest::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
|
||||||
|
any `actix-web` method previously expecting a time v0.1 input.
|
||||||
|
|
||||||
* Setting a cookie's SameSite property, explicitly, to `SameSite::None` will now
|
* Setting a cookie's SameSite property, explicitly, to `SameSite::None` will now
|
||||||
result in `SameSite=None` being sent with the response Set-Cookie header.
|
result in `SameSite=None` being sent with the response Set-Cookie header.
|
||||||
To create a cookie without a SameSite attribute, remove any calls setting same_site.
|
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
|
* actix-http support for Actors messages was moved to actix-http crate and is enabled
|
||||||
with feature `actors`
|
with feature `actors`
|
||||||
|
|
||||||
* content_length function is removed from actix-http.
|
* content_length function is removed from actix-http.
|
||||||
You can set Content-Length by normally setting the response body or calling no_chunking function.
|
You can set Content-Length by normally setting the response body or calling no_chunking function.
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
* Added compile success and failure testing. [#1677]
|
||||||
|
|
||||||
|
[#1677]: https://github.com/actix/actix-web/pull/1677
|
||||||
|
|
||||||
|
|
||||||
## 0.3.0 - 2020-09-11
|
## 0.3.0 - 2020-09-11
|
||||||
|
@ -22,3 +22,4 @@ proc-macro2 = "1"
|
|||||||
actix-rt = "1.0.0"
|
actix-rt = "1.0.0"
|
||||||
actix-web = "3.0.0"
|
actix-web = "3.0.0"
|
||||||
futures-util = { version = "0.3.5", default-features = false }
|
futures-util = { version = "0.3.5", default-features = false }
|
||||||
|
trybuild = "1"
|
||||||
|
@ -1,8 +1,22 @@
|
|||||||
# Helper and convenience macros for Actix-web. [](https://travis-ci.org/actix/actix-web) [](https://codecov.io/gh/actix/actix-web) [](https://crates.io/crates/actix-web-codegen) [](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
# actix-web-codegen
|
||||||
|
|
||||||
|
> Helper and convenience macros for Actix Web
|
||||||
|
|
||||||
|
[](https://crates.io/crates/actix-web-codegen)
|
||||||
|
[](https://docs.rs/actix-web)
|
||||||
|
[](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)
|
||||||
|
[](https://travis-ci.org/actix/actix-web)
|
||||||
|
[](https://codecov.io/gh/actix/actix-web)
|
||||||
|
[](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
## Documentation & Resources
|
## Documentation & Resources
|
||||||
|
|
||||||
* [API Documentation](https://docs.rs/actix-web-codegen/)
|
- [API Documentation](https://docs.rs/actix-web-codegen)
|
||||||
* [Chat on gitter](https://gitter.im/actix/actix)
|
- [Chat on Gitter](https://gitter.im/actix/actix-web)
|
||||||
* Cargo package: [actix-web-codegen](https://crates.io/crates/actix-web-codegen)
|
- Cargo package: [actix-web-codegen](https://crates.io/crates/actix-web-codegen)
|
||||||
* Minimum supported Rust version: 1.40 or later
|
- Minimum supported Rust version: 1.42 or later.
|
||||||
|
|
||||||
|
## Compile Testing
|
||||||
|
Uses the [`trybuild`] crate. All compile fail tests should include a stderr file generated by `trybuild`. See the [workflow section](https://github.com/dtolnay/trybuild#workflow) of the trybuild docs for info on how to do this.
|
||||||
|
|
||||||
|
[`trybuild`]: https://github.com/dtolnay/trybuild
|
||||||
|
@ -49,13 +49,13 @@ use proc_macro::TokenStream;
|
|||||||
|
|
||||||
/// Creates route handler with `GET` method guard.
|
/// Creates route handler with `GET` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[get("path"[, attributes])]`
|
/// Syntax: `#[get("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// ## Attributes:
|
/// ## Attributes:
|
||||||
///
|
///
|
||||||
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
|
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
|
||||||
/// - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
|
/// - `guard = "function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
|
||||||
/// - `wrap="Middleware"` - Registers a resource middleware.
|
/// - `wrap = "Middleware"` - Registers a resource middleware.
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn get(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn get(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::generate(args, input, route::GuardType::Get)
|
route::generate(args, input, route::GuardType::Get)
|
||||||
@ -63,7 +63,7 @@ pub fn get(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
/// Creates route handler with `POST` method guard.
|
/// Creates route handler with `POST` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[post("path"[, attributes])]`
|
/// Syntax: `#[post("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// Attributes are the same as in [get](attr.get.html)
|
/// Attributes are the same as in [get](attr.get.html)
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
@ -73,7 +73,7 @@ pub fn post(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
/// Creates route handler with `PUT` method guard.
|
/// Creates route handler with `PUT` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[put("path"[, attributes])]`
|
/// Syntax: `#[put("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// Attributes are the same as in [get](attr.get.html)
|
/// Attributes are the same as in [get](attr.get.html)
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
@ -83,9 +83,9 @@ pub fn put(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
/// Creates route handler with `DELETE` method guard.
|
/// Creates route handler with `DELETE` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[delete("path"[, attributes])]`
|
/// Syntax: `#[delete("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// Attributes are the same as in [get](attr.get.html)
|
/// Attributes are the same as in [get](attr.get.html).
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn delete(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn delete(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::generate(args, input, route::GuardType::Delete)
|
route::generate(args, input, route::GuardType::Delete)
|
||||||
@ -93,9 +93,9 @@ pub fn delete(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
/// Creates route handler with `HEAD` method guard.
|
/// Creates route handler with `HEAD` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[head("path"[, attributes])]`
|
/// Syntax: `#[head("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// Attributes are the same as in [head](attr.head.html)
|
/// Attributes are the same as in [get](attr.get.html).
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn head(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn head(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::generate(args, input, route::GuardType::Head)
|
route::generate(args, input, route::GuardType::Head)
|
||||||
@ -103,9 +103,9 @@ pub fn head(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
/// Creates route handler with `CONNECT` method guard.
|
/// Creates route handler with `CONNECT` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[connect("path"[, attributes])]`
|
/// Syntax: `#[connect("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// Attributes are the same as in [connect](attr.connect.html)
|
/// Attributes are the same as in [get](attr.get.html).
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn connect(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn connect(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::generate(args, input, route::GuardType::Connect)
|
route::generate(args, input, route::GuardType::Connect)
|
||||||
@ -113,9 +113,9 @@ pub fn connect(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
/// Creates route handler with `OPTIONS` method guard.
|
/// Creates route handler with `OPTIONS` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[options("path"[, attributes])]`
|
/// Syntax: `#[options("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// Attributes are the same as in [options](attr.options.html)
|
/// Attributes are the same as in [get](attr.get.html).
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn options(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn options(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::generate(args, input, route::GuardType::Options)
|
route::generate(args, input, route::GuardType::Options)
|
||||||
@ -123,9 +123,9 @@ pub fn options(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
/// Creates route handler with `TRACE` method guard.
|
/// Creates route handler with `TRACE` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[trace("path"[, attributes])]`
|
/// Syntax: `#[trace("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// Attributes are the same as in [trace](attr.trace.html)
|
/// Attributes are the same as in [get](attr.get.html).
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn trace(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn trace(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::generate(args, input, route::GuardType::Trace)
|
route::generate(args, input, route::GuardType::Trace)
|
||||||
@ -133,9 +133,9 @@ pub fn trace(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
/// Creates route handler with `PATCH` method guard.
|
/// Creates route handler with `PATCH` method guard.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[patch("path"[, attributes])]`
|
/// Syntax: `#[patch("path" [, attributes])]`
|
||||||
///
|
///
|
||||||
/// Attributes are the same as in [patch](attr.patch.html)
|
/// Attributes are the same as in [get](attr.get.html).
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn patch(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn patch(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::generate(args, input, route::GuardType::Patch)
|
route::generate(args, input, route::GuardType::Patch)
|
||||||
|
7
actix-web-codegen/tests/trybuild.rs
Normal file
7
actix-web-codegen/tests/trybuild.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#[test]
|
||||||
|
fn compile_macros() {
|
||||||
|
let t = trybuild::TestCases::new();
|
||||||
|
|
||||||
|
t.pass("tests/trybuild/simple.rs");
|
||||||
|
t.compile_fail("tests/trybuild/simple-fail.rs");
|
||||||
|
}
|
25
actix-web-codegen/tests/trybuild/simple-fail.rs
Normal file
25
actix-web-codegen/tests/trybuild/simple-fail.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use actix_web::*;
|
||||||
|
|
||||||
|
#[get("/one", other)]
|
||||||
|
async fn one() -> impl Responder {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post(/two)]
|
||||||
|
async fn two() -> impl Responder {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
static PATCH_PATH: &str = "/three";
|
||||||
|
|
||||||
|
#[patch(PATCH_PATH)]
|
||||||
|
async fn three() -> impl Responder {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[delete("/four", "/five")]
|
||||||
|
async fn four() -> impl Responder {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
23
actix-web-codegen/tests/trybuild/simple-fail.stderr
Normal file
23
actix-web-codegen/tests/trybuild/simple-fail.stderr
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
error: Unknown attribute.
|
||||||
|
--> $DIR/simple-fail.rs:3:15
|
||||||
|
|
|
||||||
|
3 | #[get("/one", other)]
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: expected identifier or literal
|
||||||
|
--> $DIR/simple-fail.rs:8:8
|
||||||
|
|
|
||||||
|
8 | #[post(/two)]
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: Unknown attribute.
|
||||||
|
--> $DIR/simple-fail.rs:15:9
|
||||||
|
|
|
||||||
|
15 | #[patch(PATCH_PATH)]
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: Multiple paths specified! Should be only one!
|
||||||
|
--> $DIR/simple-fail.rs:20:19
|
||||||
|
|
|
||||||
|
20 | #[delete("/four", "/five")]
|
||||||
|
| ^^^^^^^
|
15
actix-web-codegen/tests/trybuild/simple.rs
Normal file
15
actix-web-codegen/tests/trybuild/simple.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use actix_web::*;
|
||||||
|
|
||||||
|
#[get("/config")]
|
||||||
|
async fn config() -> impl Responder {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() {
|
||||||
|
let srv = test::start(|| App::new().service(config));
|
||||||
|
|
||||||
|
let request = srv.get("/config");
|
||||||
|
let response = request.send().await.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
}
|
@ -1,6 +1,3 @@
|
|||||||
#![deny(rust_2018_idioms)]
|
|
||||||
#![allow(clippy::needless_doctest_main, clippy::type_complexity)]
|
|
||||||
|
|
||||||
//! Actix web is a powerful, pragmatic, and extremely fast web framework for Rust.
|
//! Actix web is a powerful, pragmatic, and extremely fast web framework for Rust.
|
||||||
//!
|
//!
|
||||||
//! ## Example
|
//! ## Example
|
||||||
@ -68,6 +65,11 @@
|
|||||||
//! * `rustls` - HTTPS support via `rustls` crate, supports `HTTP/2`
|
//! * `rustls` - HTTPS support via `rustls` crate, supports `HTTP/2`
|
||||||
//! * `secure-cookies` - secure cookies support
|
//! * `secure-cookies` - secure cookies support
|
||||||
|
|
||||||
|
#![deny(rust_2018_idioms)]
|
||||||
|
#![allow(clippy::needless_doctest_main, clippy::type_complexity)]
|
||||||
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod app_service;
|
mod app_service;
|
||||||
mod config;
|
mod config;
|
||||||
|
@ -9,7 +9,7 @@ mod condition;
|
|||||||
mod defaultheaders;
|
mod defaultheaders;
|
||||||
pub mod errhandlers;
|
pub mod errhandlers;
|
||||||
mod logger;
|
mod logger;
|
||||||
mod normalize;
|
pub mod normalize;
|
||||||
|
|
||||||
pub use self::condition::Condition;
|
pub use self::condition::Condition;
|
||||||
pub use self::defaultheaders::DefaultHeaders;
|
pub use self::defaultheaders::DefaultHeaders;
|
||||||
|
@ -79,6 +79,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
pub struct NormalizePathNormalization<S> {
|
pub struct NormalizePathNormalization<S> {
|
||||||
service: S,
|
service: S,
|
||||||
merge_slash: Regex,
|
merge_slash: Regex,
|
||||||
@ -113,6 +114,10 @@ where
|
|||||||
// normalize multiple /'s to one /
|
// normalize multiple /'s to one /
|
||||||
let path = self.merge_slash.replace_all(&path, "/");
|
let path = self.merge_slash.replace_all(&path, "/");
|
||||||
|
|
||||||
|
// Ensure root paths are still resolvable. If resulting path is blank after previous step
|
||||||
|
// it means the path was one or more slashes. Reduce to single slash.
|
||||||
|
let path = if path.is_empty() { "/" } else { path.as_ref() };
|
||||||
|
|
||||||
// Check whether the path has been changed
|
// Check whether the path has been changed
|
||||||
//
|
//
|
||||||
// This check was previously implemented as string length comparison
|
// This check was previously implemented as string length comparison
|
||||||
@ -158,10 +163,23 @@ mod tests {
|
|||||||
let mut app = init_service(
|
let mut app = init_service(
|
||||||
App::new()
|
App::new()
|
||||||
.wrap(NormalizePath::default())
|
.wrap(NormalizePath::default())
|
||||||
|
.service(web::resource("/").to(HttpResponse::Ok))
|
||||||
.service(web::resource("/v1/something/").to(HttpResponse::Ok)),
|
.service(web::resource("/v1/something/").to(HttpResponse::Ok)),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/").to_request();
|
||||||
|
let res = call_service(&mut app, req).await;
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/?query=test").to_request();
|
||||||
|
let res = call_service(&mut app, req).await;
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("///").to_request();
|
||||||
|
let res = call_service(&mut app, req).await;
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
|
||||||
let req = TestRequest::with_uri("/v1//something////").to_request();
|
let req = TestRequest::with_uri("/v1//something////").to_request();
|
||||||
let res = call_service(&mut app, req).await;
|
let res = call_service(&mut app, req).await;
|
||||||
assert!(res.status().is_success());
|
assert!(res.status().is_success());
|
||||||
@ -184,10 +202,24 @@ mod tests {
|
|||||||
let mut app = init_service(
|
let mut app = init_service(
|
||||||
App::new()
|
App::new()
|
||||||
.wrap(NormalizePath(TrailingSlash::Trim))
|
.wrap(NormalizePath(TrailingSlash::Trim))
|
||||||
|
.service(web::resource("/").to(HttpResponse::Ok))
|
||||||
.service(web::resource("/v1/something").to(HttpResponse::Ok)),
|
.service(web::resource("/v1/something").to(HttpResponse::Ok)),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
// root paths should still work
|
||||||
|
let req = TestRequest::with_uri("/").to_request();
|
||||||
|
let res = call_service(&mut app, req).await;
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/?query=test").to_request();
|
||||||
|
let res = call_service(&mut app, req).await;
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("///").to_request();
|
||||||
|
let res = call_service(&mut app, req).await;
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
|
||||||
let req = TestRequest::with_uri("/v1/something////").to_request();
|
let req = TestRequest::with_uri("/v1/something////").to_request();
|
||||||
let res = call_service(&mut app, req).await;
|
let res = call_service(&mut app, req).await;
|
||||||
assert!(res.status().is_success());
|
assert!(res.status().is_success());
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
|
||||||
|
* add ability to set address for `TestServer` [#1645]
|
||||||
|
|
||||||
|
[#1645]: https://github.com/actix/actix-web/pull/1645
|
||||||
|
|
||||||
## 2.0.0 - 2020-09-11
|
## 2.0.0 - 2020-09-11
|
||||||
* Update actix-codec and actix-utils dependencies.
|
* Update actix-codec and actix-utils dependencies.
|
||||||
|
|
||||||
|
|
||||||
## 2.0.0-alpha.1 - 2020-05-23
|
## 2.0.0-alpha.1 - 2020-05-23
|
||||||
* Update the `time` dependency to 0.2.7
|
* Update the `time` dependency to 0.2.7
|
||||||
* Update `actix-connect` dependency to 2.0.0-alpha.2
|
* Update `actix-connect` dependency to 2.0.0-alpha.2
|
||||||
|
@ -44,12 +44,20 @@ pub use actix_testing::*;
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn test_server<F: ServiceFactory<TcpStream>>(factory: F) -> TestServer {
|
pub async fn test_server<F: ServiceFactory<TcpStream>>(factory: F) -> TestServer {
|
||||||
|
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
|
test_server_with_addr(tcp, factory).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start [`test server`](./fn.test_server.html) on a concrete Address
|
||||||
|
pub async fn test_server_with_addr<F: ServiceFactory<TcpStream>>(
|
||||||
|
tcp: net::TcpListener,
|
||||||
|
factory: F,
|
||||||
|
) -> TestServer {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
// run server in separate thread
|
// run server in separate thread
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let sys = System::new("actix-test-server");
|
let sys = System::new("actix-test-server");
|
||||||
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
|
||||||
let local_addr = tcp.local_addr().unwrap();
|
let local_addr = tcp.local_addr().unwrap();
|
||||||
|
|
||||||
Server::build()
|
Server::build()
|
||||||
|
@ -16,7 +16,8 @@ use futures_util::ready;
|
|||||||
use rand::{distributions::Alphanumeric, Rng};
|
use rand::{distributions::Alphanumeric, Rng};
|
||||||
|
|
||||||
use actix_web::dev::BodyEncoding;
|
use actix_web::dev::BodyEncoding;
|
||||||
use actix_web::middleware::Compress;
|
use actix_web::middleware::normalize::TrailingSlash;
|
||||||
|
use actix_web::middleware::{Compress, NormalizePath};
|
||||||
use actix_web::{dev, test, web, App, Error, HttpResponse};
|
use actix_web::{dev, test, web, App, Error, HttpResponse};
|
||||||
|
|
||||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||||
@ -866,6 +867,20 @@ async fn test_slow_request() {
|
|||||||
assert!(data.starts_with("HTTP/1.1 408 Request Timeout"));
|
assert!(data.starts_with("HTTP/1.1 408 Request Timeout"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_normalize() {
|
||||||
|
let srv = test::start_with(test::config().h1(), || {
|
||||||
|
App::new()
|
||||||
|
.wrap(NormalizePath::new(TrailingSlash::Trim))
|
||||||
|
.service(
|
||||||
|
web::resource("/one").route(web::to(|| HttpResponse::Ok().finish())),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = srv.get("/one/").send().await.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
}
|
||||||
|
|
||||||
// #[cfg(feature = "openssl")]
|
// #[cfg(feature = "openssl")]
|
||||||
// #[actix_rt::test]
|
// #[actix_rt::test]
|
||||||
// async fn test_ssl_handshake_timeout() {
|
// async fn test_ssl_handshake_timeout() {
|
||||||
|
Reference in New Issue
Block a user