Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New policy? strict-origin-when-cross-origin #205

Closed
rafanake opened this issue Apr 27, 2021 · 21 comments
Closed

New policy? strict-origin-when-cross-origin #205

rafanake opened this issue Apr 27, 2021 · 21 comments
Labels
enhancement New feature or request

Comments

@rafanake
Copy link

Looks like facebook added a new CORS policy and you cant display the data directly anymore...

Is there any way to display the image into a tag?

@pgrimaud
Copy link
Owner

Refs to #204

Your pictures come from an old feed? (eg. saved in database)?

@rafanake
Copy link
Author

rafanake commented Apr 27, 2021

Refs to #204

Your pictures come from an old feed? (eg. saved in database)?

Nope! But thats ok, it's not this API fault!

I was able to "bypass" Instagram CORS by saving the image content into a file, then display the saved file instead the one recieved from api!

Thanks and FU Facebook!

@pgrimaud
Copy link
Owner

Yeah, that's bad.

Another solution could be to use an image proxy service :

@pgrimaud pgrimaud added the help wanted Extra attention is needed label Apr 27, 2021
@samholguin
Copy link

Just to confirm, there's no easy way around the CORS policy change, we either have to save locally or use a proxy?

@pgrimaud
Copy link
Owner

pgrimaud commented May 2, 2021

@samholguin I don't find a way to avoid CORS policy change (by changing pictures signatures maybe).
So yes, you have to save picture locally for long term good usage.

@veuxx
Copy link

veuxx commented May 2, 2021

i, particularly, am using @copy and hosting the images on the my own server, to avoid multiple requests ... but you can try the solution below ... I created a function to facilitate the implementation.

function encodeimg($url){

	$imageData = base64_encode(file_get_contents($url));
	$src = 'data: '.mime_content_type($url).';base64,'.$imageData;
	return $src;
}

Use like:
<img src="<?=encodeimg($string_of_link_img);?>" />

@samholguin
Copy link

If anyone needs a WordPress solution:

/**
 * Save image
 *
 * @return $imageId post ID
 */
protected function save_image($file)
{
    global $wpdb;

    // check if image exists
    $imageSourceUrl = $wpdb->get_results(
        $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta where meta_key = %s and meta_value = %s", '_source_url', $file)
    );

    if (! empty($imageSourceUrl)) {
        return $imageSourceUrl[0]->post_id;
    }

    // insert image
    $imageId = media_sideload_image($file, '', 'Instagram feed', 'id');
    return (! is_wp_error($imageId) ? $imageId : '');
}

@pgrimaud
Copy link
Owner

pgrimaud commented May 4, 2021

I may add a method to save pictures directly in this package.

Example :

// previously, instanciate cachepool blabla

$api = new Api($cachePool);
$api->login($credentials->getLogin(), $credentials->getPassword());

$profile = $api->getProfile('twhiddleston');

foreach($profile->getMedias() as $media) {
   $localMedia = $media->downloadTo('/path/to/your/storage/folder');
   print_r($localMedia); // will return file name of media on your storage folder
}

What do you think about?

@singhpaul
Copy link

singhpaul commented May 5, 2021

We can't use the src returned by the API as the src value to embed an image with an img tag any longer because of the change in CORS policy, even though if you type in the src url directly into a browser, the image will load. Is that correct? This is the behavior we are experiencing and just want to confirm that's to be expected with this new change.

@pgrimaud
Copy link
Owner

pgrimaud commented May 5, 2021

We can't use the src returned by the API as the src value to embed an image with an img tag any longer because of the change in CORS policy, even though if you type in the src url directly into a browser, the image will load. Is that correct? This is the behavior we are experiencing and just want to confirm that's to be expected with this new change.

That's the CORS policy, you can't embedded the IG picture into your website in an img tag.

But you can access to this picture with a direct link from a client (curl, wget or direct access from your browser).

