I’m trying to Proxy serve an HTTP image in my HTTPS site I heard that I can do a proxy serve of this file in one of my endpoint and render it in my site instead of displaying the actual file url. Below Is what I did but I’m getting the error below
Below is my HTML code I created my Custom Facade to display the image
<div><img src="{{ MyFacade.proxyImage("http://unsecure-image.com/image.jpeg") }}" /></div>
Below is my code in Laravel PHP
public function proxyImage($url) {
$imgInfo = getimagesize( $url );
if (stripos($imgInfo['mime'], 'image/') === false) {
die('Invalid image file');
}
header("Content-type: ".$imgInfo['mime']);
readfile( $url );
}
Any idea on how to achieve this? I just want to display the image
Advertisement
Answer
Ok here is the final answer to my question and thanks to @Lawrence for the idea. Hope this will help others having the same problem
public function proxyImage(Request $request, $key)
{
try {
$referer = $request->headers->get('referer');
// Let's remove the param query since we need
$sanitized_referer = substr($referer,0,strpos($referer, '?'));
if (!$referer) {
return abort('404');
}
if ($sanitized_referer != null) {
$referer = $sanitized_referer;
}
$image = $request->get('image');
if (filter_var($image, FILTER_VALIDATE_URL) === false) {
return abort('404');
}
$key = urldecode($key);
$decrypted_key = decrypt($key);
if (!isset($key) || $decrypted_key != $image) {
Log::info("Decripted key " . $decrypted_key . " referer " . $referer);
if ($decrypted_key != $referer) {
return abort('404');
}
}
if (!MyFacade::image_exist($image)) {
$image = 'images/no-images.jpg';
}
$file = file_get_contents($image);
$type = pathinfo($image, PATHINFO_EXTENSION);
header('Content-Type:'.$type);
echo $file;
} catch (Exception $e) {
Log::info($e->getMessage());
return abort(404);
}
}
And in my facade below are the code
class MyFacade {
/**
* Generate an encrypted url
*
* @param string $url - The url to be encrypted
* @return string - The encrypted url
*/
public function generateToken($url)
{
return urlencode(encrypt($url));
}
/**
* Check the image header if the image url contains an actual image or the file really does exist
* this is special handling for a bug with file_exist that returns false even if file does exist
*
* @param string $url - The image url to check
* @return boolean - true if the file exist, false otherwise
*/
public function image_exist($url)
{
$file_headers = @get_headers($url);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
return false;
}
return true;
}
/**
* Generate a url to return to the client. If the protocol is HTTP it will return the original image url
* but if the url is not http it will proxy serve the url and return an encrypted value
*
* @param string $image_url - The url to be check and encrypted if not https
* @return string - The newly generated url
*/
public function generateUrl($image_url)
{
if (parse_url($image_url, PHP_URL_SCHEME) == 'https') {
return $image_url;
}
return url('proxy-image/' . $this->generateToken($image_url) . '?image=' . $image_url);
}
}
Now on my blade template I just call the generateUrl. If the image is not in https format then it will return a url with encrypted token appended on it and a parameter of $image just to check if the token and the image in the params are the same url. In my blade I’m doing something like this
<img src="{{ Application::generateUrl('http://unsecuresite.com') }}"