フレームワークを作成するときは、クロスドメインの問題のため、ユーザーのリクエスト ターゲットをフックし、ユーザー コードの Image.src 操作をインターセプトして、プロキシ アクセスのために独自の URL にリダイレクトする必要があります。これについていくつかの調査を行いました。
考えられる解決策
- プロキシを使用してプロキシをラップして返し、ハンドラーを通じてプロキシをインターセプトします。
- Object.defineProperty を使用して変更を監視し、インターセプトします
Proxy メソッドを使用してインターセプトする場合は、Proxy オブジェクトが返されるため、src をインターセプトして変更することはできますが、drawImage を介して Canvas に描画することができないという欠点があります。
通常の描画方法:
let canvas2d = document.createElement('canvas').getContext('2d')
let img = new Image()
image.src='a.jpg'
// image会自动请求
image.onload = ()=>{
canvas2d.drawImage(img,0,0)
// 成功绘制
}
プロキシ インターセプトを追加した後:
function hookFunction(src){
// hook的url
}
function FakeImage(){
const img = new Image()
const handler = {
set(obj, prop, value) {
if ((prop === 'src')) {
console.log('Hook set src',value);
obj[prop] = hookFunction(src)
} else {
return Reflect.set(...arguments);
}
}
}
return new Proxy(img,handler)
}
let canvas2d = document.createElement('canvas').getContext('2d')
let img = new FakeImage()
image.src='a.jpg'
// image会自动请求
image.onload = ()=>{
canvas2d.drawImage(img,0,0)
// 绘制出错,img为Proxy对象,不是HTMLImageElement
}
srcを変更したのにキャンバスに描画できないので、元のsetterを保存したままObject.definePropertyを使用してHTMLImageElementの自動リクエストを維持するのが解決策です。
function hookFunction(src){
// hook的url
}
function FakeImage(){
const img = new Image()
// 保存原有的setter
const originalSet = Object.getOwnPropertyDescriptor(img.__proto__,'src').set
Object.defineProperty(img,'src',{
set:(src)=>{
console.log('Hook set src',value)
// call原来的setter以触发自动请求
originalSet.call(img,value)
}
})
return img
}
let canvas2d = document.createElement('canvas').getContext('2d')
let img = new FakeImage()
image.src='a.jpg'
// image会自动请求
image.onload = ()=>{
canvas2d.drawImage(img,0,0)
// 绘制成功且hook成功
}