Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debug server #125

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions config/routes.php
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
use Yiisoft\Yii\Debug\Api\Inspector\Controller\CacheController;
use Yiisoft\Yii\Debug\Api\Inspector\Controller\CommandController;
use Yiisoft\Yii\Debug\Api\Inspector\Controller\ComposerController;
use Yiisoft\Yii\Debug\Api\Inspector\Controller\DebugServerController;
use Yiisoft\Yii\Debug\Api\Inspector\Controller\GitController;
use Yiisoft\Yii\Debug\Api\Inspector\Controller\InspectController;
use Yiisoft\Yii\Debug\Api\Inspector\Controller\OpcacheController;
@@ -58,6 +59,9 @@ static function (ResponseFactoryInterface $responseFactory, ValidatorInterface $
Route::get('/event-stream')
->action([DebugController::class, 'eventStream'])
->name('event-stream'),
Route::get('/dev')
->action([DebugServerController::class, 'stream'])
->name('stream'),
),
Group::create('/inspect/api')
->withCors(CorsAllowAll::class)
9 changes: 5 additions & 4 deletions src/Debug/Controller/DebugController.php
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@

namespace Yiisoft\Yii\Debug\Api\Debug\Controller;

use OpenApi\Attributes as OA;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
@@ -12,6 +13,7 @@
use Yiisoft\Assets\AssetPublisherInterface;
use Yiisoft\DataResponse\DataResponse;
use Yiisoft\DataResponse\DataResponseFactoryInterface;
use Yiisoft\Http\Header;
use Yiisoft\Router\CurrentRoute;
use Yiisoft\Yii\Debug\Api\Debug\Exception\NotFoundException;
use Yiisoft\Yii\Debug\Api\Debug\Exception\PackageNotInstalledException;
@@ -21,7 +23,6 @@
use Yiisoft\Yii\Debug\Api\ServerSentEventsStream;
use Yiisoft\Yii\Debug\Storage\StorageInterface;
use Yiisoft\Yii\View\ViewRenderer;
use OpenApi\Attributes as OA;

/**
* Debug controller provides endpoints that expose information about requests processed that debugger collected.
@@ -323,11 +324,11 @@
$retries = 0;

return $responseFactory->createResponse()
->withHeader('Content-Type', 'text/event-stream')
->withHeader('Cache-Control', 'no-cache')
->withHeader('Connection', 'keep-alive')
->withHeader(Header::CONTENT_TYPE, 'text/event-stream')
->withHeader(Header::CACHE_CONTROL, 'no-cache')
->withHeader(Header::CONNECTION, 'keep-alive')
->withBody(
new ServerSentEventsStream(function (array &$buffer) use (

Check failure on line 331 in src/Debug/Controller/DebugController.php

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

InvalidArgument

src/Debug/Controller/DebugController.php:331:44: InvalidArgument: Argument 1 of Yiisoft\Yii\Debug\Api\ServerSentEventsStream::__construct expects Closure():Generator, but impure-Closure(array<array-key, mixed>):bool provided (see https://psalm.dev/004)

Check failure on line 331 in src/Debug/Controller/DebugController.php

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

InvalidArgument

src/Debug/Controller/DebugController.php:331:44: InvalidArgument: Argument 1 of Yiisoft\Yii\Debug\Api\ServerSentEventsStream::__construct expects Closure():Generator, but impure-Closure(array<array-key, mixed>):bool provided (see https://psalm.dev/004)

Check failure on line 331 in src/Debug/Controller/DebugController.php

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

InvalidArgument

src/Debug/Controller/DebugController.php:331:44: InvalidArgument: Argument 1 of Yiisoft\Yii\Debug\Api\ServerSentEventsStream::__construct expects Closure():Generator, but impure-Closure(array<array-key, mixed>):bool provided (see https://psalm.dev/004)
$compareFunction,
&$hash,
&$retries,
54 changes: 54 additions & 0 deletions src/Inspector/Controller/DebugServerController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Debug\Api\Inspector\Controller;

use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Yiisoft\Http\Header;
use Yiisoft\Yii\Debug\Api\ServerSentEventsStream;
use Yiisoft\Yii\Debug\DebugServer\Connection;

final class DebugServerController
{
public function stream(
ResponseFactoryInterface $responseFactory
): ResponseInterface {
if (\function_exists('pcntl_signal')) {
\pcntl_signal(\SIGINT, static function (): never {
exit(1);
});
}

$socket = Connection::create();

Check failure on line 24 in src/Inspector/Controller/DebugServerController.php

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

UndefinedClass

src/Inspector/Controller/DebugServerController.php:24:19: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Debug\DebugServer\Connection does not exist (see https://psalm.dev/019)

Check failure on line 24 in src/Inspector/Controller/DebugServerController.php

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

UndefinedClass

src/Inspector/Controller/DebugServerController.php:24:19: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Debug\DebugServer\Connection does not exist (see https://psalm.dev/019)

Check failure on line 24 in src/Inspector/Controller/DebugServerController.php

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

UndefinedClass

src/Inspector/Controller/DebugServerController.php:24:19: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Debug\DebugServer\Connection does not exist (see https://psalm.dev/019)
$socket->bind();

return $responseFactory->createResponse()
->withHeader(Header::CONTENT_TYPE, 'text/event-stream')
->withHeader(Header::CACHE_CONTROL, 'no-cache')
->withHeader(Header::CONNECTION, 'keep-alive')
->withBody(
new ServerSentEventsStream(function () use ($socket) {
foreach ($socket->read() as $message) {
switch ($message[0]) {
case Connection::TYPE_ERROR:
return '';
case Connection::TYPE_RELEASE:
/**
* Break the loop if the client aborted the connection (closed the page)
*/
if (connection_aborted()) {
return '';
}
break;
case Connection::TYPE_RESULT:

