nicklasos
10/27/2016 - 3:36 PM

PHP HTTP Client

PHP HTTP Client

<?php
namespace App\Http;

use TestCase;

class ResponseTest extends TestCase
{
    public function testContent()
    {
        $response = new Response('Test content', []);

        $this->assertEquals('Test content', $response->content());
    }

    public function testHeaders()
    {
        $headers = [
            'HTTP/1.0 302 Found',
            'Cache-Control: private',
            'Content-Type: text/html; charset=UTF-8',
            'Location: http://www.google.com.ua/?gfe_rd=cr&ei=d2QQWOaZG7HG7gTR4JiQBA',
            'Content-Length: 262',
            'Date: Wed, 26 Oct 2016 08:08:23 GMT',
            'HTTP/1.0 200 OK',
            'Date: Wed, 26 Oct 2016 08:08:23 GMT',
            'Expires: -1',
            'Cache-Control: private, max-age=0',
            'Content-Type: text/html; charset=windows-1251',
            'P3P: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."',
            'Server: gws',
            'X-XSS-Protection: 1; mode=block',
            'X-Frame-Options: SAMEORIGIN',
            'Set-Cookie: NID=89=GYqmjY; expires=Thu, 27-Apr-2017 08:08:23 GMT; path=/; domain=.google.com.ua; HttpOnly',
            'Accept-Ranges: none',
            'Vary: Accept-Encoding',
        ];

        $response = new Response('content', $headers);

        $responseHeaders = $response->headers();

        $this->assertEquals('Wed, 26 Oct 2016 08:08:23 GMT', $responseHeaders['Date']);

        $this->assertEquals('HTTP/1.0 302 Found', $responseHeaders[0]);
        $this->assertEquals('HTTP/1.0 200 OK', $responseHeaders[1]);

        $this->assertEquals(200, $response->status());
    }

    public function testJson()
    {
        $response = new Response('{"foo": "bar"}', []);

        $this->assertEquals(['foo' => 'bar'], $response->json());
    }
}
<?php
namespace App\Http;

class Response
{
    /**
     * @var string
     */
    private $content;

    /**
     * @var array
     */
    private $headers;

    public function __construct(string $content, array $headers = [])
    {
        $this->content = $content;
        $this->headers = $this->parseHeaders($headers);
    }

    public function content(): string
    {
        return $this->content;
    }

    public function headers(): array
    {
        return $this->headers;
    }

    public function json(): array
    {
        return json_decode($this->content, true);
    }

    private function parseHeaders(array $headers): array
    {
        $head = [];

        foreach ($headers as $k => $v) {
            $t = explode(':', $v, 2);
            if (isset($t[1])) {
                $head[trim($t[0])] = trim($t[1]);
            } else {
                $head[] = $v;
                if (preg_match('#HTTP/[0-9\.]+\s+([0-9]+)#', $v, $out)) {
                    $head['response_code'] = intval($out[1]);
                }
            }
        }

        return $head;
    }

    /**
     * @return int|null
     */
    public function status()
    {
        return $this->headers['response_code'] ?? null;
    }
}
<?php
namespace App\Http;

/**
 * <code>
 * $client = new \Http\Client();
 *
 * $response = $client->get('http://google.com');
 *
 * $response->content(); // text response
 * $response->headers(); // array
 * $response->status(); // 200, etc…
 * $response->json(); // equals to json_decode($response->content(), true);
 *
 * // GET with headers:
 *
 * $client->get('http://foo', ['Content-Type' => 'application/json']);
 *
 * // POST
 *
 * $headers = ['Content-Type' => 'application/json’];
 * $body = json_encode([‘foo’ => ‘bar’]);
 *
 * $client->post('http://foo', $headers, $body);
 * </code>
 */
class Client
{
    public function post(string $url, array $headers = [], string $data = '', array $params = []): Response
    {
        $opts = [
            'http' => [
                'method' => 'POST',
                'header' => $this->headers($headers),
                'content' => $data,
            ],
        ];

        return $this->request($url, $opts, $params);
    }

    public function put(string $url, array $headers = [], string $data = '', array $params = []): Response
    {
        $opts = [
            'http' => [
                'method' => 'PUT',
                'header' => $this->headers($headers),
                'content' => $data,
            ],
        ];

        return $this->request($url, $opts, $params);
    }

    public function get(string $url, array $headers = [], array $params = []): Response
    {
        $opts = [
            'http' => [
                'method' => 'GET',
                'header' => $this->headers($headers),
            ],
        ];

        return $this->request($url, $opts, $params);
    }

    private function request(string $url, array $opts, array $params): Response
    {
//        $opts['http']['ignore_errors'] = true;

        $opts['http']['timeout'] = $params['timeout'] ?? 10;

        $content = file_get_contents($url, false, stream_context_create($opts));

        return new Response($content, $http_response_header);
    }

    private function headers(array $headers): string
    {
        $result = '';
        foreach ($headers as $key => $val) {
            $result .= $key . ': ' . $val . PHP_EOL;
        }

        return $result;
    }
}