Another method could be to use an image proxy service (e.g. https://cloudinary.com/documentation/fetch_remote_images
or https://imgproxy.net/) which will make a curl request on the fly to the picture and serve it for you without any CORS policy.

@singhpaul
Copy link

That's the CORS policy, you can't embedded the IG picture into your website in an img tag.

But you can access to this picture with a direct link from a client (curl, wget or direct access from your browser).

Another method could be to use an image proxy service (e.g. https://cloudinary.com/documentation/fetch_remote_images
or https://imgproxy.net/) which will make a curl request on the fly to the picture and serve it for you without any CORS policy.

Thanks, I began to realize I was answering my own question as I was typing but went ahead and posted in case others had wondered the same.

We decided to just save and serve the images locally (as others here have also suggested) and that seems to be working well. Likely a better scenario anyway as it will avoid running afoul of Facebook's usage limits.

@samholguin
Copy link

I may add a method to save pictures directly in this package.

Example :

// previously, instanciate cachepool blabla

$api = new Api($cachePool);
$api->login($credentials->getLogin(), $credentials->getPassword());

$profile = $api->getProfile('twhiddleston');

foreach($profile->getMedias() as $media) {
   $localMedia = $media->downloadTo('/path/to/your/storage/folder');
   print_r($localMedia); // will return file name of media on your storage folder
}

What do you think about?

Good idea.

I am not sure it will be useful in cases like mine when working with the likes of WordPress, but people can easily sort that as I did.

@David-Kurniawan
Copy link
Contributor

i've same issue, for me this simple way can quick solve the problem in prod 😄

    private function getImage($url, $ext, $host)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, urldecode($url));
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'accept-encoding: gzip, deflate, br',
            'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36',
            'host: '.$host
        ));
        $picture = curl_exec($ch);
        curl_close($ch);
        header('Content-type: image/'.$ext);
        echo $picture;
    }

Just load image from your server side if possible 👍

@thefoxlab
Copy link

thefoxlab commented Jun 1, 2021

i, particularly, am using @copy and hosting the images on the my own server, to avoid multiple requests ... but you can try the solution below ... I created a function to facilitate the implementation.

function encodeimg($url){

	$imageData = base64_encode(file_get_contents($url));
	$src = 'data: '.mime_content_type($url).';base64,'.$imageData;
	return $src;
}

Use like:
<img src="<?=encodeimg($string_of_link_img);?>" />


function encodeimg($url){
    $r = get_headers($url,1);
    if(isset($r['Content-Type']))
    {
        $imageData = base64_encode(file_get_contents($url));
        $src = 'data: '.$r['Content-Type'].';base64,'.$imageData;        
    }
    else{
        $src = $url;
    }
    return $src;
}

PS: mime_content_type() will be use for local file, Not for remote file URL :)

Thanks for the trick!

@YannBoyongo
Copy link

i, particularly, am using @copy and hosting the images on the my own server, to avoid multiple requests ... but you can try the solution below ... I created a function to facilitate the implementation.

function encodeimg($url){

	$imageData = base64_encode(file_get_contents($url));
	$src = 'data: '.mime_content_type($url).';base64,'.$imageData;
	return $src;
}

Use like:
<img src="<?=encodeimg($string_of_link_img);?>" />


function encodeimg($url){
    $r = get_headers($url,1);
    if(isset($r['Content-Type']))
    {
        $imageData = base64_encode(file_get_contents($url));
        $src = 'data: '.$r['Content-Type'].';base64,'.$imageData;        
    }
    else{
        $src = $url;
    }
    return $src;
}

PS: mime_content_type() used for file only not for remote url!

Thanks tricks!

this works perfectly, thanks

@veuxx
Copy link

veuxx commented Jun 3, 2021

i, particularly, am using @copy and hosting the images on the my own server, to avoid multiple requests ... but you can try the solution below ... I created a function to facilitate the implementation.

function encodeimg($url){

	$imageData = base64_encode(file_get_contents($url));
	$src = 'data: '.mime_content_type($url).';base64,'.$imageData;
	return $src;
}