yield $message[1];
}
}
return '';
})
);
}
}
29 changes: 14 additions & 15 deletions src/ServerSentEventsStream.php
Original file line number Diff line number Diff line change
@@ -5,13 +5,16 @@
namespace Yiisoft\Yii\Debug\Api;

use Closure;
use Generator;
use Psr\Http\Message\StreamInterface;

final class ServerSentEventsStream implements StreamInterface, \Stringable
{
public array $buffer = [];
private bool $eof = false;

/**
* @param Closure(): Generator $stream
*/
public function __construct(
private Closure $stream,
) {
@@ -27,9 +30,9 @@
$this->eof = true;
}

public function getSize(): int
public function getSize(): ?int
{
return 0;
return null;
}

public function tell(): int
@@ -77,24 +80,20 @@
*/
public function read(int $length): string
{
$continue = ($this->stream)($this->buffer);
foreach (($this->stream)($this) as $message) {

Check failure on line 83 in src/ServerSentEventsStream.php

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

TooManyArguments

src/ServerSentEventsStream.php:83:18: TooManyArguments: Too many arguments for - expecting 0 but saw 1 (see https://psalm.dev/026)

Check failure on line 83 in src/ServerSentEventsStream.php

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

TooManyArguments

src/ServerSentEventsStream.php:83:18: TooManyArguments: Too many arguments for - expecting 0 but saw 1 (see https://psalm.dev/026)

Check failure on line 83 in src/ServerSentEventsStream.php

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

TooManyArguments

src/ServerSentEventsStream.php:83:18: TooManyArguments: Too many arguments for - expecting 0 but saw 1 (see https://psalm.dev/026)
if (empty($message)) {
break;
}

if (!$continue) {
$this->eof = true;
return sprintf("data: %s\n\n", $message);
}

$output = '';
foreach ($this->buffer as $key => $value) {
unset($this->buffer[$key]);
$output .= sprintf("data: %s\n", $value);
}
$output .= "\n";
return $output;
$this->eof = true;
return '';
}

public function getContents(): string
{
return $this->read(1024);
return $this->read(8_388_608); // 8MB
}

public function getMetadata($key = null): array
Loading