Skip to content
Permalink
Browse files

Use token as a reference to params in bundler URLs

Closes #2
  • Loading branch information
apeschar committed Oct 19, 2019
1 parent 7f402ef commit 93de81b4025c97170ae660b28d41a708e5f98663
@@ -0,0 +1,14 @@
<?php
namespace Kibo\Phast\Common;
class Base64url {
public static function encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
public static function decode($data) {
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}
}
@@ -10,6 +10,7 @@
use Kibo\Phast\Retrievers\UniversalRetriever;
use Kibo\Phast\Security\ServiceSignatureFactory;
use Kibo\Phast\ValueObjects\URL;
use Kibo\Phast\Services\Bundler\TokenRefMakerFactory;
class Factory implements HTMLFilterFactory {
@@ -43,7 +44,8 @@ public function make(array $config) {
$localRetriever,
$retriever,
new OptimizerFactory($config),
(new CSSCompositeFactory())->make($config)
(new CSSCompositeFactory())->make($config),
(new TokenRefMakerFactory())->make($config)
);
}
@@ -8,7 +8,7 @@
use Kibo\Phast\Retrievers\Retriever;
use Kibo\Phast\Security\ServiceSignature;
use Kibo\Phast\Services\Bundler\ServiceParams;
use Kibo\Phast\Services\Bundler\ShortBundlerParamsParser;
use Kibo\Phast\Services\Bundler\TokenRefMaker;
use Kibo\Phast\Services\ServiceFilter;
use Kibo\Phast\Services\ServiceRequest;
use Kibo\Phast\ValueObjects\PhastJavaScript;
@@ -88,14 +88,20 @@ class Filter extends BaseHTMLStreamFilter {
*/
private $optimizer;
/**
* @var TokenRefMaker
*/
private $tokenRefMaker;
public function __construct(
ServiceSignature $signature,
URL $baseURL,
array $config,
Retriever $localRetriever,
Retriever $retriever,
OptimizerFactory $optimizerFactory,
ServiceFilter $cssFilter
ServiceFilter $cssFilter,
TokenRefMaker $tokenRefMaker
) {
$this->signature = $signature;
$this->baseURL = $baseURL;
@@ -110,6 +116,7 @@ public function __construct(
$this->retriever = $retriever;
$this->optimizerFactory = $optimizerFactory;
$this->cssFilter = $cssFilter;
$this->tokenRefMaker = $tokenRefMaker;
foreach ($config['whitelist'] as $key => $value) {
if (!is_array($value)) {
@@ -318,6 +325,7 @@ private function makeStyle(URL $url, $content, $media, $optimized, $stripImports
$style->setAttribute('media', $media);
}
if ($optimized) {
$style->setAttribute('data-phast-original-src', $url->toString());
$style->setAttribute('data-phast-params', $this->makeServiceParams($url, $stripImports));
}
$style->setTextContent($content);
@@ -352,6 +360,7 @@ protected function makeServiceParams(URL $originalLocation, $stripImports = fals
}
return ServiceParams::fromArray($params)
->sign($this->signature)
->replaceByTokenRef($this->tokenRefMaker)
->serialize();
}
@@ -1,3 +1,5 @@
/* globals phast */

phast.stylesLoading = 0;

var resourceLoader = phast.ResourceLoader.instance;
@@ -13,14 +15,21 @@ phast.forEachSelectedElement('style[data-phast-params]', function (style) {
})
.catch(function (err) {
console.warn("[Phast] Failed to load CSS", params, err);
console.info("[Phast] Falling back to <link> element for", params.src);
var src = style.getAttribute('data-phast-original-src');
if (!src) {
console.error("[Phast] No data-phast-original-src on <style>!", style);
return;
}
console.info("[Phast] Falling back to <link> element for", src);
var link = document.createElement('link');
link.href = params.src;
link.href = src;
link.media = style.media;
link.rel = 'stylesheet';
link.onload = function () {
style.parentNode.removeChild(style);
};
link.addEventListener('load', function () {
if (style.parentNode) {
style.parentNode.removeChild(style);
}
});
style.parentNode.insertBefore(link, style.nextSibling);
})
.finally(function () {
@@ -1,3 +1,5 @@
/* globals phast */

var Promise = phast.ES6Promise.Promise;

phast.ResourceLoader = function (client, cache) {
@@ -143,12 +145,7 @@ phast.ResourceLoader.BundlerServiceClient.RequestsPack = function (shortParamsMa
if (cacheMarkers.length > 0) {
parts.unshift('c=' + phast.hash(cacheMarkers.join('|'), 23045));
}
return parts.join('&').replace(/(%..)|([A-M])|([N-Z])/gi, function (m, e, am, nz) {
if (e) {
return m;
}
return String.fromCharCode(m.charCodeAt(0) + (am ? 13 : -13));
});
return obfuscateQuery(parts.join('&'));
};

function getSortedTokens() {
@@ -187,6 +184,18 @@ phast.ResourceLoader.BundlerServiceClient.RequestsPack = function (shortParamsMa
return charsTable[p2] + charsTable[p1];
}

function obfuscateQuery(query) {
if (!/(^|&)s=/.test(query)) {
return query;
}
return query.replace(/(%..)|([A-M])|([N-Z])/gi, function (m, e, am, nz) {
if (e) {
return m;
}
return String.fromCharCode(m.charCodeAt(0) + (am ? 13 : -13));
});
}

this.handleResponse = function (responseText) {
try {
var responses = JSON.parse(responseText);
@@ -1,3 +1,5 @@
/* global phast */

var Promise = phast.ES6Promise;

var go = phast.once(loadScripts);
@@ -1,3 +1,5 @@
/* globals phast */

var Promise = phast.ES6Promise;

phast.ScriptsLoader = {};
@@ -306,7 +308,7 @@ phast.ScriptsLoader.Scripts.AsyncAJAXScript = function (utils, element, fetch, f
};

this.describe = function () {
return 'bundled async script at ' + JSON.parse(element.getAttribute('data-phast-params'))['src'];
return 'bundled async script at ' + element.getAttribute('data-phast-original-src');
};
};

@@ -336,7 +338,7 @@ phast.ScriptsLoader.Scripts.SyncAJAXScript = function (utils, element, fetch, fa
};

this.describe = function () {
return 'bundled sync script at ' + JSON.parse(element.getAttribute('data-phast-params'))['src'];
return 'bundled sync script at ' + element.getAttribute('data-phast-original-src');
};
};

@@ -5,6 +5,7 @@
use Kibo\Phast\Filters\HTML\HTMLFilterFactory;
use Kibo\Phast\Retrievers\LocalRetriever;
use Kibo\Phast\Security\ServiceSignatureFactory;
use Kibo\Phast\Services\Bundler\TokenRefMakerFactory;
class Factory implements HTMLFilterFactory {
@@ -18,7 +19,8 @@ public function make(array $config) {
return new Filter(
$filterConfig,
(new ServiceSignatureFactory())->make($config),
new LocalRetriever($config['retrieverMap'])
new LocalRetriever($config['retrieverMap']),
(new TokenRefMakerFactory())->make($config)
);
}
@@ -10,6 +10,7 @@
use Kibo\Phast\Retrievers\LocalRetriever;
use Kibo\Phast\Security\ServiceSignature;
use Kibo\Phast\Services\Bundler\ServiceParams;
use Kibo\Phast\Services\Bundler\TokenRefMaker;
use Kibo\Phast\Services\ServiceRequest;
use Kibo\Phast\ValueObjects\PhastJavaScript;
use Kibo\Phast\ValueObjects\URL;
@@ -32,6 +33,8 @@ class Filter extends BaseHTMLStreamFilter {
*/
private $retriever;
private $tokenRefMaker;
/**
* @var ObjectifiedFunctions
*/
@@ -46,11 +49,13 @@ public function __construct(
array $config,
ServiceSignature $signature,
LocalRetriever $retriever,
TokenRefMaker $tokenRefMaker,
ObjectifiedFunctions $functions = null
) {
$this->config = $config;
$this->signature = $signature;
$this->retriever = $retriever;
$this->tokenRefMaker = $tokenRefMaker;
$this->functions = is_null($functions) ? new ObjectifiedFunctions() : $functions;
}
@@ -103,6 +108,7 @@ private function makeServiceParams(URL $url, $cacheMarker) {
'isScript' => '1'
])
->sign($this->signature)
->replaceByTokenRef($this->tokenRefMaker)
->serialize();
}
@@ -33,7 +33,8 @@ public function make(array $config) {
$cssServiceFactory->makeRetriever($config),
$cssFilter,
$jsServiceFactory->makeRetriever($config),
$jsFilter
$jsFilter,
(new TokenRefMakerFactory())->make($config)
);
}
@@ -41,26 +41,22 @@ class Service {
*/
private $jsFilter;
/**
* Service constructor.
* @param ServiceSignature $signature
* @param Retriever $cssRetriever
* @param ServiceFilter $cssFilter
* @param Retriever $jsRetriever
* @param ServiceFilter $jsFilter
*/
private $tokenRefMaker;
public function __construct(
ServiceSignature $signature,
Retriever $cssRetriever,
ServiceFilter $cssFilter,
Retriever $jsRetriever,
ServiceFilter $jsFilter
ServiceFilter $jsFilter,
TokenRefMaker $tokenRefMaker
) {
$this->signature = $signature;
$this->cssRetriever = $cssRetriever;
$this->cssFilter = $cssFilter;
$this->jsRetriever = $jsRetriever;
$this->jsFilter = $jsFilter;
$this->tokenRefMaker = $tokenRefMaker;
}
@@ -79,6 +75,15 @@ private function streamResponse(ServiceRequest $request) {
yield '[';
$firstRow = true;
foreach ($this->getParams($request) as $key => $params) {
if (isset ($params['ref'])) {
$ref = $params['ref'];
$params = $this->tokenRefMaker->getParams($ref);
if (!$params) {
$this->logger()->error('Could not resolve ref {ref}', ['ref' => $ref]);
yield $this->generateJSONRow(['status' => 404], $firstRow);
continue;
}
}
if (!isset ($params['src'])) {
$this->logger()->error('No src found for set {key}', ['key' => $key]);
yield $this->generateJSONRow(['status' => 404], $firstRow);
@@ -81,4 +81,12 @@ private function makeToken(ServiceSignature $signature) {
});
return $signature->sign(json_encode($params));
}
public function replaceByTokenRef(TokenRefMaker $maker) {
if (!isset($this->token)) {
return $this;
}
$ref = $maker->getRef($this->token, $this->toArray());
return $ref ? ServiceParams::fromArray(['ref' => $ref]) : $this;
}
}

0 comments on commit 93de81b

Please sign in to comment.
You can’t perform that action at this time.