Use like:
<img src="<?=encodeimg($string_of_link_img);?>" />


function encodeimg($url){
    $r = get_headers($url,1);
    if(isset($r['Content-Type']))
    {
        $imageData = base64_encode(file_get_contents($url));
        $src = 'data: '.$r['Content-Type'].';base64,'.$imageData;        
    }
    else{
        $src = $url;
    }
    return $src;
}

PS: mime_content_type() used for file only not for remote url!

Thanks tricks!

thanks for the contributions... i hadn't even noticed, because the image was actually locally

@jesserosenfield
Copy link

jesserosenfield commented Jun 10, 2021

Awesome plugin thanks!!!

I got this working– and converted the JPGs to webp as well

	$profile = $api->getProfile('username');
	$profile = $profile->getMedias();
	
	$instahtml = '';
	
	$i = 1;
	
	foreach($profile as $img) {
		$link = $img->getLink();
		
		$theimg = $img->getDisplaySrc();
		$imgfile = basename($theimg);
			$imgfile = strtok($imgfile, '?');
			$imgpath = dirname(__FILE__) . '/../../assets/images/insta/' . $imgfile;
			
		if(!file_exists($imgpath) || (function_exists('imagewebp') && !file_exists($imgpath . '.webp'))) {
			if(!file_exists($imgpath)) {
				$theimg = copy($theimg, $imgpath);				
			}
			
			if(function_exists('imagewebp')) {
				$jpg = imagecreatefromjpeg($imgpath);
				$w = imagesx($jpg);
				$h = imagesy($jpg);
				
				$webp = imagecreatetruecolor($w,$h);

				imagecopy($webp,$jpg,0,0,0,0,$w,$h);
				imagewebp($webp, $imgpath . '.webp', 80);
				
				
				imagedestroy($jpg);
				imagedestroy($webp);
			}
		}
		
		$theimg = get_stylesheet_directory_uri() . '/assets/images/insta/' . $imgfile;
		
	
		$instahtml .= "
			<div class='col-1200-2'>
				<a href='$link' class='block insta-item bg-item-wrap'>
					<div class='bg-item bg-cover' data-background-image='$theimg'>
					</div>
				</a>
			</div>
		";
		
		if($i == 6) {
			break;
		}
		
		$i++;
	}

@timohausmann
Copy link

Very simply function to download URL content to your server:

downloadURL($media->getThumbnailSrc(), $media->getId());

function downloadURL($url, $filename) {
    $content = file_get_contents($url);
    file_put_contents(__DIR__ ."/{$filename}.jpg", $content);
}

@pgrimaud
Copy link
Owner

pgrimaud commented Jul 8, 2021

@Nispeon Could you take a look at this enhancement please? Maybe create a method to download media on a targeted directory Thanks 👀

@pgrimaud pgrimaud added enhancement New feature or request and removed help wanted Extra attention is needed labels Jul 8, 2021
@pgrimaud
Copy link
Owner

pgrimaud commented Jul 8, 2021

@Nispeon had a new helper in 6.8.0 version.

You can now download picture directly with this package.

Example : https://github.com/pgrimaud/instagram-user-feed/blob/master/examples/medias-download.php

Helper code : https://github.com/pgrimaud/instagram-user-feed/blob/master/src/Instagram/Utils/MediaDownloadHelper.php

@pgrimaud pgrimaud closed this as completed Jul 8, 2021
@paulprins
Copy link

I know the issue is closed but I just wrapped up a library you can use to download and temporarily cache the media (and therefore not need to host it forever). It will either give you the cached URL back, or download the media before giving you the cached URL. Lifetimes and timestamps are stored per media item.

https://github.com/FreshVine/expiring-media-cache

Example:

use FreshVine\ExpiringMediaCache\ExpiringMediaCache as ExpiringMediaCache;
.....

$ExpiringMedia = new ExpiringMediaCache( );
$ImageCachedURL = $ExpiringMedia->getURL( $ExpiringMedia->cacheThis( REMOTE_URL ) );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests