mirror of
https://github.com/LBRYFoundation/lbry.com.git
synced 2025-08-23 09:37:26 +00:00
382 lines
11 KiB
PHP
382 lines
11 KiB
PHP
<?php
|
|
|
|
class Response
|
|
{
|
|
const HEADER_STATUS = 'Status';
|
|
const HEADER_LOCATION = 'Location';
|
|
|
|
const HEADER_CACHE_CONTROL = 'Cache-Control';
|
|
const HEADER_LAST_MODIFIED = 'Last-Modified';
|
|
const HEADER_ETAG = 'Etag';
|
|
|
|
const HEADER_CONTENT_TYPE = 'Content-Type';
|
|
const HEADER_CONTENT_LENGTH = 'Content-Length';
|
|
const HEADER_CONTENT_DISPOSITION = 'Content-Disposition';
|
|
const HEADER_CONTENT_TYPE_OPTIONS = 'X-Content-Type-Options';
|
|
const HEADER_CONTENT_ENCODING = 'Content-Encoding';
|
|
const HEADER_CROSS_ORIGIN = 'Access-Control-Allow-Origin';
|
|
|
|
protected static $metaDescription = '';
|
|
protected static $metaTitle = '';
|
|
protected static $jsCalls = [];
|
|
protected static $assets = [
|
|
'js' => [
|
|
'/js/jquery-3.3.1.min.js',
|
|
'/js/global.js'
|
|
],
|
|
'css' => ['/css/all.css']
|
|
];
|
|
protected static $headers = [];
|
|
protected static $headersSent = false;
|
|
protected static $content = '';
|
|
protected static $contentSent = false;
|
|
protected static $isHeadersOnly = false;
|
|
protected static $gzipResponseContent = true;
|
|
protected static $metaImages = [];
|
|
protected static $facebookAnalyticsType = "PageView";
|
|
|
|
public static function setMetaDescription($description)
|
|
{
|
|
static::$metaDescription = $description;
|
|
}
|
|
|
|
public static function addMetaImage($url)
|
|
{
|
|
static::$metaImages[] = $url;
|
|
}
|
|
|
|
public static function addMetaImages(array $urls)
|
|
{
|
|
foreach ($urls as $url) {
|
|
static::addMetaImage($url);
|
|
}
|
|
}
|
|
|
|
public static function getMetaDescription()
|
|
{
|
|
return static::$metaDescription ?: 'A Content Revolution';
|
|
}
|
|
|
|
public static function getMetaImages()
|
|
{
|
|
return static::$metaImages ?: [Request::getHostAndProto() . '/img/lbry-green-meta-1200x900.png'];
|
|
}
|
|
|
|
public static function setMetaTitle($title)
|
|
{
|
|
static::$metaTitle = $title;
|
|
}
|
|
|
|
public static function getMetaTitle()
|
|
{
|
|
return static::$metaTitle;
|
|
}
|
|
|
|
public static function guessMetaTitle($content)
|
|
{
|
|
$title = '';
|
|
preg_match_all('/<h(1|2)[^>]*>([^<]+)</', $content, $titleMatches);
|
|
foreach ($titleMatches[1] as $matchIndex => $headerValue) {
|
|
if ($headerValue == '1' || !$title) {
|
|
$title = $titleMatches[2][$matchIndex];
|
|
if ($headerValue == '1') {
|
|
return $title;
|
|
}
|
|
}
|
|
}
|
|
return $title;
|
|
}
|
|
|
|
public static function getJsCalls()
|
|
{
|
|
return static::$jsCalls;
|
|
}
|
|
|
|
public static function jsOutputCallback($js)
|
|
{
|
|
static::$jsCalls[] = $js;
|
|
return '';
|
|
}
|
|
|
|
public static function addJsAsset($src)
|
|
{
|
|
static::$assets['js'][$src] = $src;
|
|
}
|
|
|
|
public static function addCssAsset($src)
|
|
{
|
|
static::$assets['css'][$src] = $src;
|
|
}
|
|
|
|
public static function getJsAssets()
|
|
{
|
|
return static::$assets['js'];
|
|
}
|
|
|
|
public static function getCssAssets()
|
|
{
|
|
return static::$assets['css'];
|
|
}
|
|
|
|
public static function setCssAssets(array $assets = [])
|
|
{
|
|
static::$assets['css'] = $assets;
|
|
}
|
|
public static function setGzipResponseContent($gzip = true)
|
|
{
|
|
static::$gzipResponseContent = $gzip;
|
|
}
|
|
|
|
public static function gzipContentIfNotDisabled()
|
|
{
|
|
if (static::$gzipResponseContent) {
|
|
$content = static::getContent();
|
|
if (strlen($content) > 256) { // not worth it for really short content
|
|
$compressed = gzencode($content, 1);
|
|
static::setContent($compressed);
|
|
static::setHeader(static::HEADER_CONTENT_LENGTH, strlen($compressed));
|
|
static::setHeader(static::HEADER_CONTENT_ENCODING, 'gzip');
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function send()
|
|
{
|
|
static::sendHeaders();
|
|
static::sendContent();
|
|
}
|
|
|
|
public static function setContent(string $content)
|
|
{
|
|
static::$content = $content;
|
|
}
|
|
|
|
public static function getContent(): string
|
|
{
|
|
return static::$content;
|
|
}
|
|
|
|
public static function sendContent()
|
|
{
|
|
if (static::$contentSent) {
|
|
throw new LogicException('Content has already been sent. It cannot be sent twice');
|
|
}
|
|
|
|
if (!static::$isHeadersOnly) {
|
|
echo static::$content;
|
|
}
|
|
|
|
static::$contentSent = true;
|
|
}
|
|
|
|
public static function setIsHeadersOnly(bool $isHeadersOnly = true)
|
|
{
|
|
static::$isHeadersOnly = $isHeadersOnly;
|
|
}
|
|
|
|
public static function setDownloadHttpHeaders($name, $type = null, $size = null, $noSniff = true)
|
|
{
|
|
static::setBinaryHttpHeaders($type, $size, $noSniff);
|
|
static::setHeader('Content-Disposition', 'attachment;filename=' . $name);
|
|
}
|
|
|
|
public static function setBinaryHttpHeaders($type, $size = null, $noSniff = true)
|
|
{
|
|
static::setGzipResponseContent(false); // in case its already compressed
|
|
static::setHeaders(array_filter([
|
|
static::HEADER_CONTENT_TYPE => $type,
|
|
static::HEADER_CONTENT_LENGTH => $size ?: null,
|
|
static::HEADER_CONTENT_TYPE_OPTIONS => $noSniff ? 'nosniff' : null,
|
|
]));
|
|
}
|
|
|
|
public static function setContentEtag()
|
|
{
|
|
static::setHeader(static::HEADER_ETAG, md5(static::getContent()));
|
|
}
|
|
|
|
public static function enableHttpCache(int $seconds = 300)
|
|
{
|
|
static::addCacheControlHeader('max-age', $seconds);
|
|
static::setHeader('Pragma', 'public');
|
|
}
|
|
|
|
public static function addCacheControlHeader(string $name, $value = null)
|
|
{
|
|
$cacheControl = static::getHeader(static::HEADER_CACHE_CONTROL);
|
|
$currentHeaders = [];
|
|
if ($cacheControl) {
|
|
foreach (preg_split('/\s*,\s*/', $cacheControl) as $tmp) {
|
|
$tmp = explode('=', $tmp);
|
|
$currentHeaders[$tmp[0]] = $tmp[1] ?? null;
|
|
}
|
|
}
|
|
$currentHeaders[strtr(strtolower($name), '_', '-')] = $value;
|
|
|
|
$headers = [];
|
|
foreach ($currentHeaders as $key => $currentVal) {
|
|
$headers[] = $key . ($currentVal !== null ? '=' . $currentVal : '');
|
|
}
|
|
|
|
static::setHeader(static::HEADER_CACHE_CONTROL, implode(', ', $headers));
|
|
}
|
|
|
|
public static function setHeader($name, $value)
|
|
{
|
|
static::$headers[$name] = $value;
|
|
}
|
|
|
|
public static function setHeaders($headers, $overwrite = true)
|
|
{
|
|
foreach ($headers as $name => $value) {
|
|
if ($overwrite || !static::getHeader($name)) {
|
|
static::setHeader($name, $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function getHeader($name, $default = null)
|
|
{
|
|
return static::$headers[$name] ?? $default;
|
|
}
|
|
|
|
public static function getHeaders(): array
|
|
{
|
|
return static::$headers;
|
|
}
|
|
|
|
public static function setStatus($status)
|
|
{
|
|
static::setHeader(static::HEADER_STATUS, $status);
|
|
}
|
|
|
|
public static function setDefaultSecurityHeaders()
|
|
{
|
|
$defaultHeaders = [
|
|
'Content-Security-Policy' => "frame-ancestors 'none'",
|
|
'X-Frame-Options' => 'DENY',
|
|
'X-XSS-Protection' => '1',
|
|
];
|
|
|
|
if (IS_PRODUCTION) {
|
|
$defaultHeaders['Strict-Transport-Security'] = 'max-age=31536000';
|
|
}
|
|
|
|
static::setHeaders($defaultHeaders, false);
|
|
}
|
|
|
|
public static function sendHeaders()
|
|
{
|
|
if (static::$headersSent) {
|
|
throw new LogicException('Headers have already been sent. They cannot be sent twice');
|
|
}
|
|
|
|
if (!static::getHeader(static::HEADER_CONTENT_TYPE)) {
|
|
static::setHeader(static::HEADER_CONTENT_TYPE, 'text/html');
|
|
}
|
|
|
|
$headers = static::getHeaders();
|
|
|
|
if (isset($headers[static::HEADER_STATUS])) {
|
|
$status = 'HTTP/1.0 ' . $headers[static::HEADER_STATUS] . ' ' . static::getStatusTextForCode($headers[static::HEADER_STATUS]);
|
|
header($status);
|
|
|
|
if (substr(php_sapi_name(), 0, 3) == 'cgi') {
|
|
// fastcgi servers cannot send this status information because it was sent by them already due to the HTT/1.0 line
|
|
// so we can safely unset them. see ticket #3191
|
|
unset($headers[static::HEADER_STATUS]);
|
|
}
|
|
}
|
|
|
|
foreach ($headers as $name => $value) {
|
|
header($name . ': ' . $value);
|
|
}
|
|
|
|
static::$headersSent = true;
|
|
}
|
|
|
|
public static function getStatusTextForCode($code)
|
|
{
|
|
$statusTexts = [
|
|
'100' => 'Continue',
|
|
'101' => 'Switching Protocols',
|
|
'200' => 'OK',
|
|
'201' => 'Created',
|
|
'202' => 'Accepted',
|
|
'203' => 'Non-Authoritative Information',
|
|
'204' => 'No Content',
|
|
'205' => 'Reset Content',
|
|
'206' => 'Partial Content',
|
|
'300' => 'Multiple Choices',
|
|
'301' => 'Moved Permanently',
|
|
'302' => 'Found',
|
|
'303' => 'See Other',
|
|
'304' => 'Not Modified',
|
|
'305' => 'Use Proxy',
|
|
'306' => '(Unused)',
|
|
'307' => 'Temporary Redirect',
|
|
'400' => 'Bad Request',
|
|
'401' => 'Unauthorized',
|
|
'402' => 'Payment Required',
|
|
'403' => 'Forbidden',
|
|
'404' => 'Not Found',
|
|
'405' => 'Method Not Allowed',
|
|
'406' => 'Not Acceptable',
|
|
'407' => 'Proxy Authentication Required',
|
|
'408' => 'Request Timeout',
|
|
'409' => 'Conflict',
|
|
'410' => 'Gone',
|
|
'411' => 'Length Required',
|
|
'412' => 'Precondition Failed',
|
|
'413' => 'Request Entity Too Large',
|
|
'414' => 'Request-URI Too Long',
|
|
'415' => 'Unsupported Media Type',
|
|
'416' => 'Requested Range Not Satisfiable',
|
|
'417' => 'Expectation Failed',
|
|
'419' => 'Authentication Timeout',
|
|
'422' => 'Unprocessable Entity',
|
|
'426' => 'Upgrade Required',
|
|
'429' => 'Too Many Requests',
|
|
'500' => 'Internal Server Error',
|
|
'501' => 'Not Implemented',
|
|
'502' => 'Bad Gateway',
|
|
'503' => 'Service Unavailable',
|
|
'504' => 'Gateway Timeout',
|
|
'505' => 'HTTP Version Not Supported',
|
|
];
|
|
|
|
return $statusTexts[$code] ?? null;
|
|
}
|
|
|
|
public static function setFacebookPixelAnalyticsType($type)
|
|
{
|
|
static::$facebookAnalyticsType = $type;
|
|
}
|
|
|
|
public static function getFacebookPixelAnalyticsType()
|
|
{
|
|
return static::$facebookAnalyticsType;
|
|
}
|
|
|
|
protected static function normalizeHeaderName($name): string
|
|
{
|
|
return preg_replace_callback(
|
|
'/\-(.)/',
|
|
function ($matches) {
|
|
return '-' . strtoupper($matches[1]);
|
|
},
|
|
strtr(ucfirst(strtolower($name)), '_', '-')
|
|
);
|
|
}
|
|
|
|
|
|
// public static function addBodyCssClass($classOrClasses)
|
|
// {
|
|
// static::$bodyCssClasses = array_unique(array_merge(static::$bodyCssClasses, (array)$classOrClasses));
|
|
// }
|
|
//
|
|
// public static function getBodyCssClasses()
|
|
// {
|
|
// return static::$bodyCssClasses;
|
|
// }
|
|
}
|