actix / actix/actix-web

middleware::Compress seems to be buffering content indefinitely

オープン
#3,410 コメント 1 件 リアクション 4 件 担当者 0 名 GitHub で見る
A-web C-bug
主要言語
Rust
スター
24.8k
フォーク
1.9k
平均マージ
23時間 10分
マージ済み PR(30日)
26

説明

Initially reported https://github.com/lovasoa/SQLpage/issues/435

When making streaming responses and activating `middleware::Compress`, the compression seems to buffer content indefinitely, without ever flushing the streaming data when it's small enough.

Here is an example demonstrating the problem

```rust
use actix_web::{
get, middleware,
web::{self, Bytes},
App, HttpResponse, HttpServer,
};
use futures::stream::{self, StreamExt};
use std::time::Duration;
use tokio::time::sleep;

#[get("/")]
async fn index() -> HttpResponse {
let stream = stream::once(async {
let initial_content = r#"



Streaming HTML Example

This content appears immediately

"#;
Ok::<_, std::io::Error>(Bytes::from(initial_content))
})
.chain(stream::once(async {
sleep(Duration::from_secs(5)).await;
let delayed_content = r#"
This content appears after 5 seconds

"#;
Ok::<_, std::io::Error>(Bytes::from(delayed_content))
}));

HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.streaming(stream)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(
web::scope("/compressed")
.wrap(middleware::Compress::default())
.service(index),
)
.service(index)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
```

## Expected Behavior

- When visiting I should see `This content appears immediately` immediateley, and then after 5 seconds `This content appears after 5 seconds`
- When visiting http://localhost:8080/compressed/ the behavior should be the same, or as close as possible.

## Current Behavior

- When visiting http://localhost:8080/compressed/ the page stays blank for five seconds, then displays `This content appears immediately` and `This content appears after 5 seconds` at the same time.

## Possible Solution

The compression middleware should flush the writer object after a few milliseconds without new input data, to avoid indefinitely retaining data in memory on the server when it could actually already be rendered on the client.

It's possible to retain data in memory for a few milliseconds to ensure good compression ratios, but actix shouldn't keep streaming data in memory for multiple seconds.

## Context

We are trying to integrate easy native loading spinners without javascript in [SQLPage](https://sql.ophir.dev)

## Your Environment

- Actix Web Version: 4.8.0

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

Start with the middleware::Compress implementation and run the supplied Rust streaming example, comparing compressed and uncompressed responses. Done means the initial HTML appears promptly on the compressed endpoint while the delayed content still arrives after five seconds, without changing the documented streaming behavior.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
rust
領域
api, backend
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。