diff --git a/src/pjdietz/WellRESTed/Response.php b/src/pjdietz/WellRESTed/Response.php index b90b749..3d09cb5 100644 --- a/src/pjdietz/WellRESTed/Response.php +++ b/src/pjdietz/WellRESTed/Response.php @@ -33,6 +33,8 @@ class Response extends Message implements ResponseInterface private $reasonPhrase; /** @var int HTTP status code */ private $statusCode; + /** @var string HTTP protocol and version*/ + private $protocol = "HTTP/1.1"; // ------------------------------------------------------------------------- @@ -79,56 +81,64 @@ class Response extends Message implements ResponseInterface } } - /** @param string $bodyFilePath Path to a file to read and output as the body */ + /** + * Provide the path to a file to output as the response body. + * + * @param string $bodyFilePath Filepath + */ public function setBodyFilePath($bodyFilePath) { $this->bodyFilePath = $bodyFilePath; } - /** @return string Path to a file to read and output as the body */ + /** + * Return the path to the file to output as the response body. + * + * @return string Filepath + */ public function getBodyFilePath() { return $this->bodyFilePath; } - /** @return string Portion of the status line explaining the status. */ + /** + * Return the portion of the status line explaining the status. + * + * @return string + */ public function getReasonPhrase() { return $this->reasonPhrase; } /** - * Assign an explaination for the status code. Not normally needed. + * Return true for status codes in the 1xx-3xx range. * - * @param string $statusCodeMessage + * @return bool */ - public function setReasonPhrase($statusCodeMessage) - { - $this->reasonPhrase = $statusCodeMessage; - } - - /** @return bool True if the status code is in the 2xx range. */ public function getSuccess() { - return $this->statusCode >= 200 && $this->statusCode < 300; + return $this->statusCode < 400; } - /** @return int */ + /** + * Return the HTTP status code for the response. + * + * @return int + */ public function getStatusCode() { return $this->statusCode; } - /** @return string HTTP status line, e.g. HTTP/1.1 200 OK. */ + /** + * Return the HTTP status line, e.g. HTTP/1.1 200 OK. + * + * @return string + */ public function getStatusLine() { - return sprintf( - '%s/%s %s %s', - strtoupper($this->protocol), - $this->protocolVersion, - $this->statusCode, - $this->reasonPhrase - ); + return $this->protocol . " " . $this->statusCode . " " . $this->reasonPhrase; } /** @@ -140,7 +150,7 @@ class Response extends Message implements ResponseInterface */ public function setStatusCode($statusCode, $reasonPhrase = null) { - $this->statusCode = (int)$statusCode; + $this->statusCode = (int) $statusCode; if (is_null($reasonPhrase)) { @@ -179,7 +189,7 @@ class Response extends Message implements ResponseInterface $text = 'Moved Permanently'; break; case 302: - $text = 'Moved Temporarily'; + $text = 'Found'; break; case 303: $text = 'See Other'; @@ -215,7 +225,7 @@ class Response extends Message implements ResponseInterface $text = 'Proxy Authentication Required'; break; case 408: - $text = 'Request Time-out'; + $text = 'Request Timeout'; break; case 409: $text = 'Conflict'; @@ -233,7 +243,7 @@ class Response extends Message implements ResponseInterface $text = 'Request Entity Too Large'; break; case 414: - $text = 'Request-URI Too Large'; + $text = 'Request-URI Too Long'; break; case 415: $text = 'Unsupported Media Type'; @@ -251,10 +261,10 @@ class Response extends Message implements ResponseInterface $text = 'Service Unavailable'; break; case 504: - $text = 'Gateway Time-out'; + $text = 'Gateway Timeout'; break; case 505: - $text = 'HTTP Version not supported'; + $text = 'HTTP Version Not Supported'; break; default: $text = 'Nonstandard'; @@ -306,14 +316,12 @@ class Response extends Message implements ResponseInterface private function outputBodyFile() { $handle = fopen($this->getBodyFilePath(), 'rb'); - if ($handle === false) { - return; - } - while (!feof($handle)) { - $buffer = fread($handle, self::CHUNK_SIZE); - print $buffer; - ob_flush(); - flush(); + if ($handle !== false) { + while (!feof($handle)) { + $buffer = fread($handle, self::CHUNK_SIZE); + print $buffer; + flush(); + } } } } diff --git a/test/RequestTest.php b/test/RequestTest.php index 2dd165a..cd66245 100644 --- a/test/RequestTest.php +++ b/test/RequestTest.php @@ -240,6 +240,25 @@ class RequestBuilderTest extends \PHPUnit_Framework_TestCase ); } + /** + * @dataProvider defaultPortProvider + */ + public function testDefaultPort($scheme, $port) + { + $rqst = new Request("http://localhost:9999"); + $rqst->setScheme($scheme); + $rqst->setPort(); + $this->assertEquals($port, $rqst->getPort()); + } + + public function defaultPortProvider() + { + return [ + ["http", 80], + ["https", 443] + ]; + } + /** * @dataProvider invalidSchemeProvider * @expectedException \UnexpectedValueException @@ -516,9 +535,9 @@ class RequestBuilderTest extends \PHPUnit_Framework_TestCase { return [ ["http://localhost:9991", [ - CURLOPT_FAILONERROR, true + CURLOPT_FAILONERROR, true, + CURLOPT_TIMEOUT_MS, 10 ]], ]; } - } diff --git a/test/ResponseTest.php b/test/ResponseTest.php new file mode 100644 index 0000000..8ea55b5 --- /dev/null +++ b/test/ResponseTest.php @@ -0,0 +1,189 @@ + "text/plain")); + } + + /** + * @dataProvider statusCodeProvider + */ + public function testStatusLine($statusCode, $reasonPhrase, $statusLine) + { + $resp = new Response(); + $resp->setStatusCode($statusCode, $reasonPhrase); + $this->assertEquals($statusLine, $resp->getStatusLine()); + } + + /** + * @dataProvider statusCodeProvider + */ + public function testReasonPhrase($statusCode, $reasonPhrase, $statusLine) + { + $resp = new Response(); + $resp->setStatusCode($statusCode, $reasonPhrase); + $this->assertEquals(substr($statusLine, 13), $resp->getReasonPhrase()); + } + + /** + * @dataProvider statusCodeProvider + */ + public function testSuccess($statusCode, $reasonPhrase, $statusLine) + { + $resp = new Response(); + $resp->setStatusCode($statusCode, $reasonPhrase); + if ($statusCode < 400) { + $this->assertTrue($resp->getSuccess()); + } else { + $this->assertFalse($resp->getSuccess()); + } + } + + public function statusCodeProvider() + { + return [ + [100, null, "HTTP/1.1 100 Continue"], + [101, null, "HTTP/1.1 101 Switching Protocols"], + [200, null, "HTTP/1.1 200 OK"], + [201, null, "HTTP/1.1 201 Created"], + [202, null, "HTTP/1.1 202 Accepted"], + [203, null, "HTTP/1.1 203 Non-Authoritative Information"], + [204, null, "HTTP/1.1 204 No Content"], + [205, null, "HTTP/1.1 205 Reset Content"], + [206, null, "HTTP/1.1 206 Partial Content"], + [300, null, "HTTP/1.1 300 Multiple Choices"], + [301, null, "HTTP/1.1 301 Moved Permanently"], + [302, null, "HTTP/1.1 302 Found"], + [303, null, "HTTP/1.1 303 See Other"], + [304, null, "HTTP/1.1 304 Not Modified"], + [305, null, "HTTP/1.1 305 Use Proxy"], + [400, null, "HTTP/1.1 400 Bad Request"], + [401, null, "HTTP/1.1 401 Unauthorized"], + [402, null, "HTTP/1.1 402 Payment Required"], + [403, null, "HTTP/1.1 403 Forbidden"], + [404, null, "HTTP/1.1 404 Not Found"], + [405, null, "HTTP/1.1 405 Method Not Allowed"], + [406, null, "HTTP/1.1 406 Not Acceptable"], + [407, null, "HTTP/1.1 407 Proxy Authentication Required"], + [408, null, "HTTP/1.1 408 Request Timeout"], + [409, null, "HTTP/1.1 409 Conflict"], + [410, null, "HTTP/1.1 410 Gone"], + [411, null, "HTTP/1.1 411 Length Required"], + [412, null, "HTTP/1.1 412 Precondition Failed"], + [413, null, "HTTP/1.1 413 Request Entity Too Large"], + [414, null, "HTTP/1.1 414 Request-URI Too Long"], + [415, null, "HTTP/1.1 415 Unsupported Media Type"], + [500, null, "HTTP/1.1 500 Internal Server Error"], + [501, null, "HTTP/1.1 501 Not Implemented"], + [502, null, "HTTP/1.1 502 Bad Gateway"], + [503, null, "HTTP/1.1 503 Service Unavailable"], + [504, null, "HTTP/1.1 504 Gateway Timeout"], + [505, null, "HTTP/1.1 505 HTTP Version Not Supported"], + [598, null, "HTTP/1.1 598 Nonstandard"], + [599, "Smelly", "HTTP/1.1 599 Smelly"] + ]; + } + + /** + * @dataProvider invalidReasonPhraseProvider + * @expectedException \InvalidArgumentException + */ + public function testInvalidReasonPhrase($statusCode, $reasonPhrase) + { + $resp = new Response(); + $resp->setStatusCode($statusCode, $reasonPhrase); + } + + public function invalidReasonPhraseProvider() + { + return [ + [599, false], + ["100", true], + ["*", []] + ]; + } + + public function testBodyFile() + { + $path = tempnam(sys_get_temp_dir(), "TST"); + $resp = new Response(); + $resp->setBodyFilePath($path); + $this->assertEquals($path, $resp->getBodyFilePath()); + unlink($path); + } + + public function testRespondBodyFile() + { + $path = tempnam(sys_get_temp_dir(), "TST"); + $body = "This is the body"; + + $f = fopen($path, "w"); + fwrite($f, $body); + fclose($f); + + $resp = new Response(); + $resp->setStatusCode(200); + $resp->setBodyFilePath($path); + + ob_start(); + ob_clean(); + @$resp->respond(); + $captured = ob_get_contents(); + ob_end_clean(); + + unlink($path); + + $this->assertEquals($captured, $body); + } + + public function testMissingRespondBodyFile() + { + $path = tempnam(sys_get_temp_dir(), "TST"); + + $resp = new Response(); + $resp->setStatusCode(200); + $resp->setBodyFilePath($path); + unlink($path); + + ob_start(); + ob_clean(); + @$resp->respond(); + $captured = ob_get_contents(); + ob_end_clean(); + + $this->assertEquals("", $captured); + } + + public function testRespondBody() + { + $body = "This is the body"; + + $resp = new Response(200, $body, array("Content-type" => "text/plain")); + ob_start(); + @$resp->respond(); + $captured = ob_get_contents(); + ob_end_clean(); + + $this->assertEquals($body, $captured); + } + + + +}