Osumi Framework
es en eu v9.10.1 GitHub

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:

They cannot return body, because a streamed response has no complete body materialized in memory.

If Middleware returns stop => true before emission starts:


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:

  1. readable stream;
  2. HTTP headers;
  3. HTTP status code;
  4. chunk size;
  5. 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.