Skip to content

Commit c0d02cc

Browse files
author
Greg Bowler
committed
Implement protocol version parsing
1 parent 2184a3e commit c0d02cc

File tree

4 files changed

+189
-2
lines changed

4 files changed

+189
-2
lines changed

src/Header/Headers.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ public function getAll(string $name):?array {
115115
return null;
116116
}
117117

118+
public function getFirst():string {
119+
return $this->headerLines[0] ?? "";
120+
}
121+
118122
public function current():HeaderLine {
119123
return $this->headerLines[$this->iteratorIndex];
120124
}

src/Message.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ trait Message {
1919
*
2020
* @return string HTTP protocol version.
2121
*/
22-
public function getProtocolVersion() {
22+
public function getProtocolVersion():string {
23+
if(strstr($this->protocol, "/")) {
24+
return substr(
25+
$this->protocol,
26+
strpos($this->protocol, "/") + 1
27+
);
28+
}
29+
2330
return $this->protocol;
2431
}
2532

@@ -43,7 +50,34 @@ public function withProtocolVersion($version) {
4350
}
4451

4552
$clone = clone $this;
46-
$clone->protocol = $version;
53+
54+
if(strstr($clone->protocol, "/")) {
55+
$versionStartPos = strpos(
56+
$clone->protocol,
57+
"/"
58+
) + 1;
59+
$versionEndPos = strpos(
60+
$clone->protocol,
61+
" "
62+
);
63+
64+
$protocol = "";
65+
$protocol .= substr(
66+
$clone->protocol,
67+
0,
68+
$versionStartPos
69+
);
70+
$protocol .= $version;
71+
$protocol .= substr(
72+
$clone->protocol,
73+
$versionEndPos
74+
);
75+
$clone->protocol = $protocol;
76+
}
77+
else {
78+
$clone->protocol = $version;
79+
}
80+
4781
return $clone;
4882
}
4983

src/Request.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ public function __construct(
2323
$this->method = RequestMethod::filterMethodName($method);
2424
$this->uri = $uri;
2525
$this->headers = $headers;
26+
27+
$firstLine = $this->headers->getFirst();
28+
$this->protocol = substr(
29+
$firstLine,
30+
0,
31+
strpos($firstLine, " ")
32+
);
2633
}
2734

2835
/**

test/unit/MessageTest.php

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
namespace Gt\Http\Test;
3+
4+
use Gt\Http\Header\Headers;
5+
use Gt\Http\Header\RequestHeaders;
6+
use Gt\Http\Message;
7+
use Gt\Http\Request;
8+
use Gt\Http\RequestMethod;
9+
use Gt\Http\Uri;
10+
use PHPUnit\Framework\MockObject\MockObject;
11+
use PHPUnit\Framework\TestCase;
12+
13+
class MessageTest extends TestCase {
14+
/** @dataProvider data_request */
15+
public function testGetProtocolVersionRequest(
16+
string $method,
17+
string $uriString,
18+
array $headersArray
19+
) {
20+
/** @var MockObject|Uri $uri */
21+
$uri = self::createMock(Uri::class);
22+
$uri->method("__toString")
23+
->willReturn($uriString);
24+
25+
/** @var MockObject|RequestHeaders $headers */
26+
$headers = self::createMock(RequestHeaders::class);
27+
$headers->method("getFirst")
28+
->willReturn($headersArray[0]);
29+
30+
$request = new Request(
31+
$method,
32+
$uri,
33+
$headers
34+
);
35+
36+
$expected = substr(
37+
$headersArray[0],
38+
strpos($headersArray[0], "/") + 1
39+
);
40+
$expected = substr(
41+
$expected,
42+
0,
43+
strpos($expected, " ")
44+
);
45+
46+
$protocolVersion = $request->getProtocolVersion();
47+
self::assertEquals($expected, $protocolVersion);
48+
}
49+
50+
public function data_request():array {
51+
$data = [];
52+
53+
for($i = 0; $i < 10; $i++) {
54+
$method = RequestMethod::ALLOWED_METHODS[
55+
array_rand(RequestMethod::ALLOWED_METHODS)
56+
];
57+
$uriString = self::generateUri();
58+
$headersArray = self::generateHeaders();
59+
60+
$data []= [
61+
$method,
62+
$uriString,
63+
$headersArray,
64+
];
65+
}
66+
67+
return $data;
68+
}
69+
70+
public static function generateUri():string {
71+
$uri = "http";
72+
if(rand(0, 1)) {
73+
$uri .= "s";
74+
}
75+
$uri .= "://";
76+
77+
$uri .= uniqid("www.");
78+
$uri .= ".com";
79+
80+
if(rand(0, 1)) {
81+
$pathParts = rand(1, 10);
82+
for($i = 0; $i < $pathParts; $i++) {
83+
$uri .= "/";
84+
$uri .= uniqid();
85+
}
86+
}
87+
88+
if(rand(0, 1)) {
89+
$uri .= "?";
90+
$qsParts = rand(1, 10);
91+
for($i = 0; $i < $qsParts; $i++) {
92+
if($i > 0) {
93+
$uri .= "&";
94+
}
95+
96+
$qsParts .= uniqid("key-");
97+
$qsParts .= "=";
98+
$qsParts .= uniqid("value-");
99+
}
100+
}
101+
102+
return $uri;
103+
}
104+
105+
public static function generateHeaders():array {
106+
$headers = [];
107+
108+
$firstLine = "";
109+
if(rand(0, 1)) {
110+
$firstLine .= strtoupper(
111+
substr(uniqid(), 0, 4)
112+
);
113+
$firstLine .= "/";
114+
$firstLine .= rand(1, 9);
115+
}
116+
else {
117+
$firstLine .= "HTTP";
118+
$firstLine .= "/";
119+
if(rand(0, 1)) {
120+
$firstLine .= "1.1";
121+
}
122+
else {
123+
$firstLine .= rand(2, 3);
124+
}
125+
}
126+
127+
$firstLine .= " ";
128+
$firstLine .= rand(200, 550);
129+
$firstLine .= " ";
130+
$firstLine .= "TEST";
131+
$headers []= $firstLine;
132+
133+
for($i = 0; $i < rand(1, 10); $i++) {
134+
$line = uniqid("Key-");
135+
$line .= ": ";
136+
$line .= uniqid("value-");
137+
$headers []= $line;
138+
}
139+
140+
return $headers;
141+
}
142+
}

0 commit comments

Comments
 (0)