Migration Guide: 9.9.1 → 9.10.0
Osumi Framework 9.10.0 introduces native support for streamed HTTP responses.
Updating from 9.9.1 is backward compatible and does not require changes to existing application code.
There is no automatic migration step for this release because no application files or configuration need to be transformed.
Streamed responses
Components can now return an OStreamResponse directly from their run() method.
<?php
declare(strict_types=1);
namespace Osumi\OsumiFramework\App\Module\Download;
use Osumi\OsumiFramework\Core\OComponent;
use Osumi\OsumiFramework\Web\OStreamResponse;
class DownloadComponent extends OComponent {
/**
* Stream a file to the client.
*
* @return OStreamResponse Streamed HTTP response.
*/
public function run(): OStreamResponse {
$stream = fopen(
'/path/to/file.zip',
'rb'
);
if ($stream === false) {
throw new \RuntimeException(
'Could not open file.'
);
}
return new OStreamResponse(
$stream,
[
'Content-Type' => 'application/zip',
'Content-Length' => strval(
filesize('/path/to/file.zip')
),
'Content-Disposition' => 'attachment; filename="file.zip"'
]
);
}
}
A component whose run() method explicitly declares OStreamResponse does not require a template file.
Lifecycle
A streamed response follows this pipeline:
before Middleware
↓
Component
↓
OStreamResponse
↓
afterRender Middleware
↓
afterResponse Middleware
↓
Database connections closed
↓
HTTP headers
↓
Chunked stream emission
Layouts are not applied to streamed responses.
The framework does not start sending stream bytes until both afterRender and afterResponse have completed.
This allows Middleware to stop the request before a download begins.
Middlewares
During a streamed response:
$data['is_streaming_response'] === true
Middlewares can still modify:
contextheadersstatus_codestopmessage
They cannot return body, because a streamed response has no complete body materialized in memory.
If Middleware returns stop => true before emission starts:
- the stream is discarded;
- normal response headers are restored;
- the regular error response is generated;
- no stream bytes are sent.
Resource management
By default, OStreamResponse considers the framework to own the stream and closes it automatically.
The default chunk size is 1 MiB, allowing large files to be served without loading their complete contents into memory.
new OStreamResponse(
$stream,
$headers,
200,
1048576,
true
);
The parameters are:
- readable stream;
- HTTP headers;
- HTTP status code;
- chunk size;
- whether the stream is automatically closed.
Compatibility
Traditional template-based responses continue to work unchanged.
Existing components can continue using:
public function run(): void
public function run(ORequest $req): void
public function run(MyDTO $dto): void
The new OStreamResponse extends these capabilities and does not replace the traditional rendering system.