{"id":306734,"date":"2020-07-10T09:00:27","date_gmt":"2020-07-10T09:00:27","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=306734"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=306734","title":{"rendered":"\u0412\u043d\u0435\u0434\u0440\u044f\u0435\u043c \u043a\u0440\u043e\u0441\u0441-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0443\u0448-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f: \u043d\u0430\u0447\u0430\u043b\u043e"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/510354\/\">\n<p>\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0412\u043b\u0430\u0434\u0438\u043c\u0438\u0440 \u0421\u0442\u043e\u043b\u044f\u0440\u043e\u0432, \u044f \u0431\u044d\u043a\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 \u0414\u043e\u043c\u041a\u043b\u0438\u043a\u0435. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u043a\u0440\u043e\u0441\u0441-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0443\u0448-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f. \u0425\u043e\u0442\u044f \u043f\u0440\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0435\u043c\u0430\u043b\u043e, \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u044e\u0430\u043d\u0441\u0430\u0445, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441 \u0432\u0430\u043c\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0443\u0448\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/-x\/zg\/ww\/-xzgwwcse6ekckljinmc2cbvses.png\"><\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0443\u0434\u0430 \u043c\u044b \u0432\u043e\u043e\u0431\u0449\u0435 \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0443\u0448\u0438. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u0432\u0435\u0431-\u0441\u0430\u0439\u0442, iOS-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 Android-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0432\u0435\u0431-\u043f\u0443\u0448\u0435\u0439. \u0414\u043b\u044f \u0438\u0445 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0432\u043e\u0435\u043c\u0443 \u043f\u0443\u0448-\u0441\u0435\u0440\u0432\u0435\u0440\u0443, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0441\u0435\u0440\u0432\u0438\u0441-\u0432\u043e\u0440\u043a\u0435\u0440 (\u0432 \u043d\u0435\u043c \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>push<\/code>). \u041d\u044e\u0430\u043d\u0441 \u0442\u0443\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043f\u0443\u0448-\u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u0432\u043e\u0439: <\/p>\n<p>  <\/p>\n<ul>\n<li>\u0423 Firefox \u043e\u043d \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <a href=\"https:\/\/mozilla-push-service.readthedocs.io\/en\/latest\/\">Mozilla Push Service<\/a>. \u0415\u0433\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u044b, \u0447\u0435\u043c \u043c\u044b \u043f\u043e\u0437\u0436\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c.<\/li>\n<li>\u0423 Chrome \u044d\u0442\u043e Google Cloud Messaging (\u043d\u0435 Firebase Cloud Messaging, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043f\u043e \u0438\u043c\u0435\u043d\u0430\u043c \u0434\u043e\u043c\u0435\u043d\u043e\u0432 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u043a\u043e\u0434\u0435), \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u0430\u044f \u043d\u043e\u0432\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043d\u0430\u0441 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0435\u0431-\u043f\u0443\u0448\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b IETF (<a href=\"https:\/\/datatracker.ietf.org\/wg\/webpush\/documents\/\">https:\/\/datatracker.ietf.org\/wg\/webpush\/documents\/<\/a>), \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b API \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043a\u0430\u043a \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u0442\u0430\u043a \u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0430 \u0431\u0430\u0437\u0435 Android. \u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432: <\/p>\n<p>  <\/p>\n<ul>\n<li>\u0415\u0441\u043b\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b Google Apps, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Firebase Cloud Messaging.<\/li>\n<li>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043e\u0442 Huawei \u0431\u0435\u0437 Google Apps, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Huawei Push Kit.<\/li>\n<li>\u041c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0443\u0448-\u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u043b\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u043c\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/bubu1.eu\/openpush\/\">https:\/\/bubu1.eu\/openpush\/<\/a>, \u0431\u043b\u0430\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0441\u0442\u044c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u0434\u0435\u0442 iOS. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Android, \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 Apple \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u0438\u043d \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Apple Push Notification service (APNs).<\/p>\n<p>  <\/p>\n<p>\u041c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441: \u043d\u0435\u0443\u0436\u0435\u043b\u0438 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0451 \u044d\u0442\u043e \u043c\u043d\u043e\u0433\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u0432, API \u0438 \u043f\u0440\u043e\u0447\u0435\u0433\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435? \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0432\u0441\u0451 \u043d\u0435 \u0442\u0430\u043a \u0443\u0436 \u0438 \u043f\u043b\u043e\u0445\u043e, \u0442\u0430\u043a \u043a\u0430\u043a Firebase Cloud Messaging, \u043f\u043e\u043c\u0438\u043c\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043d\u0430 Android, \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0435\u0449\u0435 \u0438 \u0432\u0435\u0431-\u043f\u0443\u0448\u0438 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 APNs. \u0422\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0445\u0435\u043c\u0435: \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 Huawei \u0431\u0435\u0437 Google Apps \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0447\u0435\u0440\u0435\u0437 Huawei Push Kit, \u0432 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f Firebase Cloud Messaging.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/qa\/ge\/am\/qageampihx2hkgoy4mawznpw7pm.png\"><\/p>\n<p>  <\/p>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043c\u043d\u043e\u0433\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u0432 \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0441\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0439:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a \u043f\u0443\u0448-\u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u2014 \u0442\u043e\u043a\u0435\u043d.<\/li>\n<li>\u041a\u043b\u0438\u0435\u043d\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u043e\u043a\u0435\u043d \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0441\u0442\u0430\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u044b\u043c \u0441 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/li>\n<li>\u0421\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c\u0443 \u0442\u043e\u043a\u0435\u043d\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0443\u0448\u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/li>\n<\/ol>\n<p>  <\/p>\n<h1 id=\"poprobuem-napisat-testovoe-prilozhenie\">\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h1>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d \u043e\u0442 Firebase \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0448. \u041d\u0443\u0436\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 <a href=\"https:\/\/console.firebase.google.com\/\">\u043a\u043e\u043d\u0441\u043e\u043b\u0438 Firebase<\/a> \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u0436\u0435\u043d \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u0441\u0442\u0430\u0442\u0438\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441 \u043e\u0434\u043d\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">simple_example.html<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"html\">&lt;!DOCTYPE html&gt; &lt;html&gt;     &lt;head&gt;         &lt;meta charset=&quot;utf-8&quot;&gt;         &lt;title&gt;\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0438\u0435\u043c\u0430 \u043f\u0443\u0448\u0435\u0439&lt;\/title&gt;     &lt;\/head&gt;     &lt;body&gt;     &lt;script src=&quot;https:\/\/www.gstatic.com\/firebasejs\/7.14.5\/firebase-app.js&quot;&gt;&lt;\/script&gt;     &lt;script src=&quot;https:\/\/www.gstatic.com\/firebasejs\/7.14.5\/firebase-messaging.js&quot;&gt;&lt;\/script&gt;     &lt;script&gt;         function toClipboard(text) {             const tmp = document.createElement('textarea');             tmp.hidden = true;             tmp.value = text;             window.document.body.appendChild(tmp);             tmp.select();             window.document.execCommand(&quot;copy&quot;);             alert(&quot;Copied the text: &quot; + text);             window.document.body.removeChild(tmp);         }     &lt;\/script&gt;     &lt;button onclick=&quot;enableNotifications()&quot;&gt;\u041f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f&lt;\/button&gt;     &lt;div id=&quot;pushTokenLayer&quot; hidden&gt;         Firebase token &lt;code id=&quot;pushTokenValue&quot; style=&quot;cursor:pointer&quot; onclick=&quot;toClipboard(this.innerText)&quot;&gt;&lt;\/code&gt;&lt;br\/&gt;     &lt;\/div&gt;     &lt;script&gt;         async function enableNotifications() {             \/\/ Insert your firebase project config here             const firebaseConfig = {};              const app = firebase.initializeApp(firebaseConfig);             const messaging = app.messaging();              const permission = await Notification.requestPermission();             if (permission !== 'granted') {                 console.log(&quot;user denied notifications&quot;)             }              const token = await messaging.getToken();              window.document.getElementById(&quot;pushTokenLayer&quot;).removeAttribute(&quot;hidden&quot;);              const pushTokenValue = window.document.getElementById(&quot;pushTokenValue&quot;);             pushTokenValue.innerText = token         }     &lt;\/script&gt;     &lt;\/body&gt; &lt;\/html&gt;<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442 \u0441\u0435\u0440\u0432\u0438\u0441-\u0432\u043e\u0440\u043a\u0435\u0440\u0430. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u043d \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e \u043f\u0443\u0442\u0438 <code>\/firebase-messaging-sw.js<\/code>. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 <a href=\"https:\/\/firebase.google.com\/docs\/cloud-messaging\/js\/receive\">\u043e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443, \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d. \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 API \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043e\u043b\u0433\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 (\u043d\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442). \u0414\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">curl -X POST 'https:\/\/fcm.googleapis.com\/fcm\/send' \\ -H 'Authorization: key=&lt;fcm server key&gt;' \\ -H 'Content-Type: application\/json' \\ -d '{  &quot;to&quot; : &quot;&lt;\u0442\u043e\u043a\u0435\u043d \u0438\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430&gt;&quot;,  &quot;notification&quot; : {      &quot;body&quot; : &quot;Body of Your Notification&quot;,      &quot;title&quot;: &quot;Title of Your Notification&quot;  } }'<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/_d\/_2\/nr\/_d_2nrysytrobtgw_txicwetag8.png\"><\/p>\n<p>  <\/p>\n<p>\u0422\u0443\u0442 \u0435\u0441\u0442\u044c \u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0431\u044b\u0442\u044c: <strong>\u043f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043e\u043d \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u043c<\/strong> (\u0442.\u0435. \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439). \u041d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u043e\u043d \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u0435\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440. \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043e\u043f\u0438\u0441\u0430\u043d \u043a\u043e\u043b\u0431\u044d\u043a <code>setBackgroundMessageHandler<\/code>. \u041c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441-\u0432\u043e\u0440\u043a\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0432 \u043a\u043e\u043d\u0435\u0446 \u0444\u0430\u0439\u043b\u0430 \u043a\u043e\u0434:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">messaging.setBackgroundMessageHandler((payload) =&gt; {   console.log('Message received. ', payload);   \/\/ ... });<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0441\u0435\u0440\u0432\u0438\u0441-\u0432\u043e\u0440\u043a\u0435\u0440\u0430, \u0441\u043d\u043e\u0432\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0443\u0448\u2026 \u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0432\u0438\u0434\u0438\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438, \u0445\u043e\u0442\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u043e\u0441\u044c. \u041f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435? \u041e\u0442\u0432\u0435\u0442 \u0432 \u0435\u0441\u0442\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<blockquote><p>Note: If you set notification fields in your message payload, your setBackgroundMessageHandler callback is not called, and instead the SDK displays a notification based on your payload.<\/p><\/blockquote>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 <code>notification<\/code> \u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043b\u0431\u044d\u043a \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f. <strong>\u042d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0432\u0430\u0436\u043d\u043e\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435, \u043a \u043d\u0435\u043c\u0443 \u043c\u044b \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435.<\/strong><\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u043e\u0431\u043e\u0439\u0442\u0438, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043f\u0443\u0448\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u041f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <code>firebase-messaging-sw.js<\/code>:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">firebase-messaging-sw.js<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">self.addEventListener(&quot;push&quot;, event =&gt; { event.waitUntil(onPush(event)) });  async function onPush(event) {     const push = event.data.json();     console.log(&quot;push received&quot;, push)      const { notification = {} } = {...push};      await self.registration.showNotification(notification.title, {         body: notification.body,     }) }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0432 json \u0438 \u043f\u0430\u0440\u0441\u0438\u043c \u0435\u0435 \u0432 js-\u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u0435\u0434\u0435\u043d \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c, \u0437\u0430\u043e\u0434\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <code>waitUntil<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430: \u043e\u043d \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0440\u0432\u0438\u0441-\u0432\u043e\u0440\u043a\u0435\u0440 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b \u0440\u0430\u0431\u043e\u0442\u0443 \u0434\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 <code>onPush<\/code>.<\/p>\n<p>  <\/p>\n<h2 id=\"teper-dobavim-polzovateley-v-nashe-prilozhenie\">\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0437\u0430\u0432\u0435\u0434\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">user_example.html<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"html\">&lt;!DOCTYPE html&gt; &lt;html&gt;     &lt;head&gt;         &lt;meta charset=&quot;utf-8&quot;&gt;         &lt;title&gt;\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0438\u0435\u043c\u0430 \u043f\u0443\u0448\u0435\u0439&lt;\/title&gt;     &lt;\/head&gt;     &lt;body&gt;     &lt;script src=&quot;https:\/\/www.gstatic.com\/firebasejs\/7.14.5\/firebase-app.js&quot;&gt;&lt;\/script&gt;     &lt;script src=&quot;https:\/\/www.gstatic.com\/firebasejs\/7.14.5\/firebase-messaging.js&quot;&gt;&lt;\/script&gt;     &lt;script&gt;         function toClipboard(text) {             const tmp = document.createElement('textarea');             tmp.hidden = true;             tmp.value = text;             window.document.body.appendChild(tmp);             tmp.select();             window.document.execCommand(&quot;copy&quot;);             alert(&quot;Copied the text: &quot; + text);             window.document.body.removeChild(tmp);         }     &lt;\/script&gt;     &lt;form onsubmit=&quot;enableNotifications(this); return false&quot; action=&quot;#&quot;&gt;         User ID &lt;input type=&quot;number&quot; name=&quot;userID&quot; required\/&gt;         &lt;input type=&quot;submit&quot; value=&quot;\u041f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f&quot;\/&gt;     &lt;\/form&gt;     &lt;div id=&quot;pushTokenLayer&quot; hidden&gt;         Firebase token &lt;code id=&quot;pushTokenValue&quot; style=&quot;cursor:pointer&quot; onclick=&quot;toClipboard(this.innerText)&quot;&gt;&lt;\/code&gt;&lt;br\/&gt;         &lt;button onclick=&quot;logout()&quot;&gt;\u0412\u044b\u0439\u0442\u0438&lt;\/button&gt;     &lt;\/div&gt;     &lt;script&gt;         \/\/ Insert your firebase project config here         const firebaseConfig = {};          const app = firebase.initializeApp(firebaseConfig);         const messaging = app.messaging(); \/\/ this fails if browser not supported          async function getMe() {             const resp = await fetch(`${window.location.origin}\/api\/v1\/users\/me`, {                 credentials: &quot;include&quot;,             });              if (resp.status === 401) {                 return null;             }             if (!resp.ok) {                 throw `unexpected status code ${resp.status}`             }              return await resp.json();         }          async function sendToken(token) {             const me = await getMe();             if (me === null) {                 console.error(&quot;unauthorized on send token&quot;);                 return;             }              window.localStorage.getItem(&quot;push-token-user&quot;);              const resp = await fetch(`${window.location.origin}\/api\/v1\/tokens`, {                 method: &quot;POST&quot;,                 body: JSON.stringify({                     token: {token: token, platform: &quot;web&quot;}                 }),                 credentials: &quot;include&quot;,             })             if (!resp.ok) {                 console.error(&quot;send token failed&quot;);                 return;             }              \/\/ put current user to local storage for comparison             window.localStorage.setItem(&quot;push-token-user&quot;, JSON.stringify(me));         }          getMe().             then(me =&gt; {                 if (!me) {                     \/\/ if user not authorized we must invalidate firebase registration                     \/\/ to prevent receiving pushes for unauthorized user                     \/\/ this may happen i.e. if 'deleteToken' failed on logout                     console.log(`user unauthorized, invalidate fcm registration`);                     window.localStorage.removeItem(&quot;push-token-user&quot;);                     messaging.deleteToken();                     return null;                 }                  \/\/ if user authorized and it's not user that received push token earlier                 \/\/ we also must invalidate token to prevent receiving pushes for wrong user                 \/\/ this may happen if i.e. user not logged out explicitly                 let pushTokenUser = window.localStorage.getItem(&quot;push-token-user&quot;);                 if (pushTokenUser &amp;&amp; JSON.parse(pushTokenUser).id !== me.id) {                     console.log(&quot;token for wrong user, invalidate fcm registration&quot;);                     window.localStorage.removeItem(&quot;push-token-user&quot;);                     messaging.deleteToken();                     pushTokenUser = null;                 }                  \/\/ if user authorized and permission granted but token wasn't send we should re-send it                 if (!pushTokenUser &amp;&amp; Notification.permission === &quot;granted&quot;) {                     console.log(&quot;token not sent to server while notification permission granted&quot;);                     messaging.getToken().then(sendToken);                 }             }).             catch(e =&gt; console.log(&quot;get me error&quot;, e))          \/\/ according to sources of firebase-js-sdk source code registration token refreshed once a week         messaging.onTokenRefresh(async () =&gt; {             const newToken = await messaging.getToken();             pushTokenValue.innerText = newToken;             console.log(`updated token to ${newToken}`)             await sendToken(newToken)         })          async function enableNotifications(form) {             const loginResponse = await fetch(`${window.location.origin}\/api\/v1\/users\/login`, {                 method: &quot;POST&quot;,                 body: JSON.stringify({                     id: Number(form.elements.userID.value),                 })             })             if (!loginResponse.ok) {                 alert(&quot;login failed&quot;);                 return;             }              const permission = await Notification.requestPermission();             if (permission !== 'granted') {                 console.log(&quot;user denied notifications&quot;)                 return;             }              const token = await messaging.getToken();              window.document.getElementById(&quot;pushTokenLayer&quot;).removeAttribute(&quot;hidden&quot;);              const pushTokenValue = window.document.getElementById(&quot;pushTokenValue&quot;);             pushTokenValue.innerText = token              await sendToken(token)         }          async function logout() {             const messaging = firebase.messaging();             await messaging.deleteToken();             console.log(`deleted token from firebase`)             window.document.getElementById(&quot;pushTokenLayer&quot;).setAttribute(&quot;hidden&quot;, &quot;&quot;);             await fetch(`${window.location.origin}\/api\/v1\/users\/logout`, {                 method: &quot;POST&quot;,                 credentials: &quot;include&quot;,             })         }     &lt;\/script&gt;     &lt;\/body&gt; &lt;\/html&gt;<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u0431\u044d\u043a\u0435\u043d\u0434, \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 Go. \u0422\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0434\u0430, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0435\u0433\u043e \u0437\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u0432:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">inmemory.go<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">type MemoryStorage struct {     mu          sync.RWMutex     userTokens  map[uint64][]Token     tokenOwners map[string]uint64 }  func NewMemoryStorage() *MemoryStorage {     return &amp;MemoryStorage{         userTokens:  map[uint64][]Token{},         tokenOwners: map[string]uint64{},     } }  type Token struct {     Token    string `json:&quot;token&quot;`     Platform string `json:&quot;platform&quot;` }  func (ms *MemoryStorage) SaveToken(ctx context.Context, userID uint64, token Token) error {     ms.mu.Lock()     defer ms.mu.Unlock()      owner, ok := ms.tokenOwners[token.Token]     \/\/ if old user comes with some token it's ok     if owner == userID {         return nil     }     \/\/ if new user come with existing token we     \/\/ should change it's owner to prevent push target mismatch     if ok {         ms.deleteTokenFromUser(token.Token, owner)     }      ut := ms.userTokens[userID]     ut = append(ut, token)     ms.userTokens[userID] = ut      ms.tokenOwners[token.Token] = userID      return nil }  func (ms *MemoryStorage) deleteTokenFromUser(token string, userID uint64) {     ut := ms.userTokens[userID]     for i, t := range ut {         if t.Token == token {             ut[i], ut[len(ut)-1] = ut[len(ut)-1], Token{}             ut = ut[:len(ut)-1]             break         }     }     ms.userTokens[userID] = ut }  func (ms *MemoryStorage) UserTokens(ctx context.Context, userID uint64) ([]Token, error) {     ms.mu.RLock()     defer ms.mu.RUnlock()      tokens := ms.userTokens[userID]     ret := make([]Token, len(tokens))     copy(ret, tokens)      return ret, nil }  func (ms *MemoryStorage) DeleteTokens(ctx context.Context, tokens []string) error {     ms.mu.Lock()     defer ms.mu.Unlock()      for _, token := range tokens {         user, ok := ms.tokenOwners[token]         if !ok {             return nil         }          ms.deleteTokenFromUser(token, user)     }     return nil }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0412 \u0431\u044d\u043a\u0435\u043d\u0434 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u0443\u0448\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p>  <\/p>\n<p>\u0411\u0430\u0437\u043e\u0432\u043e \u043c\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u043e\u043a\u0430\u0437 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u0438 \u043f\u0440\u0438 \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u041f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0445\/\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u043a\u0443\u043a.<\/li>\n<li>\u041f\u0440\u0438 \u0432\u044b\u0445\u043e\u0434\u0435 \u043c\u044b \u0438\u043d\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u043c \u043f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d. \u041f\u0440\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e Firebase \u043d\u0430\u043c \u043e\u0442\u0432\u0435\u0442\u0438\u0442 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u0442\u043e\u043a\u0435\u043d \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0438 \u043c\u044b \u0443\u0434\u0430\u043b\u0438\u043c \u0435\u0433\u043e \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430.<\/li>\n<li>\u041f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d\u0430 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u0421\u0442\u0430\u0440\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u043c\u044b \u0443\u0434\u0430\u043b\u0438\u043c \u0443\u0436\u0435 \u043f\u0440\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043f\u0443\u0448\u0430.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u043f\u0438\u0448\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0436\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0443\u0436\u0435 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 (\u043e\u043d\u0438 \u043e\u0442\u0440\u0430\u0436\u0435\u043d\u044b \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435):<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d\u044b \u0438\u043c\u0435\u044e\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0441\u0440\u043e\u043a \u0436\u0438\u0437\u043d\u0438, \u043e\u0434\u043d\u0430\u043a\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u0435\u0433\u043e \u0438\u0437 \u0441\u0430\u043c\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430, \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0421\u0443\u0434\u044f \u043f\u043e \u043a\u043e\u0434\u0443 firebase-js-sdk, \u044d\u0442\u043e\u0442 \u0441\u0440\u043e\u043a \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u0434\u0435\u043b\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u043b\u0431\u044d\u043a \u043d\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 <code>onTokenRefresh<\/code> \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437 \u0432 \u043d\u0435\u0434\u0435\u043b\u044e.<\/li>\n<li>\u0420\u0430\u0437\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0441\u043b\u0430\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u043f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d\u044b. \u0422\u0430\u043a\u043e\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0438\u043d\u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0432 Firebase \u043d\u0435 \u043f\u0440\u043e\u0448\u0435\u043b \u0443\u0441\u043f\u0435\u0448\u043d\u043e. \u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043c\u044b \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u0435\u043d\u044f\u0435\u043c \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0430 \u0442\u043e\u043a\u0435\u043d\u0430.<\/li>\n<li>\u0423 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c\u0441\u044f \u0441\u0435\u0441\u0441\u0438\u044f \u0431\u0435\u0437 \u044f\u0432\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0430\u0443\u0442\u0430. \u0422.\u0435. \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d, \u043e\u0434\u043d\u0430\u043a\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0442 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0442\u044c. \u0421\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041c\u044b \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0435\u0449\u0435 \u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441\u0432\u0435\u0440\u044f\u044f \u0435\u0433\u043e \u0441 \u043e\u0442\u0432\u0435\u0442\u043e\u043c \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. \u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u0438\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d, \u0442\u043e \u043f\u0443\u0448-\u0442\u043e\u043a\u0435\u043d \u0438\u043d\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041e\u0434\u043d\u0430\u043a\u043e \u0443 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432\u0441\u0451 \u0436\u0435 \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u043a: \u0438\u043d\u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441\u0430\u0439\u0442\u0430.<\/li>\n<li>\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0439\u0442\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u0442\u043e\u043a\u0435\u043d. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u0430 \u0432 \u0447\u0430\u0442 \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u043f\u0443\u0448\u0430 (\u0432 Android\/iOS \u043c\u043e\u0436\u043d\u043e, \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u2014 \u043d\u0435\u0442), \u043a\u043d\u043e\u043f\u043a\u0438 \u0438 \u043f\u0440\u043e\u0447\u0435\u0435.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0418 \u0432\u043e\u0442, \u0433\u0440\u0430\u0431\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u043d\u044b, \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u044b\u043b\u043e\u0436\u0435\u043d\u044b \u0432 \u043f\u0440\u043e\u0434. \u041f\u0443\u0448\u0438 \u0445\u043e\u0434\u044f\u0442\u2026 \u0438\u043b\u0438 \u043d\u0435 \u0445\u043e\u0434\u044f\u0442? \u0421\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043f\u0440\u043e<\/p>\n<p>  <\/p>\n<h2 id=\"nadezhnost\">\u041d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c<\/h2>\n<p>  <\/p>\n<p>\u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e, \u0445\u043e\u0442\u044f \u0432 Huawei \u043d\u0430\u0434 \u044d\u0442\u0438\u043c \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0438\u0441\u044c \u0438 <a href=\"https:\/\/developer.huawei.com\/consumer\/en\/doc\/development\/HMS-Guides\/push-receipt\">\u0441\u0434\u0435\u043b\u0430\u043b\u0438<\/a>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0430\u043c\u0438\u043c. \u041f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043f\u0443\u0448\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0443\u0448, \u0431\u043b\u0430\u0433\u043e \u0438 Firebase, \u0438 Huawei \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442: \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0418\u0434\u0435\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f: \u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e UUID) \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u043f\u0443\u0448\u0435. \u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0438 \u043f\u043e\u043a\u0430\u0437\u0435 \u043f\u0443\u0448\u0430 \u0434\u0435\u043b\u0430\u0435\u0442 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0441\u043b\u0430\u043d\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f. \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0431\u0435\u043a\u0435\u043d\u0434 \u0438 <code>firebase-messaging-sw.js<\/code>:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">firebase-messaging-sw.js<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">self.addEventListener(&quot;push&quot;, event =&gt; { event.waitUntil(onPush(event)) });  async function onPush(event) {     const push = event.data.json();     console.log(&quot;push received&quot;, push)      const { notification = {}, data = {} } = {...push};      await self.registration.showNotification(notification.title, {         body: notification.body,     })      if (data.id) {         await fetch(`${self.location.origin}\/api\/v1\/notifications\/${data.id}\/confirm`, { method: &quot;POST&quot; })     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0418 \u0435\u0441\u043b\u0438 \u0441 \u0432\u0435\u0431\u043e\u043c \u043d\u0430\u043c \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u043e \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0432\u0441\u0451 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u041f\u043e\u043c\u043d\u0438\u0442\u0435 \u043f\u0440\u043e \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043e <code>setBackgroundMessageHandler<\/code>? \u0422\u0430\u043a \u0432\u043e\u0442, \u0434\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 Firebase (\u0434\u0430 \u0438 \u0432 Huawei) \u0435\u0441\u0442\u044c \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0435 (\u043f\u043e API) \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0430, \u0443\u0441\u043b\u043e\u0432\u043d\u043e, <strong>\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043f\u0443\u0448\u0438<\/strong> (\u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 <code>notification<\/code>) \u0438 <strong>data-\u043f\u0443\u0448\u0438<\/strong>. \u041f\u043e \u0437\u0430\u0434\u0443\u043c\u043a\u0435, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043f\u0443\u0448\u0438 \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438 \u043d\u0430 \u0438\u0445 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0440\u0430\u0437\u0443 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435, \u0430 data-\u043f\u0443\u0448\u0438 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0435\u0448\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c. <\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0432\u0435\u0431-\u043f\u0443\u0448\u0435\u0439 \u0441 \u043d\u0438\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u043e \u043f\u043e\u043a\u0430\u0437\u0430, \u043e\u0442\u043a\u0430\u0437\u0430\u0432\u0448\u0438\u0441\u044c \u043e\u0442 firebase-js-sdk \u0432 \u0441\u0435\u0440\u0432\u0438\u0441-\u0432\u043e\u0440\u043a\u0435\u0440\u0435, \u0442\u043e \u0432 Android \u0442\u0430\u043a \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f Android \u043c\u044b \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u043b\u0438 \u0432\u0441\u044e \u043d\u0443\u0436\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432 data \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c <code>notification<\/code>, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u043d\u0430\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438. <\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f APNs \u0436\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c <code>mutable-content<\/code> \u0432 1, \u0438 \u0442\u043e\u0433\u0434\u0430 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u0443\u0448\u0430 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u0434, \u043d\u043e <a href=\"https:\/\/developer.apple.com\/documentation\/usernotifications\/modifying_content_in_newly_delivered_notifications\">\u0441 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u044b\u043c\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438<\/a>, \u0445\u043e\u0442\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, <strong>\u0438\u043c\u0435\u043d\u043d\u043e \u0438\u0437-\u0437\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 iOS \u043f\u0440\u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0438 \u043f\u0443\u0448\u0430 \u043d\u0435 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f, \u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b<\/strong>.<\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u0441\u044e\u0434\u0430 \u0432\u044b\u0442\u0435\u043a\u0430\u0435\u0442 \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c: data-\u043f\u0443\u0448\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u043e \u0438 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0438 \u043f\u0440\u043e\u0447\u0435\u0433\u043e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Telegram \u043e\u0431\u0445\u043e\u0434\u0438\u043b \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044f \u0430\u0434\u0440\u0435\u0441\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u043f\u0443\u0448\u0438.<\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0434\u043e\u0436\u0434\u0430\u043b\u0438\u0441\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437, \u0441\u043a\u0430\u0436\u0435\u043c, 15 \u043c\u0438\u043d\u0443\u0442 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043c\u0441. \u0410 \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0441\u043b\u0435 \u0441\u043c\u0441 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043f\u0443\u0448, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c <code>TTL<\/code> \u043f\u0440\u0438 \u0435\u0433\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u044d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0441\u0442\u0438. \u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0441\u0442\u044c \u043f\u0443\u0448\u0435\u0439 \u043f\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439:<\/p>\n<p>  <\/p>\n<ul>\n<li>Android (\u0438\u0441\u043a\u043b\u044e\u0447\u0430\u044f Huawei) \u2014 40 %<\/li>\n<li>Web \u2014 50 %<\/li>\n<li>iOS \u2014 70 %<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u043b\u044f Huawei \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u0435\u0449\u0435 \u043d\u0435 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043e. \u0421\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u044b \u043d\u0435 \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b\u0438 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044e \u0434\u043e\u043b\u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0443\u0448\u0435\u0439, \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 <a href=\"https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/462507\">\u042f\u043d\u0434\u0435\u043a\u0441.\u041f\u043e\u0447\u0442\u0435<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0418\u0442\u043e\u0433\u043e\u0432\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u043e\u0439:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ji\/dj\/m1\/jidjm1tpvtdjquk98o7iqaxel08.png\"><\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u043d\u0430 <a href=\"https:\/\/github.com\/xakep666\/push-article\">GitHub<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0447\u0430\u0441\u0442\u044f\u0445 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u0445, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u043f\u0443\u0448-\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438, \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043e \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u044f\u0445 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0432\u0435\u0431-\u043f\u0443\u0448\u0438, \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/510354\/\"> https:\/\/habr.com\/ru\/company\/domclick\/blog\/510354\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/510354\/\">\n<p>\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0412\u043b\u0430\u0434\u0438\u043c\u0438\u0440 \u0421\u0442\u043e\u043b\u044f\u0440\u043e\u0432, \u044f \u0431\u044d\u043a\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 \u0414\u043e\u043c\u041a\u043b\u0438\u043a\u0435. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u043a\u0440\u043e\u0441\u0441-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0443\u0448-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f. \u0425\u043e\u0442\u044f \u043f\u0440\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0435\u043c\u0430\u043b\u043e, \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u044e\u0430\u043d\u0441\u0430\u0445, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441 \u0432\u0430\u043c\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0443\u0448\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/-x\/zg\/ww\/-xzgwwcse6ekckljinmc2cbvses.png\"><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-306734","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/306734","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=306734"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/306734\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=306734"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=306734"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=306734"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}