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') }}"