From 5c5527daa4350a3b3c55a289554549403526f3c3 Mon Sep 17 00:00:00 2001 From: Aaron Bonneau Date: Wed, 19 Jul 2017 13:13:58 -0400 Subject: [PATCH] Require Host on 1.1 requests --- src/RequestHeaderParser.php | 4 ++++ tests/RequestHeaderParserTest.php | 16 ++++++++++++++++ tests/ServerTest.php | 8 ++++---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/RequestHeaderParser.php b/src/RequestHeaderParser.php index 6fb7d0b5..1f0b9e97 100644 --- a/src/RequestHeaderParser.php +++ b/src/RequestHeaderParser.php @@ -163,6 +163,10 @@ private function parseRequest($headers) } } + if ($request->getProtocolVersion() === '1.1' && !$request->hasHeader('Host')) { + throw new \InvalidArgumentException('A client must send a host header field in all HTTP/1.1 request messages'); + } + // Optional Host header value MUST be valid (host and optional port) if ($request->hasHeader('Host')) { $parts = parse_url('http://' . $request->getHeaderLine('Host')); diff --git a/tests/RequestHeaderParserTest.php b/tests/RequestHeaderParserTest.php index cf200fb8..a1028032 100644 --- a/tests/RequestHeaderParserTest.php +++ b/tests/RequestHeaderParserTest.php @@ -234,6 +234,22 @@ public function testInvalidAbsoluteFormSchemeEmitsError() $this->assertSame('Invalid absolute-form request-target', $error->getMessage()); } + public function testHttp11RequestWithNoHostHeaderEmitsError() + { + $error = null; + + $parser = new RequestHeaderParser(); + $parser->on('headers', $this->expectCallableNever()); + $parser->on('error', function ($message) use (&$error) { + $error = $message; + }); + + $parser->feed("GET / HTTP/1.1\r\n\r\n"); + + $this->assertInstanceOf('InvalidArgumentException', $error); + $this->assertSame('A client must send a host header field in all HTTP/1.1 request messages', $error->getMessage()); + } + public function testInvalidAbsoluteFormWithFragmentEmitsError() { $error = null; diff --git a/tests/ServerTest.php b/tests/ServerTest.php index 88d5e54b..35951c26 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -891,7 +891,7 @@ function ($data) use (&$buffer) { $server->listen($this->socket); $this->socket->emit('connection', array($this->connection)); - $data = "GET / HTTP/1.1\r\n\r\n"; + $data = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"; $this->connection->emit('data', array($data)); $this->assertEquals("HTTP/1.1 200 OK\r\nUpgrade: demo\r\nContent-Length: 3\r\nConnection: close\r\n\r\nfoo", $buffer); @@ -919,7 +919,7 @@ function ($data) use (&$buffer) { $server->listen($this->socket); $this->socket->emit('connection', array($this->connection)); - $data = "GET / HTTP/1.1\r\nUpgrade: demo\r\n\r\n"; + $data = "GET / HTTP/1.1\r\nUpgrade: demo\r\nHost: localhost\r\n\r\n"; $this->connection->emit('data', array($data)); $this->assertEquals("HTTP/1.1 200 OK\r\nContent-Length: 3\r\nConnection: close\r\n\r\nfoo", $buffer); @@ -949,7 +949,7 @@ function ($data) use (&$buffer) { $server->listen($this->socket); $this->socket->emit('connection', array($this->connection)); - $data = "GET / HTTP/1.1\r\nUpgrade: demo\r\n\r\n"; + $data = "GET / HTTP/1.1\r\nUpgrade: demo\r\nHost: localhost\r\n\r\n"; $this->connection->emit('data', array($data)); $this->assertEquals("HTTP/1.1 101 Switching Protocols\r\nUpgrade: demo\r\nConnection: upgrade\r\n\r\nfoo", $buffer); @@ -979,7 +979,7 @@ function ($data) use (&$buffer) { $server->listen($this->socket); $this->socket->emit('connection', array($this->connection)); - $data = "GET / HTTP/1.1\r\nUpgrade: demo\r\n\r\n"; + $data = "GET / HTTP/1.1\r\nUpgrade: demo\r\nHost: localhost\r\n\r\n"; $this->connection->emit('data', array($data)); $stream->write('hello');