Skip to content
Advertisement

Proxy pass image Laravel

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 enter image description here

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') }}"
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement