Closed ursulnegrul closed 6 years ago
I guess you could add a custom filter that does not forward the request and does an early response return.
I know this a closed issue, but may be this filter can help to future readers:
$response = $proxy
->forward($request)
->filter(function ($request, $response, $next) {
// Inform origin server this is a mirror
$request = $request->withHeader('X-Client-Key', 'Mirror/1');
// Cache Object Id
$cacheDir = sys_get_temp_dir();
$cacheObjectId = hash("md5", (string) $request->getUri());
$cacheObjectMime = $cacheObjectId . ".headers";
$cacheEntry = $cacheDir . DIRECTORY_SEPARATOR . $cacheObjectId;
$cacheEntryHeaders = $cacheDir . DIRECTORY_SEPARATOR . $cacheObjectMime;
$cacheControl = $request->hasHeader("Cache-Control") ?
$request->getHeader("Cache-Control")[0] :
"max-age=0";
$cacheEntryFound = file_exists($cacheEntry);
// A value indicating if cache will be used...
$enableCache = $cacheEntryFound && $cacheControl !== "no-cache";
// Purge cache
$cachePurge = $request->hasHeader("X-Cache-Purge") ?
$request->getHeader("X-Cache-Purge")[0] :
"no";
if ($cacheEntryFound && strtolower($cachePurge) === "yes") {
unlink($cacheEntry);
unlink($cacheEntryHeaders);
$cacheEntryFound = false;
}
// Serve from cache.
if ($enableCache && $cacheEntryFound) {
// We expect a file with original headers.
$cacheRawHeaders = file_exists($cacheEntryHeaders) ?
// We create an array of headers
explode("\n", file_get_contents($cacheEntryHeaders)) :
// or assign a default list of headrs.
["Content-Type: application/octet-stream"];
// We can overwrite headers to add cache.
$cacheRawHeaders[] = "Cache-Control: max-age=31536000";
// Resource was served from a caché.
$cacheRawHeaders[] = "X-Cache: HIT";
// Mutate arrayto convert it to valid headers.
$cacheHeaders = [];
foreach ($cacheRawHeaders as $headerLine) {
$headerNameLength = strpos($headerLine, ":");
if ($headerNameLength === false) {
// An incorrect header line.
continue;
}
$headerName = substr($headerLine, 0, $headerNameLength);
$headerValue = substr($headerLine, $headerNameLength + 1);
$cacheHeaders[$headerName] = trim($headerValue);
}
// Support resource identifiers
$cacheValidators = [
"If-None-Match" => "ETag",
"if-Modified-Since" => "Last-Modified"
];
foreach ($cacheValidators as $browserHeader => $cacheHeaderCompare) {
if ($request->hasHeader($browserHeader) && array_key_exists($cacheHeaderCompare, $cacheHeaders)) {
$leftValidationToken = $request->getHeader($browserHeader)[0];
$rightValidationToken = $cacheHeaders[$cacheHeaderCompare];
if ($leftValidationToken === $rightValidationToken) {
return $response->withStatus(304);
}
}
}
$cacheStream = new \Laminas\Diactoros\Stream(fopen($cacheEntry, "rb"));
// ...and creates a new response
return new \Laminas\Diactoros\Response(
$cacheStream,
200,
$cacheHeaders
);
}
// Call the next item in the middleware.
$response = $next($request, $response);
// Save cache.
if ($response->getStatusCode() === 200 && $response->hasHeader("Content-Type")) {
// Cache only if:
// * HTTP Status Code = 200
// * Content-Type is cacheable
$cacheMimeList = [
"text/javascript",
"application/javascript",
"image/jpeg",
"audio/mpeg",
"text/css",
"image/gif",
"image/vnd.microsoft.icon",
"image/x-icon",
];
// Cache a list of headers from source server.
$cacheResponseHeaders = [];
$headerList = [
"Content-Type",
"Content-Encoding",
"Date",
"ETag",
"Last-Modified",
];
foreach ($headerList as $headerName) {
if ($response->hasHeader($headerName)) {
// Example: Content-Type: text/html; charset=utf-8
$cacheResponseHeaderValue = implode(";", $response->getHeader($headerName));
$cacheResponseHeaders[] = "${headerName}: ${cacheResponseHeaderValue}";
}
}
$responseMime = $response->getHeader("Content-Type")[0];
if (in_array($responseMime, $cacheMimeList)) {
// We have a valid response to cache it.
file_put_contents($cacheEntry, $response->getBody());
// Save mime type for future downloads.
file_put_contents(
$cacheEntryHeaders,
implode("\n", $cacheResponseHeaders)
);
}
// Resource was fetched from the origin server
return $response->withHeader("X-Cache", "MISS");
}
return $response;
})
->to('https://example.com');
is there a middleware i could use to save the remote resources locally in the same relative path, like fonts and pictures, so .htaccess won't rewrite to the proxy.php if it founds the resources locally. Thank you