Actix HTTP2 error with long blocking requests and async task
- Lenguaje dominante
- Rust
- Estrellas
- 24.8k
- Forks
- 1.9k
- Merge medio
- 23 h 10 min
- PR fusionados (30 d)
- 26
Descripción
Hello, and thank you very much for this crate.
Here is the gist for a reproductible example: [https://gist.github.com/allencamal/cfe62dda9fc8132ba6707d5771cac7f1](https://gist.github.com/allencamal/cfe62dda9fc8132ba6707d5771cac7f1)
## Expected Behavior
It should be possible to curl the `failing` endpoint.
## Current Behavior
When `curl`ing the `failing` endpoint, `curl` returns the following error message:
`curl: (18) transfer closed with 7302400 bytes remaining to read`.
## Possible Solution
Actually, forcing HTTP1.1 via `curl` with the `--http1.1` option works, but I don't think this is a viable option. Disabling TLS forces HTTP1.1, and also works, but that is not something viable.
Also, using `spawn_blocking` for the blocking `sleep` fixes the issue, but that does not make the bug less curious.
## Steps to Reproduce (for bugs)
Gist: [https://gist.github.com/allencamal/cfe62dda9fc8132ba6707d5771cac7f1](https://gist.github.com/allencamal/cfe62dda9fc8132ba6707d5771cac7f1)
1. Create a new cargo project
2. Create a basic TLS server with `actix-web` and `rustls`
3. Create an endpoint that spawns a blocking task, sleeps for 15 seconds with `std::thread::sleep`, and return more than 13 MB of data.
4. Curl this endpoint. `curl --insecure https://localhost:8085/failing > a`
## Context
Here are the two endpoints:
```rust
#[actix_web::get("/working")]
async fn working(req: actix_web::HttpRequest) -> actix_web::Result {
log::info!("{:?}", req.version());
std::thread::sleep(std::time::Duration::from_secs(15));
Ok(actix_web::HttpResponse::Ok().body(DATA.to_vec()))
}
#[actix_web::get("/failing")]
async fn failing(req: actix_web::HttpRequest) -> actix_web::Result {
log::info!("{:?}", req.version());
actix_web::rt::task::spawn_blocking(|| println!("Request will fail")).await;
std::thread::sleep(std::time::Duration::from_secs(15));
Ok(actix_web::HttpResponse::Ok().body(DATA.to_vec()))
}
```
Here is the gist for a reproductible example: [https://gist.github.com/allencamal/cfe62dda9fc8132ba6707d5771cac7f1](https://gist.github.com/allencamal/cfe62dda9fc8132ba6707d5771cac7f1)
I'm creating a very basic HTTP web server, using TLS (so that http2 is available). I've got two endpoints, that basically just sleeps 15 secs (using `std`'s sleep, not `tokio`'s) and returns 20 MB of data. (for less data, e.g. 10 MB, the bug does not appears).
From my experience, sleeping for less than 15 seconds (e.g. 5 seconds) also fails, but anything less than 3 seconds works correctly.
The only difference between the two endpoints is that one calls:
`actix_web::rt::task::spawn_blocking(|| println!("Request will fail")).await;` before sleeping (blocking).
If I curl my two endpoints:
```bash
curl --insecure https://localhost:8085/working > a
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 19.0M 100 19.0M 0 0 1271k 0 0:00:15 0:00:15 --:--:-- 4709k
```
```bash
curl --insecure https://localhost:8085/failing > a
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
63 19.0M 63 12.1M 0 0 815k 0 0:00:23 0:00:15 0:00:08 3109k
curl: (18) transfer closed with 7302400 bytes remaining to read
```
The one that spawn a blocking task fails.
Note that on another project, I have a similar issue, but the error is
`curl (92) HTTP/2 stream 1 was not closed cleanly before end of the underlying stream.`
## Your Environment
`Cargo.toml` included at the beginning of the gist
- Rust Version (I.e, output of `rustc -V`): rustc 1.60.0 (7737e0b5c 2022-04-04)
- Actix Web Version: 4.0.1
Guía de contribución
Evaluación
Este issue todavía no se ha evaluado.