Skip to content

Instantly share code, notes, and snippets.

@jm42
Created October 8, 2014 15:07
Show Gist options
  • Save jm42/f6217e67976e2ca45732 to your computer and use it in GitHub Desktop.
Save jm42/f6217e67976e2ca45732 to your computer and use it in GitHub Desktop.
HTTP
<?php
class Request {
const METHOD_GET = 'GET';
const METHOD_POST = 'POST';
const METHOD_HEAD = 'HEAD';
private $method;
private $uri;
private $headers;
private $body;
private $query;
private $form;
private $files;
private $cookie;
public function __construct($method, $uri, array $headers=null, $body=null,
array $query=null, array $form=null,
array $files=null, array $cookie=null) {
/* An HTTP request */
$method = strtoupper($method);
if (!defined('static::METHOD_' . $method)) {
throw new \InvalidArgumentException(
sprintf('Invalid method, %s given', $method)
);
}
$headers = $headers ?: array();
if ($query === null) {
$queryString = parse_url($uri, PHP_URL_QUERY);
$query = array();
if ($queryString !== null)
parse_str(html_entity_decode($queryString), $query);
unset($queryString);
}
$formFiles = array();
if ($form === null) {
$form = array();
if ($body !== null && isset($headers['Content-Type'])) {
switch ($headers['Content-Type']) {
case 'application/x-www-form-urlencoded':
parse_str($body, $form);
break;
case 'multipart/form-data':
// TODO: Parse multipart body.
// Fill $form and $formFiles.
default:
throw new \LogicException('Unsupported content type');
}
}
}
if ($files === null) {
$files = $formFiles;
}
if ($cookie === null) {
$cookie = array();
if (isset($headers['Cookie'])) {
// TODO: Parse "Cookie" header.
}
}
$this->method = $method;
$this->uri = $uri;
$this->headers = $headers;
$this->body = $body;
$this->query = $query;
$this->form = $form;
$this->files = $files;
$this->cookie = $cookie;
}
public function __get($key) {
return $this->$key;
}
}
class Response {
private $status;
private $headers;
private $body;
public function __construct($status=200, array $headers=null, $body=null) {
/* An HTTP response */
$status = intval($status);
if ($status < 100 || $status > 599) {
throw new \InvalidArgumentException(
sprintf('Invalid status code, %d given', $status)
);
}
$headers = $headers ?: array();
$this->status = $status;
$this->headers = $headers;
$this->body = $body;
}
public function __get($key) {
return $this->$key;
}
public function send() {
if (headers_sent()) {
return;
}
http_response_code($this->status);
foreach ($this->headers as $key => $value) {
if (is_array($value)) {
foreach ($value as $content) {
header($key . ': ' . $content, false);
}
continue;
}
header($key . ': ' . $value);
}
if ($this->body !== null) {
echo $this->body;
}
}
}
<?php
class Aix_HTTP_RequestTest extends \PHPUnit_Framework_TestCase {
public function testConstruct() {
$request = new Request(Request::METHOD_GET, '/foo');
$this->assertEquals('GET', $request->method);
$this->assertEquals('/foo', $request->uri);
$this->assertEquals(array(), $request->headers);
$this->assertEquals(null, $request->body);
$request = new Request('pOsT', '/bar',
array('Host' => 'localhost:80'), 'name=John+Doe&age=42');
$this->assertEquals('POST', $request->method);
$this->assertEquals('localhost:80', $request->headers['Host']);
$this->assertEquals('name=John+Doe&age=42', $request->body);
}
public function testConstructQuery() {
$request = new Request(Request::METHOD_GET, '/foo?name=John&arr[]=1');
$this->assertEquals('John', $request->query['name']);
$this->assertEquals('1', $request->query['arr'][0]);
}
public function testConstructForm() {
$request = new Request(Request::METHOD_POST, '/',
array('Content-Type' => 'application/x-www-form-urlencoded'),
'name=John&arr[]=1');
$this->assertEquals('John', $request->form['name']);
$this->assertEquals('1', $request->form['arr'][0]);
}
/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Invalid method, FOOBAR given
*/
public function testInvalidMethod() {
new Request('FOOBAR', '/');
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Unsupported content type
*/
public function testUnsupportedContentTypeToDecodeBody() {
new Request('POST', '/', array('Content-Type' => 'application/xml'),
'<?xml version="1.0"?><catalog></catalog>');
}
}
class Aix_HTTP_ResponseTest extends \PHPUnit_Framework_TestCase {
public function testConstruct() {
$response = new Response();
$this->assertEquals(200, $response->status);
$this->assertEquals(array(), $response->headers);
$this->assertNull($response->body);
$response = new Response(404,
array('Content-Type' => 'text/plain; charset=utf-8'), 'NOT FOUND');
$this->assertEquals(404, $response->status);
$this->assertArrayHasKey('Content-Type', $response->headers);
$this->assertContains('text/plain; charset=utf-8', $response->headers);
$this->assertEquals('NOT FOUND', $response->body);
}
/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Invalid status code, 600 given
*/
public function testInvalidStatusCode() {
new Response(600);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment