Skip to content

Commit 1977e04

Browse files
authored
Merge pull request #123 from clue-labs/close-request
Closing request should stop reading from connection
2 parents 1373acb + 9125a4d commit 1977e04

File tree

2 files changed

+60
-41
lines changed

2 files changed

+60
-41
lines changed

src/Server.php

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
*/
3434
class Server extends EventEmitter
3535
{
36-
private $io;
37-
3836
/**
3937
* Creates a HTTP server that accepts connections from the given socket.
4038
*
@@ -65,49 +63,36 @@ class Server extends EventEmitter
6563
*/
6664
public function __construct(SocketServerInterface $io)
6765
{
68-
$this->io = $io;
69-
$that = $this;
70-
71-
$this->io->on('connection', function (ConnectionInterface $conn) use ($that) {
72-
// TODO: http 1.1 keep-alive
73-
// TODO: chunked transfer encoding (also for outgoing data)
74-
// TODO: multipart parsing
75-
76-
$parser = new RequestHeaderParser();
77-
$parser->on('headers', function (Request $request, $bodyBuffer) use ($conn, $parser, $that) {
78-
// attach remote ip to the request as metadata
79-
$request->remoteAddress = trim(
80-
parse_url('tcp://' . $conn->getRemoteAddress(), PHP_URL_HOST),
81-
'[]'
82-
);
66+
$io->on('connection', array($this, 'handleConnection'));
67+
}
8368

84-
// forward pause/resume calls to underlying connection
85-
$request->on('pause', array($conn, 'pause'));
86-
$request->on('resume', array($conn, 'resume'));
69+
/** @internal */
70+
public function handleConnection(ConnectionInterface $conn)
71+
{
72+
$that = $this;
73+
$parser = new RequestHeaderParser();
74+
$listener = array($parser, 'feed');
75+
$parser->on('headers', function (Request $request, $bodyBuffer) use ($conn, $listener, $parser, $that) {
76+
// parsing request completed => stop feeding parser
77+
$conn->removeListener('data', $listener);
8778

88-
$that->handleRequest($conn, $request, $bodyBuffer);
79+
$that->handleRequest($conn, $request);
8980

90-
$conn->removeListener('data', array($parser, 'feed'));
91-
$conn->on('end', function () use ($request) {
92-
$request->emit('end');
93-
});
94-
$conn->on('data', function ($data) use ($request) {
95-
$request->emit('data', array($data));
96-
});
97-
});
81+
if ($bodyBuffer !== '') {
82+
$request->emit('data', array($bodyBuffer));
83+
}
84+
});
9885

99-
$listener = array($parser, 'feed');
100-
$conn->on('data', $listener);
101-
$parser->on('error', function() use ($conn, $listener, $that) {
102-
// TODO: return 400 response
103-
$conn->removeListener('data', $listener);
104-
$that->emit('error', func_get_args());
105-
});
86+
$conn->on('data', $listener);
87+
$parser->on('error', function() use ($conn, $listener, $that) {
88+
// TODO: return 400 response
89+
$conn->removeListener('data', $listener);
90+
$that->emit('error', func_get_args());
10691
});
10792
}
10893

10994
/** @internal */
110-
public function handleRequest(ConnectionInterface $conn, Request $request, $bodyBuffer)
95+
public function handleRequest(ConnectionInterface $conn, Request $request)
11196
{
11297
$response = new Response($conn);
11398
$response->on('close', array($request, 'close'));
@@ -118,10 +103,30 @@ public function handleRequest(ConnectionInterface $conn, Request $request, $body
118103
return;
119104
}
120105

121-
$this->emit('request', array($request, $response));
106+
// attach remote ip to the request as metadata
107+
$request->remoteAddress = trim(
108+
parse_url('tcp://' . $conn->getRemoteAddress(), PHP_URL_HOST),
109+
'[]'
110+
);
122111

123-
if ($bodyBuffer !== '') {
124-
$request->emit('data', array($bodyBuffer));
125-
}
112+
// forward pause/resume calls to underlying connection
113+
$request->on('pause', array($conn, 'pause'));
114+
$request->on('resume', array($conn, 'resume'));
115+
116+
// closing the request currently emits an "end" event
117+
// stop reading from the connection by pausing it
118+
$request->on('end', function () use ($conn) {
119+
$conn->pause();
120+
});
121+
122+
// forward connection events to request
123+
$conn->on('end', function () use ($request) {
124+
$request->emit('end');
125+
});
126+
$conn->on('data', function ($data) use ($request) {
127+
$request->emit('data', array($data));
128+
});
129+
130+
$this->emit('request', array($request, $response));
126131
}
127132
}

tests/ServerTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@ public function testRequestResumeWillbeForwardedToConnection()
117117
$this->connection->emit('data', array($data));
118118
}
119119

120+
public function testRequestCloseWillPauseConnection()
121+
{
122+
$server = new Server($this->socket);
123+
$server->on('request', function (Request $request) {
124+
$request->close();
125+
});
126+
127+
$this->connection->expects($this->once())->method('pause');
128+
$this->socket->emit('connection', array($this->connection));
129+
130+
$data = $this->createGetRequest();
131+
$this->connection->emit('data', array($data));
132+
}
133+
120134
public function testRequestEventWithoutBodyWillNotEmitData()
121135
{
122136
$never = $this->expectCallableNever();

0 commit comments

Comments
 (0)