Skip to content

Commit c3710a5

Browse files
committed
Extrac node WebServer
1 parent 1d57271 commit c3710a5

File tree

5 files changed

+93
-25
lines changed

5 files changed

+93
-25
lines changed

bin/node

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33

44
use React\EventLoop\Factory;
55
use React\Http\Server as HttpServer;
6-
use Psr\Http\Message\ServerRequestInterface;
7-
use Blockchain\Node\Response\JsonResponse;
8-
use React\Http\Response;
96
use React\Socket\Server;
107
use Blockchain\Node;
118
use Blockchain\Miner;
@@ -18,27 +15,14 @@ require __DIR__.'/../vendor/autoload.php';
1815
$loop = Factory::create();
1916

2017
$node = new Node(new Miner(new Blockchain(Block::genesis()), new HashDifficulty\ZeroPrefix()));
18+
$webServer = new HttpServer(new Node\WebServer($node));
2119

22-
$server = new HttpServer(function (ServerRequestInterface $request) use ($node) {
23-
switch (trim($request->getUri()->getPath(), '/')) {
24-
case 'blocks':
25-
return new JsonResponse($node->blocks());
26-
case 'mine':
27-
return new JsonResponse($node->mineBlock($request->getBody()->getContents()));
28-
case 'peers':
29-
return new JsonResponse($node->peers());
30-
case 'peers/add':
31-
$data = json_decode($request->getBody()->getContents(), true);
32-
$node->addPeer(new Node\Peer($data['host'], $data['port']));
33-
return new Response(204);
34-
default:
35-
return new Response(404);
36-
}
37-
});
38-
39-
$socket = new Server(8080, $loop);
40-
$server->listen($socket);
41-
42-
echo "Server running at http://127.0.0.1:8080\n";
20+
$params = getopt('', ['port::']);
21+
$port = $params['port'] ?? 8080;
22+
23+
$socket = new Server($port, $loop);
24+
$webServer->listen($socket);
25+
26+
echo sprintf("Server running at http://127.0.0.1:%s\n", $port);
4327

4428
$loop->run();

src/Block.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ public function index(): int
113113
return $this->index;
114114
}
115115

116+
public function data(): string
117+
{
118+
return $this->data;
119+
}
120+
116121
public static function calculateHash(
117122
int $index,
118123
string $previousHash,

src/Node.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function blocks(): array
3737
public function mineBlock(string $data): Block
3838
{
3939
$block = $this->miner->mineBlock($data);
40-
$this->peers->broadcast(new Message(Message::TYPE_LAST_BLOCK, serialize($block)));
40+
$this->peers->broadcast(new Message(Message::TYPE_LAST_BLOCK, json_encode($block)));
4141

4242
return $block;
4343
}

src/Node/WebServer.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Blockchain\Node;
6+
7+
use Blockchain\Node;
8+
use Blockchain\Node\Response\JsonResponse;
9+
use Psr\Http\Message\ServerRequestInterface;
10+
use React\Http\Response;
11+
12+
final class WebServer
13+
{
14+
/**
15+
* @var Node
16+
*/
17+
private $node;
18+
19+
public function __construct(Node $node)
20+
{
21+
$this->node = $node;
22+
}
23+
24+
public function __invoke(ServerRequestInterface $request): Response
25+
{
26+
switch ($request->getMethod().':'.trim($request->getUri()->getPath(), '/')) {
27+
case 'GET:blocks':
28+
return new JsonResponse($this->node->blocks());
29+
case 'POST:mine':
30+
return new JsonResponse($this->node->mineBlock($request->getBody()->getContents()));
31+
case 'GET:peers':
32+
return new JsonResponse($this->node->peers());
33+
case 'POST:peers/add':
34+
$data = json_decode($request->getBody()->getContents(), true);
35+
$this->node->addPeer(new Peer($data['host'], $data['port']));
36+
37+
return new Response(204);
38+
default:
39+
return new Response(404);
40+
}
41+
}
42+
}

tests/NodeTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Blockchain;
6+
7+
use Blockchain\Miner\HashDifficulty\ZeroPrefix;
8+
use PHPUnit\Framework\TestCase;
9+
10+
final class NodeTest extends TestCase
11+
{
12+
/**
13+
* @var Node
14+
*/
15+
private $node;
16+
17+
public function setUp(): void
18+
{
19+
$this->node = new Node(new Miner(new Blockchain(Block::genesis()), new ZeroPrefix()));
20+
}
21+
22+
public function testListBlock(): void
23+
{
24+
$blocks = $this->node->blocks();
25+
self::assertCount(1, $blocks);
26+
self::assertInstanceOf(Block::class, $blocks[0]);
27+
}
28+
29+
public function testMineBlock(): void
30+
{
31+
$block = $this->node->mineBlock('PHP is awesome');
32+
33+
self::assertInstanceOf(Block::class, $block);
34+
self::assertEquals(1, $block->index());
35+
self::assertEquals('PHP is awesome', $block->data());
36+
}
37+
}

0 commit comments

Comments
 (0)