External resource not being loaded by AngularJs

External resource not being loaded by AngularJs

Using Angular and Phonegap, I’m trying to load a video that is on a remote server but came across an issue. In my JSON, the URL is entered as a plain HTTP URL.
“src” : “http://www.somesite.com/myvideo.mp4”

My video template

All my other data gets loaded but when I look my console, I get this error:
Error: [$interpolate:interr] Can’t interpolate: {{object.src}}
Error: [$sce:insecurl] Blocked loading resource from url not allowed by $sceDelegate policy. URL

I tried in adding $compileProvider in my config set up but it did not resolve my issue.
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);

I saw this post about cross domain issues but I’m not sure how to resolve this or what direction I should go in. Any ideas? Any help is appreciated

Solutions/Answers:

Solution 1:

This is the only solution that worked for me:

var app = angular.module('plunker', ['ngSanitize']);

app.controller('MainCtrl', function($scope, $sce) {
  $scope.trustSrc = function(src) {
    return $sce.trustAsResourceUrl(src);
  }

  $scope.movie = {src:"http://www.youtube.com/embed/Lx7ycjC8qjE", title:"Egghead.io AngularJS Binding"};
});

Then in an iframe:

<iframe class="youtube-player" type="text/html" width="640" height="385" ng-src="{{trustSrc(movie.src)}}" allowfullscreen frameborder="0">

Related:  Is there a way to “require” a JS file only once in nodejs?

http://plnkr.co/edit/tYq22VjwB10WmytQO9Pb?p=preview

Solution 2:

Another simple solution is to create a filter:

app.filter('trusted', ['$sce', function ($sce) {
    return function(url) {
        return $sce.trustAsResourceUrl(url);
    };
}]);

Then specify the filter in ng-src:

<video controls poster="img/poster.png">
       <source ng-src="{{object.src | trusted}}" type="video/mp4"/>
</video>

Solution 3:

Whitelist the resource with $sceDelegateProvider

This is caused by a new security policy put in place in Angular 1.2. It makes XSS harder by preventing a hacker from dialling out (i.e. making a request to a foreign URL, potentially containing a payload).

To get around it properly you need to whitelist the domains you want to allow, like this:

angular.module('myApp',['ngSanitize']).config(function($sceDelegateProvider) {
  $sceDelegateProvider.resourceUrlWhitelist([
    // Allow same origin resource loads.
    'self',
    // Allow loading from our assets domain.  Notice the difference between * and **.
    'http://srv*.assets.example.com/**'
  ]);

  // The blacklist overrides the whitelist so the open redirect here is blocked.
  $sceDelegateProvider.resourceUrlBlacklist([
    'http://myapp.example.com/clickThru**'
  ]);
});

This example is lifted from the documentation which you can read here:

https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider

Be sure to include ngSanitize in your app to make this work.

Related:  Switch statement for string matching in JavaScript

Disabling the feature

If you want to turn off this useful feature, and you’re sure your data is secure, you can simply allow **, like so:

angular.module('app').config(function($sceDelegateProvider) {
  $sceDelegateProvider.resourceUrlWhitelist(['**']);
});

Solution 4:

Had the same issue here. I needed to bind to Youtube links. What worked for me, as a global solution, was to add the following to my config:

.config(['$routeProvider', '$sceDelegateProvider',
        function ($routeProvider, $sceDelegateProvider) {

    $sceDelegateProvider.resourceUrlWhitelist(['self', new RegExp('^(http[s]?):\/\/(w{3}.)?youtube\.com/.+$')]);

}]);

Adding ‘self’ in there is important – otherwise will fail to bind to any URL. From the angular docs

‘self’ – The special string, ‘self’, can be used to match against all
URLs of the same domain as the application document using the same
protocol.

With that in place, I’m now able to bind directly to any Youtube link.

You’ll obviously have to customise the regex to your needs. Hope it helps!

Solution 5:

The best and easy solution for solving this issue is pass your data from this function in controller.

$scope.trustSrcurl = function(data) 
{
    return $sce.trustAsResourceUrl(data);
}

In html page

<iframe class="youtube-player" type="text/html" width="640" height="385" ng-src="{{trustSrcurl(video.src)}}" allowfullscreen frameborder="0"></iframe>

Solution 6:

I ran into the same problem using Videogular. I was getting the following when using ng-src:

Error: [$interpolate:interr] Can't interpolate: {{url}}
Error: [$sce:insecurl] Blocked loading resource from url not allowed by $sceDelegate policy

I fixed the problem by writing a basic directive:

angular.module('app').directive('dynamicUrl', function () {
return {
  restrict: 'A',
  link: function postLink(scope, element, attrs) {
    element.attr('src', scope.content.fullUrl);
  }
};
});

The html:

 <div videogular vg-width="200" vg-height="300" vg-theme="config.theme">
    <video class='videoPlayer' controls preload='none'>
          <source dynamic-url src='' type='{{ content.mimeType }}'>
    </video>
 </div>