mirror of
https://github.com/LBRYFoundation/lbry.com.git
synced 2025-08-23 17:47:26 +00:00
add response class, caching
This commit is contained in:
parent
934c0d92ef
commit
77480f029f
16 changed files with 354 additions and 137 deletions
|
@ -34,6 +34,6 @@ class Actions
|
|||
'okhttp', 'python'
|
||||
];
|
||||
|
||||
return preg_match('/(' . join('|', $bots) . ')/i', $_SERVER['HTTP_USER_AGENT']);
|
||||
return preg_match('/(' . join('|', $bots) . ')/i', Request::getUserAgent());
|
||||
}
|
||||
}
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
class Controller
|
||||
{
|
||||
const HEADER_STATUS = 'Status';
|
||||
|
||||
public static function dispatch($uri)
|
||||
{
|
||||
try
|
||||
|
@ -11,29 +9,19 @@ class Controller
|
|||
$viewAndParams = static::execute($uri);
|
||||
$viewTemplate = $viewAndParams[0];
|
||||
$viewParameters = isset($viewAndParams[1]) ? $viewAndParams[1] : [];
|
||||
$headers = isset($viewAndParams[2]) ? $viewAndParams[2] : [];
|
||||
|
||||
$defaultHeaders = [
|
||||
'Content-Security-Policy' => "frame-ancestors 'none'",
|
||||
'X-Frame-Options' => 'DENY',
|
||||
'X-XSS-Protection'=> '1',
|
||||
];
|
||||
|
||||
if (IS_PRODUCTION)
|
||||
if (!IS_PRODUCTION && isset($viewAndParams[2]))
|
||||
{
|
||||
$defaultHeaders['Strict-Transport-Security'] = 'max-age=31536000';
|
||||
throw new Exception('use response::setheader instead of returning headers');
|
||||
}
|
||||
|
||||
static::sendHeaders(array_merge($defaultHeaders, $headers));
|
||||
|
||||
if ($viewTemplate === null)
|
||||
{
|
||||
return '';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$viewTemplate)
|
||||
{
|
||||
throw new LogicException('All execute methods must return a template.');
|
||||
throw new LogicException('All execute methods must return a template or NULL.');
|
||||
}
|
||||
|
||||
$layout = !(isset($viewParameters['_no_layout']) && $viewParameters['_no_layout']);
|
||||
|
@ -44,7 +32,9 @@ class Controller
|
|||
|
||||
$content = View::render($viewTemplate, $viewParameters + ['fullPage' => true]);
|
||||
|
||||
echo $layout ? View::render('layout/basic', ['content' => $content] + $layoutParams) : $content;
|
||||
Response::setContent($layout ? View::render('layout/basic', ['content' => $content] + $layoutParams) : $content);
|
||||
Response::setDefaultSecurityHeaders();
|
||||
Response::send();
|
||||
}
|
||||
catch (StopException $e)
|
||||
{
|
||||
|
@ -99,6 +89,7 @@ class Controller
|
|||
$newsPattern = '#^' . ContentActions::URL_NEWS . '(/|$)#';
|
||||
if (preg_match($newsPattern, $uri))
|
||||
{
|
||||
Response::enableHttpCache(180);
|
||||
$slug = preg_replace($newsPattern, '', $uri);
|
||||
if ($slug == ContentActions::RSS_SLUG)
|
||||
{
|
||||
|
@ -110,6 +101,7 @@ class Controller
|
|||
$faqPattern = '#^' . ContentActions::URL_FAQ . '(/|$)#';
|
||||
if (preg_match($faqPattern, $uri))
|
||||
{
|
||||
Response::enableHttpCache(180);
|
||||
$slug = preg_replace($faqPattern, '', $uri);
|
||||
return $slug ? ContentActions::executeFaqPost($uri) : ContentActions::executeFaq();
|
||||
}
|
||||
|
@ -117,6 +109,7 @@ class Controller
|
|||
$bountyPattern = '#^' . BountyActions::URL_BOUNTY_LIST . '(/|$)#';
|
||||
if (preg_match($bountyPattern, $uri))
|
||||
{
|
||||
Response::enableHttpCache(180);
|
||||
$slug = preg_replace($bountyPattern, '', $uri);
|
||||
return $slug ? BountyActions::executeShow($uri) : BountyActions::executeList($uri);
|
||||
}
|
||||
|
@ -131,11 +124,13 @@ class Controller
|
|||
$noSlashUri = ltrim($uri, '/');
|
||||
if (View::exists('page/' . $noSlashUri))
|
||||
{
|
||||
Response::enableHttpCache(180);
|
||||
return ['page/' . $noSlashUri, []];
|
||||
}
|
||||
else
|
||||
{
|
||||
return ['page/404', [], [static::HEADER_STATUS => 404]];
|
||||
Response::setStatus(404);
|
||||
return ['page/404', []];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,88 +143,13 @@ class Controller
|
|||
|
||||
$url = str_replace('&', '&', $url);
|
||||
|
||||
$headers = [static::HEADER_STATUS => $statusCode];
|
||||
|
||||
Response::setStatus($statusCode);
|
||||
|
||||
if ($statusCode == 201 || ($statusCode >= 300 && $statusCode < 400))
|
||||
{
|
||||
$headers['Location'] = $url;
|
||||
Response::setHeader(Response::HEADER_LOCATION, $url);
|
||||
}
|
||||
|
||||
return ['internal/redirect', ['url' => $url], $headers];
|
||||
}
|
||||
|
||||
protected static function sendHeaders(array $headers)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 isset($statusTexts[$code]) ? $statusTexts[$code] : null;
|
||||
return ['internal/redirect', ['url' => $url]];
|
||||
}
|
||||
}
|
||||
|
|
59
controller/Request.class.php
Normal file
59
controller/Request.class.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
class Request
|
||||
{
|
||||
const GET = 'GET';
|
||||
const POST = 'POST';
|
||||
const HEAD = 'HEAD';
|
||||
const OPTIONS = 'OPTIONS';
|
||||
|
||||
protected static $method;
|
||||
|
||||
public static function getMethod(): string
|
||||
{
|
||||
if (!static::$method)
|
||||
{
|
||||
$method = isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : null;
|
||||
static::$method = in_array($method, [static::GET, static::POST, static::HEAD, static::OPTIONS]) ? $method : static::GET;
|
||||
}
|
||||
return static::$method;
|
||||
}
|
||||
|
||||
public static function isGet(): bool
|
||||
{
|
||||
return static::getMethod() == static::GET;
|
||||
}
|
||||
|
||||
public static function isPost(): bool
|
||||
{
|
||||
return static::getMethod() == static::POST;
|
||||
}
|
||||
|
||||
public static function isCacheableMethod(): bool
|
||||
{
|
||||
return in_array(static::getMethod(), [static::GET, static::HEAD]);
|
||||
}
|
||||
|
||||
public static function getOriginalIp(): string
|
||||
{
|
||||
return isset($_SERVER['HTTP_X_FORWARDED_FOR']) ?
|
||||
$_SERVER['HTTP_X_FORWARDED_FOR'] :
|
||||
(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '');
|
||||
}
|
||||
|
||||
public static function getUserAgent(): string
|
||||
{
|
||||
return isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
|
||||
}
|
||||
|
||||
public static function getHost(): string
|
||||
{
|
||||
// apparently trailing period is legal: http://www.dns-sd.org/TrailingDotsInDomainNames.html
|
||||
return isset($_SERVER['HTTP_HOST']) ? rtrim($_SERVER['HTTP_HOST'], '.') : '';
|
||||
}
|
||||
|
||||
public static function getRelativeUri(): string
|
||||
{
|
||||
return isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ class ContentActions extends Actions
|
|||
|
||||
public static function executeHome(): array
|
||||
{
|
||||
Response::enableHttpCache(180);
|
||||
return ['page/home', [
|
||||
'totalUSD' => CreditApi::getTotalDollarSales(),
|
||||
'totalPeople' => CreditApi::getTotalPeople()
|
||||
|
@ -70,11 +71,10 @@ class ContentActions extends Actions
|
|||
public static function executeRss(): array
|
||||
{
|
||||
$posts = Post::find(static::VIEW_FOLDER_NEWS, Post::SORT_DATE_DESC);
|
||||
Response::setHeader(Response::HEADER_CONTENT_TYPE, 'text/xml; charset=utf-8');
|
||||
return ['content/rss', [
|
||||
'posts' => array_slice($posts, 0, 10),
|
||||
'_no_layout' => true
|
||||
], [
|
||||
'Content-Type' => 'text/xml; charset=utf-8'
|
||||
]];
|
||||
}
|
||||
|
||||
|
@ -161,14 +161,12 @@ class ContentActions extends Actions
|
|||
|
||||
$zip->close();
|
||||
|
||||
Response::enableHttpCache(180);
|
||||
Response::setDownloadHttpHeaders($zipFileName, 'application/zip', filesize($zipPath));
|
||||
|
||||
return ['internal/zip', [
|
||||
'_no_layout' => true,
|
||||
'zipPath' => $zipPath
|
||||
], [
|
||||
'Content-Disposition' => 'attachment;filename=' . $zipFileName,
|
||||
'X-Content-Type-Options' => 'nosniff',
|
||||
'Content-Type' => 'application/zip',
|
||||
'Content-Length' => filesize($zipPath),
|
||||
]];
|
||||
}
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ class DownloadActions extends Actions
|
|||
protected static function guessOs()
|
||||
{
|
||||
//if exact OS is requested, use that
|
||||
$uri = strtok($_SERVER['REQUEST_URI'], '?');
|
||||
$uri = strtok(Request::getRelativeUri(), '?');
|
||||
foreach (static::getOses() as $os => $osChoice)
|
||||
{
|
||||
if ($osChoice[0] == $uri)
|
||||
|
@ -184,7 +184,7 @@ class DownloadActions extends Actions
|
|||
}
|
||||
|
||||
//otherwise guess from UA
|
||||
$ua = $_SERVER['HTTP_USER_AGENT'];
|
||||
$ua = Request::getUserAgent();
|
||||
if (stripos($ua, 'OS X') !== false)
|
||||
{
|
||||
return strpos($ua, 'iPhone') !== false || stripos($ua, 'iPad') !== false ? static::OS_IOS : static::OS_OSX;
|
||||
|
|
|
@ -11,7 +11,7 @@ class MailActions extends Actions
|
|||
{
|
||||
$nextUrl = isset($_POST['returnUrl']) && $_POST['returnUrl'] ? $_POST['returnUrl'] : '/join-list';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST')
|
||||
if (!Request::isPost())
|
||||
{
|
||||
return Controller::redirect($nextUrl);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class MailActions extends Actions
|
|||
public static function prepareJoinListPartial(array $vars)
|
||||
{
|
||||
$vars['listSig'] = md5(serialize($vars));
|
||||
$vars += ['btnClass' => 'btn-primary', 'returnUrl' => $_SERVER['REQUEST_URI']];
|
||||
$vars += ['btnClass' => 'btn-primary', 'returnUrl' => Request::getRelativeUri()];
|
||||
|
||||
if (Session::get(Session::KEY_LIST_SUB_SIGNATURE) == $vars['listSig'])
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ class NavActions extends Actions
|
|||
|
||||
public static function getNavUri()
|
||||
{
|
||||
return static::$navUri ?: $_SERVER['REQUEST_URI'];
|
||||
return static::$navUri ?: Request::getRelativeUri();
|
||||
}
|
||||
|
||||
public static function prepareFooterPartial(array $vars)
|
||||
|
|
|
@ -24,7 +24,7 @@ class i18n
|
|||
{
|
||||
if ($culture === null)
|
||||
{
|
||||
$urlTokens = $_SERVER['HTTP_HOST'] ? explode('.', $_SERVER['HTTP_HOST']) : [];
|
||||
$urlTokens = Request::getHost() ? explode('.', Request::getHost()) : [];
|
||||
$code = $urlTokens ? reset($urlTokens) : 'en';
|
||||
switch($code)
|
||||
{
|
||||
|
|
|
@ -61,8 +61,8 @@ class Prefinery
|
|||
if (!$user)
|
||||
{
|
||||
// dont record ip for lbry.io addresses, for testing
|
||||
$ip = isset($_SERVER['REMOTE_ADDR']) && !preg_match('/@lbry\.io$/', $email) ? $_SERVER['REMOTE_ADDR'] : null;
|
||||
$ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
|
||||
$ip = !preg_match('/@lbry\.io$/', $email) ? Request::getOriginalIp() : null;
|
||||
$ua = Request::getUserAgent();
|
||||
$user = Prefinery::createTester(array_filter([
|
||||
'email' => $email,
|
||||
'status' => $inviteCode ? static::STATE_ACTIVE: static::STATE_APPLIED, # yes, has to be ACTIVE to validate invite code
|
||||
|
|
|
@ -13,7 +13,7 @@ class Slack
|
|||
$slackErrorNotificationUrl = Config::get('slack_error_notification_url');
|
||||
if ($slackErrorNotificationUrl)
|
||||
{
|
||||
Curl::post($slackErrorNotificationUrl, ['text' => '<!everyone> ' . $_SERVER['REQUEST_URI'] . "\n" . $e], ['json_data' => true]);
|
||||
Curl::post($slackErrorNotificationUrl, ['text' => '<!everyone> ' . Request::getRelativeUri() . "\n" . $e], ['json_data' => true]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ class Post
|
|||
$cover = $this->getCover();
|
||||
if ($cover)
|
||||
{
|
||||
$urls[] = 'https://' . $_SERVER['SERVER_NAME'] . '/img/blog-covers/' . $cover;
|
||||
$urls[] = 'https://' . Request::getHost() . '/img/blog-covers/' . $cover;
|
||||
}
|
||||
|
||||
$matches = [];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Description of Response
|
||||
*
|
||||
|
@ -6,7 +7,20 @@
|
|||
*/
|
||||
class Response
|
||||
{
|
||||
protected static $metaDescription = '',
|
||||
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';
|
||||
|
||||
protected static
|
||||
$metaDescription = '',
|
||||
$metaTitle = '',
|
||||
$jsCalls = [],
|
||||
$assets = [
|
||||
|
@ -16,6 +30,11 @@ class Response
|
|||
],
|
||||
'css' => []
|
||||
],
|
||||
$headers = [],
|
||||
$headersSent = false,
|
||||
$content = '',
|
||||
$contentSent = false,
|
||||
$isHeadersOnly = false,
|
||||
// $bodyCssClasses = [],
|
||||
$metaImages = [];
|
||||
|
||||
|
@ -31,7 +50,7 @@ class Response
|
|||
|
||||
public static function addMetaImages(array $urls)
|
||||
{
|
||||
foreach($urls as $url)
|
||||
foreach ($urls as $url)
|
||||
{
|
||||
static::addMetaImage($url);
|
||||
}
|
||||
|
@ -61,7 +80,7 @@ class Response
|
|||
{
|
||||
$title = '';
|
||||
preg_match_all('/<h(1|2)[^>]*>([^<]+)</', $content, $titleMatches);
|
||||
foreach($titleMatches[1] as $matchIndex => $headerValue)
|
||||
foreach ($titleMatches[1] as $matchIndex => $headerValue)
|
||||
{
|
||||
if ($headerValue == '1' || !$title)
|
||||
{
|
||||
|
@ -96,6 +115,225 @@ class Response
|
|||
return static::$assets['js'];
|
||||
}
|
||||
|
||||
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::setHeaders(array_filter([
|
||||
'Content-Disposition' => 'attachment;filename=' . $name,
|
||||
'Content-Type' => $type ? 'application/zip' : null,
|
||||
'Content-Length' => $size ?: null,
|
||||
'X-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);
|
||||
}
|
||||
|
||||
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]] = isset($tmp[1]) ? $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 isset(static::$headers[$name]) ? 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');
|
||||
}
|
||||
|
||||
$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 isset($statusTexts[$code]) ? $statusTexts[$code] : null;
|
||||
}
|
||||
|
||||
protected static function normalizeHeaderName($name)
|
||||
{
|
||||
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));
|
||||
|
|
|
@ -78,17 +78,17 @@ class View
|
|||
return ParsedownExtra::instance()->text(trim(file_get_contents($path)));
|
||||
}
|
||||
|
||||
public static function exists($template)
|
||||
public static function exists($template): bool
|
||||
{
|
||||
return is_readable(static::getFullPath($template));
|
||||
}
|
||||
|
||||
protected static function isMarkdown($nameOrPath)
|
||||
protected static function isMarkdown($nameOrPath): bool
|
||||
{
|
||||
return strlen($nameOrPath) > 3 && substr($nameOrPath, -3) == '.md';
|
||||
}
|
||||
|
||||
protected static function getFullPath($template)
|
||||
protected static function getFullPath($template): string
|
||||
{
|
||||
if ($template && $template[0] == '/')
|
||||
{
|
||||
|
@ -103,12 +103,12 @@ class View
|
|||
return ROOT_DIR . '/view/template/' . $template . '.php';
|
||||
}
|
||||
|
||||
public static function imagePath($image)
|
||||
public static function imagePath($image): string
|
||||
{
|
||||
return '/img/' . $image;
|
||||
}
|
||||
|
||||
public static function parseMarkdown($template)
|
||||
public static function parseMarkdown($template): array
|
||||
{
|
||||
$path = static::getFullPath($template);
|
||||
list($ignored, $frontMatter, $markdown) = explode('---', file_get_contents($path), 3);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php $error = isset($error) ? $error : null ?>
|
||||
<form action="/list-subscribe" method="post" novalidate>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="notice notice-error spacer1"><?php echo $error ?></div>
|
||||
<?php elseif ($success): ?>
|
||||
|
@ -10,13 +11,14 @@
|
|||
<?php js_end() ?>
|
||||
<div class="notice notice-success spacer1"><?php echo $success ?></div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($error || !$success): ?>
|
||||
<div class="mail-submit">
|
||||
<input type="hidden" name="returnUrl" value="<?php echo $returnUrl ?>"/>
|
||||
<input type="hidden" name="listId" value="<?php echo $listId ?>"/>
|
||||
<input type="hidden" name="listSig" value="<?php echo $listSig ?>"/>
|
||||
<input type="email" value="" name="email" class="required email standard" placeholder= "<?php echo __('email.placeholder') ?>">
|
||||
<input type="submit" value="<?php echo isset($submitLabel) ? $submitLabel : __('email.subs') ?>" name="subscribe" id="mc-embedded-subscribe" class="<?php echo $btnClass ?>">
|
||||
<input type="submit" value="<?php echo isset($submitLabel) ? $submitLabel : __('email.subs') ?>" name="subscribe" class="<?php echo $btnClass ?>">
|
||||
<?php if (isset($fbEvent)): ?>
|
||||
<input type="hidden" name="fbEvent" value="<?php echo $fbEvent ?>" />
|
||||
<?php endif ?>
|
||||
|
|
|
@ -23,13 +23,13 @@
|
|||
<div class="span6">
|
||||
<h3><?php echo __('publish.keepl') ?></h3>
|
||||
<ul>
|
||||
<?php if ($_SERVER['REQUEST_URI'] != '/what'): ?>
|
||||
<?php if (Request::getRelativeUri() != '/what'): ?>
|
||||
<li>Read "<a href="/what" class="link-primary">Art in the Internet Age</a>", an introductory essay.</li>
|
||||
<?php endif ?>
|
||||
<?php if ($_SERVER['REQUEST_URI'] != '/team'): ?>
|
||||
<?php if (Request::getRelativeUri() != '/team'): ?>
|
||||
<li>Find out about <a href="/team" class="link-primary">the team behind LBRY</a>.</li>
|
||||
<?php endif ?>
|
||||
<?php if (strpos($_SERVER['REQUEST_URI'], '/news') === false): ?>
|
||||
<?php if (strpos(Request::getRelativeUri(), '/news') === false): ?>
|
||||
<li>Check out the latest <a href="/news" class="link-primary">news</a>.</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
|
|
|
@ -21,7 +21,7 @@ try
|
|||
{
|
||||
View::compileCss();
|
||||
}
|
||||
Controller::dispatch(strtok($_SERVER['REQUEST_URI'], '?'));
|
||||
Controller::dispatch(strtok(Request::getRelativeUri(), '?'));
|
||||
}
|
||||
catch(Throwable $e)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue