a piece of Code for webpush on rails
Last active
May 8, 2017 12:13
-
-
Save lanches-kurashita/443c42982a6543a8b846d9a554d83408 to your computer and use it in GitHub Desktop.
Webpush on rails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/views/layout/application.html.slim | |
doctype html | |
html | |
head | |
link rel='manifest' href='/manifest.json' | |
= stylesheet_link_tag 'application', media: 'all' | |
= javascript_tag do | |
= raw "window.vapidPublicKey = new Uint8Array(#{vapid_public_key});\n" | |
... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/controllers/application_controller.rb | |
class ApplicationController < ActionController::Base | |
helper_method :vapid_public_key | |
def vapid_public_key | |
@decoded_vapid_public_key ||= Base64.urlsafe_decode64(ENV['VAPID_PUBLIC_KEY']).bytes | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Device < ApplicationRecord | |
belongs_to :user | |
validates :user_id, presence: true | |
validates :endpoint, presence: true, uniqueness: { scope: :user_id } | |
validates :p256dh, presence: true | |
validates :auth, presence: true | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DevicesController < ApplicationController | |
def create | |
device = current_user.devices.find_or_initialize_by endpoint: params[:subscription][:endpoint] | |
device.attributes = device_params | |
device.save! if device.changed? | |
head :ok | |
end | |
private | |
def device_params | |
params.require(:subscription).permit(%i(endpoint p256dh auth)) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ENV['VAPID_PUBLIC_KEY'] #=> "BDIzN5ppEokkmLdcwc5hlQoZavhXA0PmFdLWicfiD-oyg_b4n42rQ08LQfPlNtkG9P6FgmuqPPCic2bzqnDistA=" | |
ENV['VAPID_PRIVATE_KEY'] #=> "A7Aok-dAKnj19Jmb8r-ujb5L5CVdjgRc_WyBwa0_Lw4=" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gem 'webpush' | |
gem 'serviceworker-rails' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- index.html --> | |
<link rel="manifest" href="/manifest.json"> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# public/manifest.json | |
{ | |
"name": "My App", | |
"short_name": "my-app", | |
"start_url": "/", | |
"icons": [ | |
{ | |
"src": "/icon.png", | |
"sizes": "192x192", | |
"type": "image/png" | |
} | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/routes.rb | |
resources :devices, only: [:create] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app/assets/javascripts/serviceworker-companion.js | |
if (navigator.serviceWorker) { | |
navigator.serviceWorker.register('/serviceworker.js', { scope: './' }) | |
.then(function(reg) { | |
console.log('[Page] Service worker registered!'); | |
// プッシュ通知の購読 | |
reg.pushManager.subscribe({ | |
userVisibleOnly: true, | |
applicationServerKey: window.vapidPublicKey, | |
}).then(subscribeSuccess); | |
}); | |
} | |
var subscribeSuccess = function(subscription){ | |
params = { | |
subscription: subscription.toJSON(); | |
} | |
$.ajax({ | |
type: 'POST', | |
url: '/devices', | |
data: params | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app/assets/javascripts/serviceworker.js.erb | |
var CACHE_VERSION = 'v1'; | |
var CACHE_NAME = CACHE_VERSION + ':sw-cache-'; | |
function onInstall(event) { | |
console.log('[Serviceworker]', "Installing!", event); | |
event.waitUntil(self.skipWaiting()); | |
} | |
function onActivate(event) { | |
console.log('[Serviceworker]', "Activating!", event); | |
event.waitUntil(self.clients.claim()); | |
} | |
// Borrowed from https://github.com/TalAter/UpUp | |
function onFetch(event) { | |
event.respondWith( | |
// try to return untouched request from network first | |
fetch(event.request).catch(function() { | |
// if it fails, try to return request from the cache | |
return caches.match(event.request).then(function(response) { | |
if (response) { | |
return response; | |
} | |
// if not found in cache, return default offline content for navigate requests | |
if (event.request.mode === 'navigate' || | |
(event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) { | |
console.log('[Serviceworker]', "Fetching offline content", event); | |
return caches.match('/offline.html'); | |
} | |
}) | |
}) | |
); | |
} | |
self.addEventListener('install', onInstall); | |
self.addEventListener('activate', onActivate); | |
self.addEventListener('fetch', onFetch); | |
// プッシュ通知を受け取った時の処理 | |
self.addEventListener('push', function(event){ | |
var title = (event.data && event.data.text()) || 'テストプッシュ'; | |
var data = { | |
body: "", | |
tag: "push-simple-demo-notification-tag", | |
icon: '/icon.jpg', | |
vibrate: [400,100,400], // ミリ秒単位で振動と休止の時間を交互に任意の回数だけ配列に格納 | |
data: { | |
link_to: '/' | |
} | |
}; | |
event.waitUntil(self.registration.showNotification(title, data)); | |
}); | |
// 通知をクリックした時の処理 | |
self.addEventListener("notificationclick", function(event) { | |
event.notification.close(); | |
var link_to = event.notification.data.link_to; | |
event.waitUntil(clients.matchAll({ | |
type: "window" | |
}).then(function(clientList) { | |
for (var i = 0; i < clientList.length; i++) { | |
var client = clientList[i]; | |
var regexp = new RegExp(link_to + '$'); | |
var match = client.url.match(regexp); | |
if (match != null && 'focus' in client) | |
return client.focus(); | |
} | |
if (clients.openWindow) { | |
return clients.openWindow(link_to); | |
} | |
})); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ApplicationRecord | |
has_many :devices, dependent: :destroy | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# One-time, on the server | |
vapid_key = Webpush.generate_key | |
# Save these in your application server settings | |
vapid_key.public_key | |
# => "BDIzN5ppEokkmLdcwc5hlQoZavhXA0PmFdLWicfiD-oyg_b4n42rQ08LQfPlNtkG9P6FgmuqPPCic2bzqnDistA=" | |
vapid_key.private_key | |
# => "A7Aok-dAKnj19Jmb8r-ujb5L5CVdjgRc_WyBwa0_Lw4=" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/services/webpush_service.rb | |
class WebpushService | |
def initialize(user_id: nil) | |
@user_id = user_id | |
end | |
def webpush_clients(message) | |
devices.each do |device| | |
webpush device, message | |
end | |
end | |
def webpush(device, message) | |
Webpush.payload_send( | |
message: message, | |
endpoint: device.endpoint, | |
p256dh: device.p256dh, | |
auth: device.auth, | |
ttl: 24 * 60 * 60, | |
vapid: { | |
public_key: ENV['VAPID_PUBLIC_KEY'], | |
private_key: ENV['VAPID_PRIVATE_KEY'] | |
} | |
) | |
end | |
private | |
def devices | |
@user_id.present? ? Device.where(user_id: @user_id) : Device.all | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment