191 lines
4.3 KiB
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;
|
|
}
|
|
}
|