как зарегистрировать работника службы из другого поддомена
У меня есть два поддомена: https://abc.xxxx.com и https://xyz.xxxx.com . Итак, мои вопросы:
1). можно ли зарегистрировать работника службы для
https://xyz.xxxx.com из https://abc.xxxx.com ? если да, то как?
2). если http://abc.xxxx.com (протокол HTTP небезопасно) потом все равно регистрировать
работник службы для https://xyz.xxxx.com из http://abc.xxxx.com как в iframe или что-то....
Это реальная ситуация, с которой я сталкиваюсь для моего множественного поддомена. Любая помощь ценится. Заранее спасибо.
3 ответов:
Вот некоторые общие ответы, которые, я думаю, должны касаться различных моментов, которые вы поднимаете в своем вопросе:
С каждым зарегистрированным работником службы связан
scope, это определяет набор веб-страниц, которыми может управлять работник службы.scopeработника службы является URL-адресом, и этот URL-адрес должен иметь тот же источник, что и страница, на которой зарегистрирован работник службы, и должен быть либо URL-адресом, соответствующим тому же уровню пути, что и страница, либо путем это на один или несколько уровней ниже. Значение по умолчаниюscopeсоответствует тому же уровню пути, что и расположение сценария Service worker. Из-за этого ограничения невозможно вызватьnavigator.serviceWorker.register(...)со страницы в одном (поддомене)домене и в конечном итоге получить работника службы, который управляет страницами в другом (поддомене)домене.Существуют ограничения, которые не позволяют вам бросать мяч.
https:<iframe>на страницеhttp:и использовать ее для регистрации работника службы. Смотрите исключение DOMException, когда Регистрация Service worker внутри https iframeХотя я не знаю, что это напрямую связано с вашим вопросом, явный вызов
fetch()для ресурсаhttp:в вашем служебном коде приведет к сбою в текущих версиях Chrome, так как смешанное содержимоеfetch()не допускается в служебном коде. Я не знаю, все ли на 100% улажено на этом фронте, и эта открытая ошибка все еще актуальна.Если у вас есть страницы которые живут на обоих
abc.123.comиxyz.123.com, и вы хотите, чтобы оба набора страниц контролировались работником службы, тогда вам нужно иметь две отдельные регистрации работника службы. Каждая регистрация должна быть для копии вашего JS-файла service worker, размещенного в соответствующем домене, соответствующем странице верхнего уровня, и все страницы и сценарии service worker должны быть доступны черезhttps:.Таким образом, Вы можете начать регистрацию работника службы для другого домен путем включения кросс-домена
<iframe>на странице, но и хост-страница, и<iframe>должны обслуживаться черезhttps:. Применяются обычные ограничения области действия Service worker, поэтому если, например, вы хотите зарегистрировать service worker для другого домена, который будет охватывать всю областьhttps://other-domain.com/, вам нужно убедиться, что местоположение регистрируемого сценария service worker находится на верхнем уровне, напримерhttps://other-domain.com/service-worker.js, а не наhttps://other-domain.com/path/to/service-worker.js. Такой подход используется, например, в проекте AMP через посредство<amp-install-serviceworker>элемент .
Service Worker scripts must be hosted at the same origin (Protocol + Domain name + Port).каждый поддомен считается разным по происхождению, поэтому вам нужно будет зарегистрировать работника службы для каждого из них. У каждого из этих работников будут своиcacheиscope.
Моя беда, я немного неправильно понял. Ну, вот код
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_sender_id и gcm_user_visible_only
Вам нужно создать ключ как для серверных, так и для браузерных приложений, здесь вы найдете дополнительную информацию об этом. страница.
Https://developers.google.com/web/updates/2015/03/push-notificatons-on-the-open-web?hl=en
Тот, что для браузерных приложений, входит в ваш манифест json.
Затем для отправки push-уведомлений вы будете использовать что-то вроде этого:
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); } } }И нет, я не знаю, какая проблема у вас была, но это работает для меня с несколькими поддоменами. :)
Comments