Reputation: 7025
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
<video controls poster="img/poster.png">
<source ng-src="{{object.src}}" type="video/mp4"/>
</video>
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
Upvotes: 198
Views: 129722
Reputation: 4462
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">
</iframe>
http://plnkr.co/edit/tYq22VjwB10WmytQO9Pb?p=preview
Upvotes: 271
Reputation: 10420
I had this error in tests, the directive templateUrl
wasn't trusted, but only for the spec, so I added the template directory:
beforeEach(angular.mock.module('app.templates'));
My main directory is app
.
Upvotes: 0
Reputation: 49132
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.
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(['**']);
});
Upvotes: 77
Reputation: 26494
If anybody is looking for a TypeScript solution:
.ts file (change variables where applicable):
module App.Filters {
export class trustedResource {
static $inject:string[] = ['$sce'];
static filter($sce:ng.ISCEService) {
return (value) => {
return $sce.trustAsResourceUrl(value)
};
}
}
}
filters.filter('trustedResource', App.Filters.trusted.filter);
Html:
<video controls ng-if="HeaderVideoUrl != null">
<source ng-src="{{HeaderVideoUrl | trustedResource}}" type="video/mp4"/>
</video>
Upvotes: 2
Reputation: 41
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>
Upvotes: 4
Reputation: 6601
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>
Upvotes: 271
Reputation: 608
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!
Upvotes: 21
Reputation: 39
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>
Upvotes: 2
Reputation: 7775
Based on the error message, your problem seems to be related to interpolation (typically your expression {{}}
), not to a cross-domain issue. Basically ng-src="{{object.src}}"
sucks.
ng-src
was designed with img
tag in mind IMO. It might not be appropriate for <source>
. See http://docs.angularjs.org/api/ng.directive:ngSrc
If you declare <source src="somesite.com/myvideo.mp4"; type="video/mp4"/>
, it will be working, right? (note that I remove ng-src
in favor of src
) If not it must be fixed first.
Then ensure that {{object.src}}
returns the expected value (outside of <video>
):
<span>{{object.src}}</span>
<video>...</video>
If it returns the expected value, the following statement should be working:
<source src="{{object.src}}"; type="video/mp4"/> //src instead of ng-src
Upvotes: 1