Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  specify next release
  CS
  fix using synchronous operating system
  fix loading the whole response body in memory
  wait for the server to boot
  dump server output to see why it fails
  return error to see why the test fail
  make sure the connections tasks are loaded in memory
  • Loading branch information
Baptouuuu committed Aug 3, 2024
2 parents 228f63e + 0eff741 commit 4cd4860
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 33 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 3.0.1 - 2024-08-03

### Fixed

- The whole response body was loaded in memory
- The server was blocking while waiting new connections, preventing previous requests from being served

## 3.0.0 - 2024-03-10

### Changed
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"require": {
"php": "~8.2",
"innmind/immutable": "~5.7",
"innmind/mantle": "~2.0",
"innmind/io": "~2.7",
"innmind/http-parser": "~2.1",
Expand Down
15 changes: 3 additions & 12 deletions src/Command/Serve.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
ServerRequest\Environment as HttpEnv,
};
use Innmind\Url\Authority\Port;
use Innmind\IO\Sockets\Server as IOServer;
use Innmind\Immutable\Str;

final class Serve implements Command
{
Expand Down Expand Up @@ -52,12 +50,7 @@ public function __invoke(Console $console): Console
static fn() => 8080,
);

return Open::of(Port::of($port))($this->os)->match(
fn($servers) => $this->serve($console, $servers),
static fn() => $console
->error(Str::of("Failed to open sockets\n"))
->exit(1),
);
return $this->serve($console, Open::of(Port::of($port)));
}

/**
Expand All @@ -84,20 +77,18 @@ public function usage(): string
USAGE;
}

private function serve(Console $console, IOServer|IOServer\Pool $servers): Console
private function serve(Console $console, Open $open): Console
{
$source = Server::of(
$this->os->clock(),
$servers,
$open,
InjectEnvironment::of(HttpEnv::of($console->variables())),
$this->handle,
);
$forerunner = Forerunner::of($this->os);

if ($console->options()->contains('no-output')) {
$source = $source->withOutput(Nothing::of());
} else {
$console = $console->output(Str::of("HTTP server ready!\n"));
}

return $forerunner($console, $source);
Expand Down
24 changes: 13 additions & 11 deletions src/Encode.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,19 @@ public function __invoke(Response $response): Sequence
$response->statusCode()->toString(),
$response->statusCode()->reasonPhrase(),
);
/** @var Sequence<string> */
$chunks = Sequence::of($firstLine);

return $chunks
->append($headers->all()->map(
static fn($header) => $header->toString(),
))
->add('')
->map(Str::of(...))
->map(static fn($line) => $line->append(self::EOL))
->append($response->body()->chunks())

return $response
->body()
->chunks()
->prepend(
$headers
->all()
->map(static fn($header) => $header->toString())
->prepend(Sequence::of($firstLine))
->add('')
->map(Str::of(...))
->map(static fn($line) => $line->append(self::EOL)),
)
->add(Str::of(self::EOL))
->add(Str::of(self::EOL));
}
Expand Down
39 changes: 32 additions & 7 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@

final class Server
{
private IOServer|IOServer\Pool $servers;
private Open $open;
private IOServer|IOServer\Pool|null $servers = null;
private InjectEnvironment $injectEnv;
private Encode $encode;
/** @var callable(ServerRequest, OperatingSystem): Response */
Expand All @@ -47,13 +48,13 @@ final class Server
* @param callable(ServerRequest, OperatingSystem): Response $handle
*/
private function __construct(
IOServer|IOServer\Pool $servers,
Open $open,
InjectEnvironment $injectEnv,
Encode $encode,
callable $handle,
Display $display,
) {
$this->servers = $servers->watch();
$this->open = $open;
$this->injectEnv = $injectEnv;
$this->encode = $encode;
$this->handle = $handle;
Expand All @@ -72,6 +73,30 @@ public function __invoke(
Continuation $continuation,
Sequence $terminated,
): Continuation {
if (\is_null($this->servers)) {
$this->servers = ($this->open)($os)->match(
static fn($servers) => $servers->watch(),
static fn() => null,
);

if (!\is_null($this->servers)) {
$console = ($this->display)(
$console,
Str::of("HTTP server ready!\n"),
);
}
}

if (\is_null($this->servers)) {
return $continuation
->carryWith(
$console
->error(Str::of("Failed to open sockets\n"))
->exit(1),
)
->terminate();
}

$console = ($this->display)($console, Str::of("Pending connections...\n"));

$connections = $this
Expand Down Expand Up @@ -127,20 +152,20 @@ public function __invoke(

return $continuation
->carryWith($console)
->launch($connections);
->launch($connections->memoize());
}

/**
* @param callable(ServerRequest, OperatingSystem): Response $handle
*/
public static function of(
Clock $clock,
IOServer|IOServer\Pool $servers,
Open $open,
InjectEnvironment $injectEnv,
callable $handle,
): self {
return new self(
$servers,
$open,
$injectEnv,
new Encode($clock),
$handle,
Expand All @@ -154,7 +179,7 @@ public static function of(
public function withOutput(Output $output): self
{
return new self(
$this->servers,
$this->open,
$this->injectEnv,
$this->encode,
$this->handle,
Expand Down
13 changes: 10 additions & 3 deletions tests/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,15 @@ public function tearDown(): void

public function testServerRespond()
{
// let time for the server to boot
\sleep(1);
$found = $this
->server
->output()
->chunks()
->find(static fn($pair) => $pair[0]->startsWith('HTTP server ready!'));
$this->assertTrue($found->match(
static fn() => true,
static fn() => false,
));

$response = $this
->os
Expand All @@ -61,7 +68,7 @@ public function testServerRespond()
))
->match(
static fn($success) => $success->response(),
static fn() => null,
static fn($error) => $error,
);

$this->assertInstanceOf(Response::class, $response);
Expand Down

0 comments on commit 4cd4860

Please sign in to comment.