Javascript 如何注册来自不同子域的服务工作者
我有两个子域:和。所以我的问题是: 1) 。是否可以为注册一名服务人员 从…起如果是,那怎么办 2) 。如果(http不安全),则无论如何都要注册 iframe之类的服务人员Javascript 如何注册来自不同子域的服务工作者,javascript,service-worker,progressive-web-apps,Javascript,Service Worker,Progressive Web Apps,我有两个子域:和。所以我的问题是: 1) 。是否可以为注册一名服务人员 从…起如果是,那怎么办 2) 。如果(http不安全),则无论如何都要注册 iframe之类的服务人员 这是一个真实的情况,我面对的是我的多个子域名。谢谢你的帮助。提前谢谢。我的错,我有点误解了。这是密码 if('serviceWorker' in navigator){ if(window.location.pathname != '/'){ //register with API
这是一个真实的情况,我面对的是我的多个子域名。谢谢你的帮助。提前谢谢。我的错,我有点误解了。这是密码
if('serviceWorker' in navigator){
if(window.location.pathname != '/'){
//register with API
if(!navigator.serviceWorker.controller) navigator.serviceWorker.register('/service-worker', { scope: '/' });
//once registration is complete
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration){
//get subscription
serviceWorkerRegistration.pushManager.getSubscription().then(function(subscription){
//enable the user to alter the subscription
//jquery selector for enabling whatever you use to subscribe.removeAttr("disabled");
//set it to allready subscribed if it is so
if(subscription){
//code for showing the user that they're allready subscribed
}
});
});
}
}else{
console.warn('Service workers aren\'t supported in this browser.');
}
下面是您的订阅/取消订阅活动
// subscribe or unsubscribe to the ServiceWorker
$(document.body).on('change', /*selector*/, function(){
//new state is checked so we subscribe
if($(this).prop('checked')){
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration){
serviceWorkerRegistration.pushManager.subscribe()
.then(function(subscription){
// The subscription was successful
console.log('subscription successful'); //subscription.subscriptionId
//save in DB - this is important because
$.post($('#basePath').val() + 'settings/ajax-SW-sub/', {id:subscription.subscriptionId}, function(data){
//console.log(data);
}, 'json');
}).catch(function(e) {
if (Notification.permission === 'denied') {
// The user denied the notification permission which
// means we failed to subscribe and the user will need
// to manually change the notification permission to
// subscribe to push messages
console.warn('Permission for Notifications was denied');
} else {
// A problem occurred with the subscription; common reasons
// include network errors, and lacking gcm_sender_id and/or
// gcm_user_visible_only in the manifest.
console.error('Unable to subscribe to push.', e);
}
});
});//*/
//new state us unchecked so we unsubscribe
}else{
$('.js-enable-sub-test').parent().removeClass('checked');
//get subscription
navigator.serviceWorker.ready.then(function(reg) {
reg.pushManager.getSubscription().then(function(subscription) {
//unregister in db
$.post($('#basePath').val() + 'settings/ajax-SW-unsub/', {id:subscription.subscriptionId}, function(data){
//console.log(data);
}, 'json');
//remove subscription from google servers
subscription.unsubscribe().then(function(successful) {
// You've successfully unsubscribed
console.log('unsubscribe successful');
}).catch(function(e) {
// Unsubscription failed
console.log('unsubscribe failed', e);
})
})
});//*/
}
});
之后,您需要在google开发者控制台上注册一个帐户,并注册一个类似*.xxxx.com的项目。然后,您需要获得一个正确的清单json,其中只有gcm\u发送者\u id和gcm\u用户\u可见
您需要为服务器和浏览器应用程序创建一个密钥,本页提供了更多信息
浏览器应用程序的一个在清单json中
然后,要发送推送通知,您将使用以下方法:
function addSWmessage($args){
$output = false;
if(!isset($args['expiration']) || $args['expiration'] == ''){
$args['expiration'] = date('Y-m-d H:i:s', strtotime('+7 days', time()));
}
$sql = sprintf("INSERT INTO `serviceworker_messages` SET title = '%s', body = '%s', imageurl = '%s', linkurl = '%s', hash = '%s', expiration = '%s'",
parent::escape_string($args['title']),
parent::escape_string($args['text']),
parent::escape_string($args['imageurl']),
parent::escape_string($args['linkurl']),
parent::escape_string(md5(uniqid('******************', true))),
parent::escape_string($args['expiration']));
if($id = parent::insert($sql)){
$output = $id;
}
return $output;
}
function pushSWmessage($args){
//$args['messageid'] $args['userids'][]
foreach($args['userids'] as $val){
$sql = sprintf("SELECT messages_mobile, messages FROM `users_serviceworker_hash` WHERE users_id = '%s'",
parent::escape_string($val));
if($row = parent::queryOne($sql)){
$m1 = json_decode($row['messages'], true);
$m1[] = $args['messageid'];
$m2 = json_decode($row['messages_mobile'], true);
$m2[] = $args['messageid'];
$sql = sprintf("UPDATE `users_serviceworker_hash` SET messages = '%s', messages_mobile = '%s' WHERE users_id = '%s'",
parent::escape_string(json_encode($m1)),
parent::escape_string(json_encode($m2)),
parent::escape_string($val['users_id']));
parent::insert($sql);
}
}
$sql = sprintf("SELECT subscriptionID, users_id FROM `users_serviceworker_subscriptions`");
if($rows = parent::query($sql)){
foreach($rows as $val){
if(in_array($val['users_id'], $args['userids'])){
$registrationIds[] = $val['subscriptionID'];
}
}
if(isset($registrationIds) && !empty($registrationIds)){
// prep the bundle
$msg = array
(
'message' => '!',
'title' => '!',
'subtitle' => '!',
'tickerText' => '!',
'vibrate' => 1,
'sound' => 1,
'largeIcon' => '!',
'smallIcon' => '!'
);
$headers = array
(
'Authorization: key='.SW_API_ACCESS_KEY,
'Content-Type: application/json'
);
$fields = array
(
'registration_ids' => $registrationIds,
'data' => $msg
);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send');
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch,CURLOPT_POSTFIELDS, json_encode($fields));
curl_exec($ch);
curl_close($ch);
}
}
}
不,我不知道您遇到了什么问题,但这对我来说适用于多个子域。:) 以下是一些一般性的答案,我认为这些答案可以解决您在问题中提出的各种问题:
- 每个已注册的服务人员都有一个关联的web页面,它指示服务人员可以控制的web页面集。服务工作者的
范围是一个URL,该URL必须与注册服务工作者的页面具有相同的来源,并且必须是与页面对应的路径级别的URL,或者是向下一级或多级的路径。默认的
对应于与服务工作者脚本位置相同的路径级别。由于此限制,无法从一个(子)域上的页面调用范围
,最终由一个服务工作者控制另一个(子)域上的页面navigator.serviceWorker.register(…)
- 存在一些限制,防止您在
页面上抛出http:
https:
,并使用该页面注册服务人员。看
- 虽然我不知道这与您的问题有直接关系,但在您的服务人员代码中显式调用
以获取fetch()
资源将导致当前版本的Chrome失败,因为服务人员中不允许混合内容http:
s。我不知道这方面的事情是否已经100%解决,是否仍然相关fetch()
abc.123.com
和xyz.123.com
上,并且您希望这两组页面都由服务人员控制,那么您需要有两个独立的服务人员注册。每次注册都需要一份service worker JS文件的副本,该文件位于顶级页面对应的相应域中,所有页面和service worker脚本都需要通过https:
访问
也就是说,您可以通过在页面上包含跨域的
来启动不同域的服务人员注册,但主机页和
都需要通过https:
提供服务。正常的服务工作者范围限制适用,因此,例如,如果您希望为覆盖整个https://other-domain.com/
scope,您需要确保正在注册的service worker脚本的位置位于顶层,例如,https://other-domain.com/service-worker.js
,而不是在https://other-domain.com/path/to/service-worker.js
。例如,这是via使用的方法。服务工作者脚本必须托管在同一个源(协议+域名+端口)。
每个子域都被视为不同的源,因此,您需要为每个子域注册一个服务工作者。每个工作进程都有自己的缓存
和范围
尝试使用Ngnix proxy\u pass。这对我来说很有用。与jQuery有任何关系吗?不是直接的,我想可能会有帮助,以防像ifame之类的打开窗口……无论如何,删除了它。你能修复它吗?。我也有类似的问题。谢谢你们的回答,但我想你们并没有理解我的问题。很抱歉,若我的问题的意思出错了。我的问题是关于服务人员的注册,而不是在承诺(fetch)中拦截请求。谢谢您的努力!!但是我的问题对于注册一个服务人员来说是非常具体的,这个服务人员的代码存在于其他子域中……正确。两者的答案都是否定的。好吧,让我再做一些搜索,如果找到相同的,那么我会将你的答案标记为接受。谢谢你的帮助,我最初的解释有一些技术错误。我已经把它清理干净了。@JeffPosnick:当一个子域完全不存在时,“否”仍然适用吗?也就是说,如果有example.com
的服务工作者,它对subdomain.example.com
没有影响吗?example.com上的软件无法控制subdomain.example.com上的任何东西。在这种情况下,这两个源将是不同的,并且没有“超集”源的概念。如果端口不同,我该如何实现这一点?(在本地主机上)