在angular很常遇到compile template時出錯的情況,因為在angular中,使用比較嚴謹的判斷方式,只要看到不符合規範,會直接拋出exception。
##Cross origin
以下是一個video的範例,設定影片的source
:
1 | <video width="320" height="240" controls> |
設定source
的影片來源:1
$scope.source = "http://other.sparrowhome.twbbs.org/movie.mp4"
這時就會發現angular拋出exception,出現cross domain的問題。
但是若是直接寫在html上呢?
1 | <video width="320" height="240" controls> |
此時你可以發現能正常的播放,但是在angular就是會拋錯,這時你可以透過$sceDelegateProvider,來設定黑名單和白名單,決定哪個domain可以讀取這隻影片。
假設你要讓所有domain都能使用,在白名單可以這樣寫:1
2
3
4
5angular
.module('MyApp')
.config(['$sceDelegateProvider', function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist(['**']);
})
若是你只要目前網域底下的子網域都可以讀取的話,可以這樣寫:
1 | $sceDelegateProvider.resourceUrlWhitelist(['http://*.sparrowhome.twbbs.org']) |
如果要透過黑名單可以直接使用resourceUrlBlacklist
。
##Unsafe resource URL
如果是讀取img
,不管是cross domain都能正常讀取,不過還是會有不讀取的狀況。
例如你透過一個<input type="file">
,去取得顯示image
,像是<img ng-src="{{img}}" />
:
1 | $scope.img = URL.createObjectURL(imgFile); |
此時就會拋出unsafe:blob
的exception
,依據URL.createObjectURL
所取得url,可以很容易發現,最前方協定是不同的。例如URL.createObjectURL
回傳一個blob:http%3A%2F%2Fsparrowhome.twbbs.org%2Fimage.png
,此時不在預設的允許名單中,這時就要透過$compileProvider.imgSrcSanitizationWhitelist
去改寫。
像是讓所有協定都通過:
1 | angular.module('MyApp').config(['$sceDelegateProvider', function( $compileProvider ) { |
也可自訂要通過特定的協定,像是/^(https?|ftp|file|blob|data):/
,同樣的href
也有aHrefSanitizationWhitelist
可以去設定。在angular中使用要嚴謹的判斷方式,當然也可透過jquery或原生javascript繞過這問題,不過這樣就有點失去用angular的意義了,畢竟用template的方式,比起寫code跟為簡潔。