Skip to content
Permalink
Browse files

Parse HTTP headers sanely

  • Loading branch information...
mkosturkov committed Jun 4, 2018
1 parent 959dffa commit 864a0bac1bec1f2f7ffd0514e46fcb06c0b74465
Showing with 52 additions and 19 deletions.
  1. +1 −0 phpunit.xml
  2. +14 −19 src/HTTP/CURLClient.php
  3. +4 −0 src/HTTP/Response.php
  4. +33 −0 test/php/HTTP/CURLClientTest.php
@@ -9,6 +9,7 @@
<testsuites>
<testsuite name="all">
<directory>test/</directory>
<exclude>test/php/HTTP/CURLClientTest.php</exclude>
</testsuite>
</testsuites>
</phpunit>
@@ -27,13 +27,25 @@ public function post(URL $url, $data, array $headers = []) {
}
private function request(URL $url, array $headers = [], array $opts = []) {
$response = new Response();
$readHeader = function ($_, $headerLine) use ($response) {
if (strpos($headerLine, 'HTTP/') === 0) {
$response->setHeaders([]);
} else {
list ($name, $value) = explode(':', $headerLine, 2);
if (trim($name) !== '') {
$response->setHeader($name, trim($value));
}
}
return strlen($headerLine);
};
$ch = curl_init((string)$url);
curl_setopt_array($ch, $opts + [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $this->makeHeaders($headers),
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_HEADER => true
CURLOPT_HEADERFUNCTION => $readHeader
]);
$responseText = @curl_exec($ch);
if ($responseText === false) {
@@ -43,8 +55,8 @@ private function request(URL $url, array $headers = [], array $opts = []) {
if (!preg_match('/^2/', $info['http_code'])) {
throw new HTTPError($info['http_code']);
}
$response = $this->parseResponse($responseText);
$response->setCode($info['http_code']);
$response->setContent($responseText);
return $response;
}
@@ -56,21 +68,4 @@ private function makeHeaders(array $headers) {
return $result;
}
private function parseResponse($responseText) {
// When status 100 curl returns two lines with status (\r\n\r\n x2)
$responseParts = explode("\r\n\r\n", $responseText);
$body = array_pop($responseParts);
$headersText = array_pop($responseParts);
$response = new Response();
$response->setContent($body);
foreach (explode("\r\n", $headersText) as $idx => $header) {
if ($idx === 0) {
continue;
}
list ($name, $value) = explode(':', $header);
$response->setHeader($name, $value);
}
return $response;
}
}
@@ -40,6 +40,10 @@ public function getHeaders() {
return $this->headers;
}
public function setHeaders(array $headers) {
$this->headers = $headers;
}
/**
* @param $name
* @param $value
@@ -0,0 +1,33 @@
<?php
namespace Kibo\Phast\HTTP;
use Kibo\Phast\ValueObjects\URL;
class CURLClientTest extends \PHPUnit_Framework_TestCase {
public function setUp() {
parent::setUp();
if (!function_exists('curl_init')) {
$this->markTestSkipped("cURL is missing");
}
}
public function testGet() {
$client = new CURLClient();
$result = $client->get(URL::fromString('http://whatismyip.akamai.com/'));
$this->assertEquals(200, $result->getCode());
$this->assertRegExp('/^\d+\.\d+\.\d+\.\d+/', $result->getContent());
$this->assertArraySubset(['Content-Type' => 'text/html'], $result->getHeaders());
}
public function testPost() {
$client = new CURLClient();
$data = str_repeat('x', 5e6);
$result = $client->post(URL::fromString('http://optimize.phast.io/?service=images'), $data);
$this->assertNotContains("HTTP/", $result->getContent());
$this->assertNotEmpty($result->getHeaders());
}
}

0 comments on commit 864a0ba

Please sign in to comment.
You can’t perform that action at this time.