1 Star 0 Fork 0

tea-sea-sun/m3u8-downloader

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
mitm.html 5.74 KB
一键复制 编辑 原始数据 按行查看 历史
<!-- 中间层页面,专门用于下载,在此页面中注册 serviceWorker,并实现拦截 -->
<!-- 本页面存在的意义,在于隔离 web 主进程的请求,让 serviceWorker 仅拦截本页面的请求 -->
<!-- serviceWorker 完全异步,全程 API 均使用 Promise 完成异步操作 -->
<script>
// 保活,每 10s 执行一次 ping,避免 serviceWorker 被删除
let keepAlive = () => {
keepAlive = () => { }
var ping = location.href.substr(0, location.href.lastIndexOf('/')) + '/ping'
var interval = setInterval(() => {
if (serviceWorker) {
serviceWorker.postMessage('ping')
} else {
fetch(ping).then(res => res.text(!res.ok && clearInterval(interval)))
}
}, 10000)
}
let scope = '' // 当前 serviceWorker 所在域,是其唯一标识符
let serviceWorker = null // serviceWorker 实例
let tempMessageStore = [] // 在处理函数未准备好之前,临时存储的 message
// 进入页面马上进行消息监听,再后续处理函数 ready 后,再触发这些 message 的处理
window.onmessage = evt => tempMessageStore.push(evt)
// 注册 serviceWorker,检测是否有旧的实例,进行复用。
function registerWorker() {
// 获取 ./ 域下已经注册过的 serviceWorker,getRegistration 返回单个,getRegistrations 返回所有
return navigator.serviceWorker.getRegistration('./')
.then(serviceWorkerRegistration => {
// 如果已经存在注册过的 serviceWorkerRegistration,则直接返回,否则产生新的一个
return serviceWorkerRegistration || navigator.serviceWorker.register('serviceWorker.js', { scope: './' })
}).then(serviceWorkerRegistration => {
scope = serviceWorkerRegistration.scope // 保存所在域
// 如果注册已就绪,则直接赋值并返回
if (serviceWorkerRegistration.active) {
serviceWorker = serviceWorkerRegistration.active
return
}
// 如果处于注册中,返回 promise,并监听其状态变更,等待其就绪状态
const swRegTmp = serviceWorkerRegistration.installing || serviceWorkerRegistration.waiting
return new Promise(resolve => {
const onStatechange = () => {
if (swRegTmp.state === 'activated') {
swRegTmp.removeEventListener('statechange', onStatechange)
serviceWorker = serviceWorkerRegistration.active
resolve()
}
}
swRegTmp.addEventListener('statechange', onStatechange)
})
})
}
// 消息监听,监听 web 主进程发送过来的消息,并进行数据中转,及数据的处理与转译
function onMessage(event) {
let {
data, // 数据
ports, // channel 所在渠道
origin // 消息作用域
} = event
console.log('onMessage', event)
// 检测消息通道
if (!ports || !ports.length) {
throw new TypeError("[StreamSaver] You didn't send a messageChannel")
}
// 检测接受的数据实体
if (typeof data !== 'object') {
throw new TypeError("[StreamSaver] You didn't send a object")
}
// 检查 readableStream
if (data.readableStream) {
console.warn("[StreamSaver] You should send the readableStream in the messageChannel, not throught mitm")
}
// 检查 pathname
if (!data.pathname) {
console.warn("[StreamSaver] Please send `data.pathname` (eg: /pictures/summer.jpg)")
data.pathname = Math.random().toString().slice(-6) + '/' + data.filename
}
/** @since v2.0.0 */
if (!data.headers) {
console.warn("[StreamSaver] pass `data.headers` that you would like to pass along to the service worker\nit should be a 2D array or a key/val object that fetch's Headers api accepts")
} else {
// test if it's correct
// should throw a typeError if not
new Headers(data.headers)
}
// the default public service worker for StreamSaver is shared among others.
// so all download links needs to be prefixed to avoid any other conflict
data.origin = origin
// if we ever (in some feature versoin of streamsaver) would like to
// redirect back to the page of who initiated a http request
data.referrer = data.referrer || document.referrer || origin
// 删除所有前导斜杠
data.pathname = data.pathname.replace(/^\/+/g, '')
// remove protocol
// 去除协议
let org = origin.replace(/(^\w+:|^)\/\//, '')
// 设置绝对路径,以用于下载
data.url = new URL(`${scope + org}/${data.pathname}`).toString()
// 检查路径是否合法
if (!data.url.startsWith(`${scope + org}/`)) {
throw new TypeError('[StreamSaver] bad `data.pathname`')
}
// This sends the message data as well as transferring
// messageChannel.port2 to the service worker. The service worker can
// then use the transferred port to reply via postMessage(), which
// will in turn trigger the onmessage handler on messageChannel.port1.
const transferable = data.readableStream
? [ports[0], data.readableStream]
: [ports[0]]
if (!(data.readableStream || data.transferringReadable)) {
keepAlive()
}
// 将从 web 主进程接收到的数据,传输给 serviceWorker 接收
return serviceWorker.postMessage(data, transferable)
}
// 消息回调,告知主进程,本页面已准备就绪
if (window.opener) {
window.opener.postMessage('StreamSaver::loadedPopup', '*')
}
// 注册完成,并进行消息处理
if (navigator.serviceWorker) {
registerWorker().then(() => {
window.onmessage = onMessage
tempMessageStore.forEach(window.onmessage) // 将之前临时存储的 message 放入处理函数中执行
})
} else {
keepAlive()
}
</script>
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/tea-sea-sun/m3u8-downloader.git
git@gitee.com:tea-sea-sun/m3u8-downloader.git
tea-sea-sun
m3u8-downloader
m3u8-downloader
master

搜索帮助