orbit/src/Orbit/Response.php

191 lines
4.3 KiB
PHP

<?php declare(strict_types=1);
namespace Orbit;
/**
* Response
*
* See the following website for description of the response spec
* https://gemini.circumlunar.space/docs/specification.html
*
* @package Orbit
*/
class Response
{
const STATUS_INPUT = 10;
const STATUS_SENSITIVE_INPUT = 11;
const STATUS_SUCCESS = 20;
const STATUS_REDIRECT_TEMPORARY = 30;
const STATUS_REDIRECT_PERMANENT = 31;
const STATUS_TEMPORARY_FAILURE = 40;
const STATUS_SERVER_UNAVAILABLE = 41;
const STATUS_CGI_ERROR = 42;
const STATUS_PROXY_ERROR = 43;
const STATUS_SLOW_DOWN = 44;
const STATUS_PERMANENT_FAILURE = 50;
const STATUS_NOT_FOUND = 51;
const STATUS_GONE = 52;
const STATUS_PROXY_REQUEST_REFUSED = 53;
const STATUS_BAD_REQUEST = 59;
const STATUS_CLIENT_CERTIFICATE_REQUIRED = 60;
const STATUS_CERTIFICATE_NOT_AUTHORISED = 61;
const STATUS_CERTIFICATE_NOT_VALID = 62;
public $status = "";
public $meta = "";
public $body = "";
public $filepath;
/**
* Constructor
*
* @param string $status
* @param string $meta
* @return void
*/
public function __construct($status = "", $meta = "")
{
$this->status = $status;
$this->meta = $meta;
}
/**
* Get a header to be sent to client
*
* @return string
*/
public function getHeader(): string
{
return sprintf("%s %s\r\n", $this->status, $this->meta);
}
/**
* Send response body to client
*
* @param resource $client
* @return int|false Number of bytes written
*/
public function send($client): int
{
if (!is_resource($client)) {
throw new \Exception("Invalid resource to write to");
}
$result = fwrite($client, $this->getHeader());
if (!$result) {
throw new \Exception("Failed to write to client");
}
if ($this->filepath) {
if (is_dir($this->filepath)) {
throw new \Exception("Cannot serve directory '{$this->filepath}'");
}
if (!file_exists($this->filepath)) {
throw new \Exception("Error reading file '{$this->filepath}'");
}
$fp = fopen($this->filepath, "rb");
if (false === $fp) {
throw new \Exception("Cannot read file '{$this->filepath}'");
}
$size = filesize($this->filepath);
$result = 1;
while (!feof($fp) && $result) {
// If the client cancels, bail out before trying large files
// So, result will be 0 if the client cancels (broken socket)
$result = fwrite($client, fread($fp, 8192));
}
fclose($fp);
return $size;
} else {
$body = $this->getBody();
fwrite($client, $body);
return mb_strlen($body);
}
}
/**
* Set response body
*
* @param string $body
* @return void
*/
public function setBody(string $body = ''): void
{
$this->body = $body;
}
/**
* Get response body
*
* @return string
*/
public function getBody(): string
{
if ($this->filepath) {
$this->body = file_get_contents($this->filepath);
}
return $this->body;
}
/**
* Set static file
*
* Indicates this response should consist of a static file on disk
*
* @param mixed $filepath
* @return void
*/
public function setStaticFile(string $filepath): void
{
$this->filepath = $filepath;
}
/**
* Set response status
*
* @param int $status
* @return void
*/
public function setStatus(int $status): void
{
$this->status = $status;
}
/**
* Get status
*
* @return int
*/
public function getStatus(): int
{
return $this->status;
}
/**
* Set response meta value
*
* @param string $meta
* @return void
*/
public function setMeta($meta): void
{
$this->meta = $meta;
}
/**
* Get meta
*
* @return string Meta value
*/
public function getMeta(): string
{
return $this->meta;
}
}