tag:blogger.com,1999:blog-90464027489423188622024-03-07T12:34:11.589+09:00tmpfiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.comBlogger192125tag:blogger.com,1999:blog-9046402748942318862.post-53673678855202810332019-07-08T23:06:00.000+09:002019-07-08T23:07:18.834+09:00Chrome 起動時にディスク使用率が100%で張り付く問題<textarea class="markdown" disabled="disabled">
Windows10 でちょくちょくディスク使用率が100%で張り付く事があった。
webでググるとそれっぽい記事はいくつか見つかったが、自分のPCの場合はそれに加えて読み取り速度と書き込み速度が0の状態でフリーズしていた。
ハードディスクかマザーボードが原因かと思ったが発生するタイミングは Chrome 起動時のタイミングで、長時間待っても解消されなかった。(一時的に解消されるが Chrome の操作をすると再度発生)
閲覧履歴やブックマークを削除すると解消するとの記事を見つけたが改善しなかったので、アンインストール→再インストールで改善した。
拡張機能のどれかのせいか、Chromeログインしてたので同期のどこかが原因だったかもしれない、謎。
</textarea>
fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-56637687581598590052019-02-15T15:41:00.002+09:002019-02-15T18:22:27.078+09:00AniHani.link の技術選定メモ<textarea class="markdown" disabled="disabled">
## 方針
あにハニでも いつから.link っぽいの欲しい -> 作る?
バックエンドをごりごりやりたくないのでなるべく baas(Firebase) を利用
フロントに集中
産物: https://fiahfy-anihani.firebaseapp.com
ソース: https://github.com/fiahfy/anihani-link
### Database
Firestore, nosql 使いたかったからそれで
データは正規化しないほうがいいみたいだけど更新時にupdateし直すのがどうしてもめんどいのとjoinするデータがそもそも少ないので参照値を利用してる
ただしデータ取得の実装によってはフロントでのリクエストが結構増える
### Batch
ツイートを取ってきてパースしていい具合にDBにぶちこむ一番面倒な部分
Firebase Functions でそれっぽいことができるのでそこで実行
当初は Spark plan (無料枠) でなんとかしようと思ったが Functions から Googleネットワーク外への送信が不可(受信はOK)
-> GAEで実行すればいいんじゃね?
-> Deploy時に利用する Build API が課金状態じゃないと使えない = 自動的に Braze plan (従量制)
-> Braze plan なら Firebase Functions でいいじゃん
となり Firebase Functions に戻る
定期実行の仕組みが必要だがいくつかパターンがある模様
* `cron-job.org` から HTTPS リクエストを送信してフックで実行
* GAEをたてて cron service でGAEにリクエスト -> pub/sub か https 送信 -> functions でフック
* Cloud Scheduler で pub/sub か https 送信 -> functions でフック
一番いまどきっぽいので Cloud Scheduler を選択
1アカウントにつき 月3つのjobまでは無料 超えてもそんなに高くない
Cloud Scheduler で pub/sub に定期的にメッセージ送信
https でフックしてもいいけどその場合トークンかなんかでパスワードかけとかないと誰かから叩かれる
### Front-end
`Vue.js`, `Nuxt.js` を選択、個人的に小さいサービスなら TypeScript すら面倒 + Vue.js とあまり相性が良くないので pure js (ES6)
というか TypeScript 導入するくらいなら `React.js`, `Next.js` の方がよさげ
module をいくつかつっこむ
* `@nuxtjs/dotenv`
`.env` 用
* `@nuxtjs/google-analytics`
GA用
* `@nuxtjs/pwa`
PWAとかmetaとかiconとか用
* `@nuxtjs/vuetify`
マテリアルデザイン+component
あとは firebase を plugin で初期化して firestore からデータを取得して表示
SSR はサイトの特性上恩恵があまりないのと面倒なのでなし
静的ホスティングで済ませたかったので `nuxt generate` してどこかにあげる
generate する場合は `mode: spa` にするもんかと勝手に思ってたけど `universal` で恩恵があるっぽい(要調査
https://qiita.com/amishiro/items/11bd642728f6b5838189#universalssr%E3%83%A2%E3%83%BC%E3%83%89%E3%81%A7%E4%BD%9C%E6%88%90
### Hosting
静的ファイルをあげられればぶっちゃけどこでもいい
候補は Github Pages, Netlify, Firebase Hosting
ググったら Netlify はたまに詰まるっていうのと Firebase Hosting は裏で Fastly 使ってるよってことだったので Firebase Hosting を選択
(ここだけ別管理にしても面倒なので)
## 構成
```
+------+
| User |
+------+
^
|
v
+-----------------------------+
| Firebase Hosting(Nuxt.js) |
+-----------------------------+
^
|
v
+----------------------+ +------------+
| Firebase Firestore | <-> | CLI(Local) |
+----------------------+ +------------+
^
|
v
+----------------------+
| Firebase Functions |
+----------------------+
^
|
+-------------------+
| Cloud Scheduler |
+-------------------+
```
## TODO
ツイートのパースがガバガバすぎてスケジュールの変更、キャンセルがうまく取れない
あにまーれだけに関していうと 非公式wiki に綺麗なスケジュールがあるのでそっちから取る方がいいかも
こだわると時間かかりそうだったのでフロントの実装が雑(ここは適宜)
キャッシュ制御もしてない
vuex もほとんど利用できてない
iPhoneX で PWA で起動すると SafeArea に余裕で食い込む
standaloneかどうか と portrait/landscape と iPhoneXかどうか が取れれば後は CSS でがんばればなんとかなりそうな気はする
ログインシステム(認証) はそもそもメンバーが少ない(9人)からいらないでしょってことで省略
Bookmark 的なものが必要になっても local storage でいいんじゃね? という感じ
それでも必要になったら Firebase Authentication
DevOps?知らない子ですね...
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-57289851399063156332019-02-06T12:43:00.001+09:002019-02-06T12:45:11.171+09:00go modules<textarea class="markdown" disabled="disabled">
## Requirement
`go 1.11` higher
```bash
$ go version
go version go1.11.2 darwin/amd64
```
## `GO111MODULE`
* unset or `auto`
`GOPATH` 内部の場合はモジュールモードoff
`GOPATH` 外部の場合はモジュールモードon
* `on`
全ての場所でモジュールモードon
* `off`
全ての場所でモジュールモードoff
## Commands
### Initialize
```
go mod init <package>
```
`go.mod` が作成される
### Run
```
go run .
```
importに応じて勝手にビルドされる `go.sum` が作成される
### Build
```
go build
```
importに応じて勝手にビルドされる `go.sum` が作成される
### Get specific version
```
go get github.com/appleboy/gin-jwt@master
```
特定の branch, version を入れる場合
```
go mod edit -require=github.com/appleboy/gin-jwt@master
go build
```
これでも同じ結果になる
## 参考
* https://github.com/golang/go/wiki/Modules
* https://qiita.com/spiegel-im-spiegel/items/5cb1587cb55d6f6a34d7
* https://budougumi0617.github.io/2018/05/10/go-get-from-go1-tag-or-branch/
* https://text.baldanders.info/golang/go-module-aware-mode/
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-58629149467312838232019-01-29T19:41:00.003+09:002019-01-29T19:41:29.311+09:00Setup format document with ESLint on VSCode<textarea class="markdown" disabled="disabled">
### key bind 追加
`File > Preferences > Keyboard Shortcuts > edit keybindings.json`
```
[
{
"key": "ctrl+alt+l",
"command": "eslint.executeAutofix"
}
]
```
### eslint.validate の設定変更
```
"eslint.validate": [
"javascript",
"javascriptreact",
{ "language": "html", "autoFix": true },
{ "language": "vue", "autoFix": true }
],
```
## 参考
* https://github.com/Microsoft/vscode-eslint/issues/417#issuecomment-410363336
* https://github.com/Microsoft/vscode-eslint/issues/185#issuecomment-307842751
</textarea>
fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-33863930713935486622019-01-22T13:43:00.001+09:002019-01-22T13:44:28.620+09:00Golang links<textarea class="markdown" disabled="disabled">
## Documents
* https://github.com/golang/go/wiki
* https://golang.org/pkg/
### samples
* https://github.com/GoogleCloudPlatform/golang-samples/tree/master/getting-started
## native な router の実装
* https://gist.github.com/reagent/043da4661d2984e9ecb1ccb5343bf438
## Framework
最近だと Gin, gollira/mux http-router or go-json-rest あたりか
* https://qiita.com/najeira/items/bdc988c4e93b3b5ccf2f
* https://github.com/mingrammer/go-web-framework-stars
* https://github.com/ant0ine/go-json-rest
* https://github.com/gin-gonic/gin
## RESTful API の実装
* https://medium.com/@thedevsaddam/build-restful-api-service-in-golang-using-gin-gonic-framework-85b1a6e176f3
* http://sgykfjsm.github.io/blog/2016/03/13/golang-json-api-tutorial/
* https://github.com/mingrammer/go-todo-rest-api-example
* https://medium.com/@swanandkeskar/rest-api-using-go-and-gorilla-mux-91cf63956de
* https://medium.com/eureka-engineering/go%E8%A8%80%E8%AA%9E%E8%A3%BDwaf-gin%E3%81%A7web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B-%E6%BA%96%E5%82%99%E7%B7%A8-6f14aba0da29
## DDD
* https://www.slideshare.net/pospome/go-80591000
* https://engineer.recruit-lifestyle.co.jp/techblog/2018-03-16-go-ddd/
* https://hackernoon.com/golang-clean-archithecture-efd6d7c43047
* https://eng-blog.iij.ad.jp/archives/2442
* https://postd.cc/golang-clean-archithecture/
* https://little-hands.hatenablog.com/entry/2018/12/10/ddd-architecture
* https://qiita.com/trrrrrys/items/4286ca3d015e252800c3
### Standard layout
* https://github.com/golang-standards/project-layout
* https://qiita.com/sueken/items/87093e5941bfbc09bea8#web
### samples
* https://qiita.com/trrrrrys/items/44e839134af1a0155be2
* https://github.com/trrrrrys/blogapi
* https://github.com/shotat/ggg/blob/master/interfaces/api/server/router/router.go
* https://github.com/hatajoe/8am
* https://github.com/nakabonne/cleanarchitecture-sample
## Go+Docker
* https://medium.com/statuscode/golang-docker-for-development-and-production-ce3ad4e69673
* https://semaphoreci.com/community/tutorials/how-to-deploy-a-go-web-application-with-docker
* https://docs.microsoft.com/ja-jp/azure/app-service/containers/quickstart-docker-go
## links
* https://qiita.com/MahoTakara/items/10fede35c03db1e3b849#%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%82%84ide
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-63039017668956056992018-11-26T11:49:00.000+09:002018-11-28T09:52:07.118+09:00UnicodeDecodeError on python3.5<textarea class="markdown" disabled="disabled">
自動アップデートのタイミングでか ubuntu16.04 上の python で以下のエラーが出たので対応
```
File "/usr/lib/python3.5/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 239: ordinal not in range(128)
```
日本語の入出力周りで出ているっぽい
`/etc/default/locale` に以下を追加して fix
```
LANG="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8" # <-- Add
```
or
```
sudo update-locale LC_CTYPE=en_US.UTF-8
```
</textarea>
fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com4tag:blogger.com,1999:blog-9046402748942318862.post-55553016418747374532018-11-21T14:08:00.001+09:002018-12-17T14:53:11.635+09:00nginx memo<textarea class="markdown" disabled="disabled">
### package
基本は `nginx` 、lua を使いたい場合は `nginx-extras`
* http://blog.it.churaumi.tv/nginx-light-full-extra-configure-compare
### config file path
設定ファイルを置く場所について
サイト設定 `server` は `conf.d` に入れてもいいけど
区別のために `sites-available` に置いて `sites-enabled` に symlink 貼った方が良さげ
lua ファイルは特に決まってないっぽいので `/etc/nginx/lua/` とかで
あとは基本的に↓
* https://gakumon.tech/nginx/nginx_conf_directory.html
### content cache
#### multi server
1台でキャッシュを扱う場合は特に何も考えなくていい
redis, memcached 等のストレージを利用するケースだとモジュールが用意されているがキャッシュの設定はアプリケーションで行わないといけない様なのでちょっと微妙
```
A response should be put in memcached in advance by means external to nginx.
```
* http://nginx.org/en/docs/http/ngx_http_memcached_module.html
```
The backend should set the data in redis. The redis key is /uri?args.
```
* https://www.nginx.com/resources/wiki/modules/redis/
* https://www.nginx.com/resources/wiki/modules/redis2/
ローカルキャッシュを利用する場合は下記の様な構成にするとうまくいく (`sharded cache` or `shared cache`)
* https://www.nginx.com/blog/shared-caches-nginx-plus-cache-clusters-part-1/
#### purge cache
nginx plus(有償) だと proxy_cache_purge module が提供されている
無料版だと
* [Cache Purge](https://github.com/FRiCKLE/ngx_cache_purge)
* [Selective Cache Purge](https://github.com/wandenberg/nginx-selective-cache-purge-module)
ここら辺が使えそう(ただしnginxをソースからビルドしないといけないっぽいのでメンテとか考えると面倒そう)
または lua で自力でやる場合は
* https://scene-si.org/2016/11/02/purging-cached-items-from-nginx-with-lua/
* https://scene-si.org/2017/01/08/improving-nginx-lua-cache-purge/
ただし `proxy_cache_key` を指定しても key が揺らぐ(Vary, set-cookie とかで)みたいなのでそこら辺気にしないと確実に消せない
デバイス別にキャッシュした場合も考慮する必要あり
```
proxy_ignore_headers Cache-Control Expires Set-Cookie Vary;
proxy_hide_header Set-Cookie;
```
example
* https://gist.github.com/fiahfy/a9d5ccbbe716286fe1b1ec71a65f1489
### proxy_set_header
location でheaderを追加したい時とかにそのまま追加だとうまくいかないのでいちいち全て再設定する必要がある
`bad`
```
server {
:
proxy_set_header Host $host;
:
location / {
proxy_set_header X-Foo 'foo';
}
```
`good`
```
server {
:
proxy_set_header Host $host;
:
location / {
proxy_set_header Host $host;
proxy_set_header X-Foo 'foo';
}
```
### template
#### log
```
log_format ltsv 'host:$http_host\t'
'port:$server_port\t'
'time:$time_iso8601\t'
'remote_addr:$remote_addr\t'
'request_method:$request_method\t'
'request_length:$request_length\t'
'request_uri:$request_uri\t'
'https:$https\t'
'uri:$uri\t'
'query_string:$query_string\t'
'status:$status\t'
'bytes_sent:$bytes_sent\t'
'body_bytes_sent:$body_bytes_sent\t'
'referer:$http_referer\t'
'useragent:$http_user_agent\t'
'forwardedfor:$http_x_forwarded_for\t'
'request_time:$request_time\t'
'upstream_response_time:$upstream_response_time';
access_log /var/log/nginx/access.log ltsv;
error_log /var/log/nginx/error.log;
```
#### proxy cache
```
proxy_cache_path /var/cache/nginx/app
levels=1:2
keys_zone=app:8m
inactive=10m
max_size=128m;
proxy_temp_path /var/cache/nginx/tmp;
```
#### map
```
map $http_user_agent $mobile {
default 0;
~iPhone 1;
~Android 1;
~BlackBerry 1;
}
```
#### ssl
```
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_certificate /etc/ssl/certs/site.pem;
ssl_certificate_key /etc/ssl/private/site.key;
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-43089249231519661622018-11-01T08:47:00.002+09:002018-11-01T08:48:35.571+09:00fs performance (sync vs async)<textarea class="markdown" disabled="disabled">
```js
const fs = require('fs')
const path = require('path')
const util = require('util')
const calcSync = (filepath) => {
const stats = fs.lstatSync(filepath)
if (!stats.isDirectory()) {
return [1, stats.size]
}
let totalNum = 0
let totalSize = 0
const filenames = fs.readdirSync(filepath)
for (let filename of filenames) {
const [num, size] = calcSync(path.join(filepath, filename))
totalNum += num
totalSize += size
}
return [totalNum, totalSize]
}
const calc = async (filepath) => {
const stats = await util.promisify(fs.lstat)(filepath)
if (!stats.isDirectory()) {
return [1, stats.size]
}
let totalNum = 0
let totalSize = 0
const filenames = await util.promisify(fs.readdir)(filepath)
for (let filename of filenames) {
const [num, size] = await calc(path.join(filepath, filename))
totalNum += num
totalSize += size
}
return [totalNum, totalSize]
}
const src = '<target>'
;(async () => {
console.time('calcSync')
console.log(calcSync(src))
console.timeEnd('calcSync')
console.time('calc')
const r = await calc(src)
console.log(r)
console.timeEnd('calc')
})()
```
```
[ 23723, 359622209 ]
calcSync: 352.919ms
[ 23723, 359622209 ]
calc: 1406.648ms
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-55271939958435285092018-09-19T14:17:00.000+09:002018-09-19T14:18:46.723+09:00Check TLS<textarea class="markdown" disabled="disabled">
### web
https://www.ssllabs.com/ssltest/
### curl
```bash
$ curl -v -s --tlsv1.0 "https://www.google.com" > /dev/null
* Rebuilt URL to: https://www.google.com/
* Trying 2404:6800:400a:808::2004...
* TCP_NODELAY set
* Connected to www.google.com (2404:6800:400a:808::2004) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.0 (OUT), TLS handshake, Client hello (1):
} [220 bytes data]
* TLSv1.0 (IN), TLS handshake, Server hello (2):
{ [96 bytes data]
* TLSv1.0 (IN), TLS handshake, Certificate (11):
{ [2104 bytes data]
:
```
* `--sslv2` SSL2.0
* `--sslv3` SSL3.0
* `--tlsv1.0` TLS1.0
* `--tlsv1.1` TLS1.1
* `--tlsv1.2` TLS1.2
### nmap
```bash
brew install nmap
```
```bash
$ nmap --script ssl-enum-ciphers -p 443 www.google.com
Starting Nmap 7.70 ( https://nmap.org ) at 2018-09-19 14:14 JST
Nmap scan report for www.google.com (172.217.161.196)
Host is up (0.0097s latency).
Other addresses for www.google.com (not scanned): 2404:6800:400a:80b::2004
rDNS record for 172.217.161.196: kix07s03-in-f4.1e100.net
PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| TLSv1.0:
| ciphers:
| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
:
```
## 参考
* https://qiita.com/greymd/items/68b0c40044a88171235a
* https://www.cloudibee.com/disabling-tls-1-0-on-nginx/
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-54872660562236294492018-08-16T13:40:00.000+09:002018-08-17T11:13:09.884+09:00Web Push<textarea class="markdown" disabled="disabled">
GCM だの FCM だの VAPID だのいろいろな実装や情報があってわかりづらいのでまとめ
* [GCM/FCMでの実装](https://fiahfy.blogspot.com/2018/08/web-push-gcmfcm.html)
* [VAPIDでの実装](https://fiahfy.blogspot.com/2018/08/web-push-vapid.html)
* [Firebase Cloud Messaging での実装](https://fiahfy.blogspot.com/2018/08/web-push-firebase-cloud-messaging.html)
sample project
https://github.com/fiahfy/webpush-sample
## 参考
* https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications
* https://developers.google.com/web/fundamentals/codelabs/push-notifications/?hl=ja
* http://blog.soushi.me/entry/2017/05/18/124558
* https://firebase.google.com/docs/cloud-messaging/js/client
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-52233872916855492042018-08-16T13:37:00.001+09:002018-08-17T14:25:20.439+09:00Web Push (Firebase Cloud Messaging)<textarea class="markdown" disabled="disabled">
Web Push に Firebase Cloud Messaging を利用した場合の実装
### Set gcm_sender_id
Firebase project を作成して `103953800507` (固定値) を指定
ドキュメントではこの固定値を入力するように記載されているが省略しても動作はする(謎)
`manifest.json`
```
{
:
"gcm_sender_id": "103953800507"
}
```
### initialize firebase app
Firebase project の設定値を指定
`index.html`
```
<script src="https://www.gstatic.com/firebasejs/5.3.1/firebase.js"></script>
<script>
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
}
firebase.initializeApp(config)
</script>
```
`app.js`
```
// Retrieve Firebase Messaging object.
const messaging = firebase.messaging()
```
### register service worker
ServiceWorker を `/firebase-messaging-sw.js` とする場合は firebase がよろしくやってくれるので省略可
`app.js`
```
navigator.serviceWorker.register('sw.js')
.then((registration) => {
messaging.useServiceWorker(registration)
})
```
### request permission and get token
`app.js`
```
messaging.requestPermission()
.then(() => {
console.log('Notification permission granted.')
messaging.getToken()
.then((currentToken) => {
if (currentToken) {
sendTokenToServer(currentToken)
} else {
// Show permission request.
console.log('No Instance ID token available. Request permission to generate one.')
// Show permission UI.
sendTokenToServer(false)
}
})
.catch((err) => {
console.log('An error occurred while retrieving token. ', err)
sendTokenToServer(false)
})
})
.catch((err) => {
console.log('Unable to get permission to notify.', err)
})
```
### receive push
タブの状態(フォアグラウンド/バックグラウンド)に応じて処理する場所が違うのでそれぞれ実装
#### receive on foreground
`app.js`
```
messaging.onMessage((e) => {
console.log('Message received. ', e)
const title = 'Title'
const options = {
body: e.data.text
}
new Notification(title, options)
})
```
#### receive on background
`sw.js`
```
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/5.3.1/firebase-app.js')
importScripts('https://www.gstatic.com/firebasejs/5.3.1/firebase-messaging.js')
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
'messagingSenderId': "<SENDER_ID>"
})
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging()
messaging.setBackgroundMessageHandler((e) => {
console.log('Message received. ', e)
// Customize notification here
const title = 'Title'
const options = {
body: e.data.text
}
return self.registration.showNotification(title, options)
})
```
### send push
`firebase-admin` を利用、
Firebase の サーバアカウントキーをダウンロードし `key.json` にリネーム
`'TOKEN'` に対象の登録トークンを指定
`main.js`
```
const admin = require('firebase-admin')
const serviceAccount = require('./key.json')
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
})
// See documentation on defining a message payload.
const message = {
data: {
text: 'Here is a payload!'
},
token: 'TOKEN'
}
// Send a message to the device corresponding to the provided
// registration token.
admin.messaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response)
})
.catch((error) => {
console.log('Error sending message:', error)
})
```
送信
```
node main.js
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-31607231962829999022018-08-16T13:08:00.000+09:002018-08-16T13:08:15.825+09:00Web Push (VAPID)<textarea class="markdown" disabled="disabled">
Web Push に VAPID を利用した場合の実装方法
### generate VAPID public/private keys
`generate_vapid_keys.js`
```
const webPush = require('web-push')
const vapidKeys = webPush.generateVAPIDKeys()
const keys = {
publicKey: vapidKeys.publicKey,
privateKey: vapidKeys.privateKey,
}
console.log(keys)
```
生成
```
node generate_vapid_keys.js
```
### register service worker
FCMの場合と変わらず
`app.js`
```
navigator.serviceWorker.register('/sw.js')
.then((registration) => {
swRegistration = registration
})
```
### subscribe
`applicationServerKey` に上記で生成した公開鍵を指定
`app.js`
```
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: "PUBLIC_KEY"
})
.then((subscription) => {
// send subscription to server
})
```
### receive push
FCMの場合と変わらず
`sw.js`
```
self.addEventListener('push', (e) => {
console.log('[Service Worker] Push Received', e)
const title = 'Title'
const options = {
body: e.data ? e.data.text() : 'Empty payload'
}
e.waitUntil(self.registration.showNotification(title, options))
})
```
### send push
暗号化周りが面倒なので `web-push` を利用
`'PUBLIC_KEY'`, `'PRIVATE_KEY'` にそれぞれ生成した公開鍵/秘密鍵を指定
`'SUBSCRIPTION'` は購読時に取得したものを指定
`main.js`
```
const webPush = require('web-push')
const payload = 'Here is a payload!'
const options = {
vapidDetails: {
subject: 'mailto:example_email@example.com',
publicKey: 'PUBLIC_KEY',
privateKey: 'PRIVATE_KEY'
},
TTL: 60
}
webPush.sendNotification(
'SUBSCRIPTION',
payload,
options
)
```
送信
```
node main.js
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-63158076717744926042018-08-16T12:59:00.001+09:002018-08-16T13:11:28.122+09:00Web Push (GCM/FCM)<textarea class="markdown" disabled="disabled">
送信のみにFCMを利用した場合の実装方法
Firefox のみの話でいうと FCM を利用しないためFCM周りの設定は省略できる
(Chromeを考えると必須ではあるが)
### Set gcm_sender_id
Firebase project を作成して `送信者 ID` を指定
`manifest.json`
```
{
:
"gcm_sender_id": "SENDER_ID"
}
```
### register service worker
`app.js`
```
navigator.serviceWorker.register('/sw.js')
.then((registration) => {
swRegistration = registration
})
```
### subscribe
`app.js`
```
swRegistration.pushManager.subscribe({
userVisibleOnly: true
})
.then((subscription) => {
// send subscription to server
})
```
`userVisibleOnly` は現状必須だが Firefox だと省略できる
### receive push
`sw.js`
```
self.addEventListener('push', (e) => {
console.log('[Service Worker] Push Received', e)
const title = 'Title'
const options = {
body: e.data ? e.data.text() : 'Empty payload'
}
e.waitUntil(self.registration.showNotification(title, options))
})
```
### send push
#### without data payloads
ペイロードなしの通知は endpoint と サーバーキーの指定のみで送信できる
サーバーキー は Firebase project に記載されているものを使用
```
curl "END_POINT" --request POST --header "TTL: 60" --header "Content-Length: 0" --header "Authorization: key=SERVER_KEY"
```
#### with data payloads
ペイロードありの通知は暗号化周りが面倒なので `web-push` を利用
`'SUBSCRIPTION'` は購読時に取得したものを指定
`main.js`
```
const webPush = require('web-push')
const payload = 'Here is a payload!'
const options = {
gcmAPIKey: 'SERVER_KEY',
TTL: 60
};
webPush.sendNotification(
'SUBSCRIPTION',
payload,
options
)
```
送信
```
node main.js
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-10703849232476371162018-03-27T11:24:00.002+09:002018-04-05T12:04:20.811+09:00Fluentd memo<textarea class="markdown" disabled="disabled">
### 動作確認
設定ファイル編集
`/etc/fluentd/fluentd.conf`
```
<source>
type forward
</source>
<match debug.**>
type stdout
</match>
```
Restart fluentd
```
$ sudo service td-agent restart
```
飛ばしてみる
```
$ echo '{"json":"message"}' | fluent-cat debug.test
```
`fluent-cat` がない場合以下を確認
* `/usr/lib/fluent/ruby/bin/fluent-cat`
* `/opt/td-agent/embedded/bin/fluent-cat`
ログを見てみる
```
$ tail /var/log/fluentd/stdout.log
2018-03-27 10:17:02 +0900 debug.test: {"json":"message"}
```
### Output file
`/etc/fluentd/fluentd.conf`
```
<match debug.file.**>
type file
path /var/log/fluent/app
time_slice_format %Y%m%d
time_slice_wait 1m
flush_interval 5s
utc
</match>
```
再起動して確認
```
$ sudo service td-agent restart
$ echo '{"json":"message"}' | fluent-cat debug.file.test
$ tail /var/log/fluent/app.20180405_0.log
2018-04-05T02:42:38Z debug.file.test {"json":"message"}
```
* `time_format`
fileに出力される時間のフォーマット
default: ISO-8601
* `utc`
ファイル分割にUTCを使用するか
default: localtime
* `compress`
圧縮するかどうか
default: no compression
* `time_slice_format`
どのくらいの期間でファイルを分割するか
default: `%Y%m%d%H`
* `time_slice_wait`
ファイル分割時の待ち時間、どのくらい遅れを許容するか
default: `10m`
* `flush_interval`
データをflushする間隔
default: `60s`
## 参考
* http://hivecolor.com/id/37
* https://qiita.com/zaburo/items/dbd943d370afe8e4a304
* http://www.usupi.org/sysad/253.html
### output file
* https://docs.fluentd.org/v0.12/articles/out_file
* https://blog.tnmt.info/2012/10/19/about-fluentd-out-file-plugin/
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-47616186027777080312018-03-19T10:53:00.001+09:002018-03-19T10:53:12.359+09:00Android emulator の hosts 書き換え<textarea class="markdown" disabled="disabled">
いつのまにか[以前](https://fiahfy.blogspot.jp/2013/05/android-studiohosts.html)の方法だとできなくなっていたので調べた
```bash
$ ./adb root && ./adb remount && ./adb push /etc/hosts /system/etc/
```
一度にやるとうまく行くらしい
## 参考
* https://qiita.com/tatsu/items/cb0085515b37d2a0c92b
* https://qiita.com/nac731/items/9242cee6756bdf70c019
</textarea>
fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-51194844854469982032018-03-04T16:13:00.001+09:002018-03-29T21:18:18.963+09:00Windows10 on VirtualBox<textarea class="markdown" disabled="disabled">
仮想マシンダウンロード
https://developer.microsoft.com/ja-jp/windows/downloads/virtual-machines
解凍して ovf を開く
VirtualBox が起動するのでインポート
評価版を延長回数を確認
```
slmgr -dlv
```
評価版を延長
```
slmgr -rearm
```
## 参考
* https://qiita.com/naru0504/items/df2ce1aa48b7e87b7374
* https://www.tipsfound.com/windows10/01014
</textarea>
fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-58023686309177934962018-02-01T08:30:00.001+09:002018-02-01T08:30:27.053+09:00adb command<textarea class="markdown" disabled="disabled">
### Show connected devices
```
$ adb devices
List of devices attached
04d385020b3f999f device
```
### Install apk
```
$ adb install <APK file>
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-64214398340305368532018-01-16T08:20:00.003+09:002018-01-16T08:23:12.604+09:00Provisioning profile "XXXXX" doesn't include signing certificate<textarea class="markdown" disabled="disabled">
証明書が複数含まれている場合によろしく使ってくれてないっぽい
`Automatic manage signing` にチェックいれれば問題はなさそうだけど、チェックを入れたくない場合は
キーチェーンアクセスのログインを確認し、対象の `iPhone Developer: YYYYY` を削除する
* https://stackoverflow.com/questions/39568005/xcode-8-shows-error-that-provisioning-profile-doesnt-include-signing-certificat
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-31443702667031336772018-01-12T08:13:00.004+09:002018-01-12T08:13:44.536+09:00Ansible cli<textarea class="markdown" disabled="disabled">
```
ansible <host-pattern> -i <inventory> -m <module-name> -a <module-args>
```
eg. service apache2 reload
```
ansible web -i prod -m service -a "name=apache2 state=reloaded"
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-58325229133516698532017-12-09T23:45:00.000+09:002017-12-10T00:16:29.249+09:00Nuxt.js を GitHub Pages で使う<textarea class="markdown" disabled="disabled">
Nuxt.js は Vue.js の Framework で Webpack, Babel 等の設定や、ルーティング、SPA、サーバサイドレンダリングの実装をシンプルなものにしてくれます。
Nuxt.js には静的なページを生成する機能もあるので今回はこれを利用して、GitHub Pages を作成します。
`nuxt-sumple` というリポジトリ名で作成しました。
今回使用したコード、作成したページは以下になります。
https://github.com/fiahfy/nuxt-sample
https://fiahfy.github.io/nuxt-sample/
###Install requirements
yarn, vue-cli を使用します。
インストールしていない場合はインストールします。
```bash
$ npm i -g yarn vue-cli
```
###Create Project
テンプレートからプロジェクトを作成します。
```bash
$ vue init nuxt-community/starter-template nuxt-sample
```
プロジェクトルートに移動して
```bash
$ cd nuxt-sample
```
依存パッケージをインストールし
```bash
$ yarn
```
サーバを起動します
```bash
$ yarn dev
```
ブラウザで http://localhost:3000 にアクセスするとページが確認できます。
以降はこのページで開発をしていきます。
###Update Config
GitHub Pages で公開するために、設定ファイル(`nuxt.config.js`)を修正します。
公開するURLは https://fiahfy.github.io/nuxt-sample/ となるので、ベースパスを考慮します。
`favicon.ico` のパスが変わるので修正します。
```js
{ rel: 'icon', type: 'image/x-icon', href: '/nuxt-sample/favicon.ico' }
```
ベースパスを設定するため `router.base` を追加します。
```js
build: {
...
},
router: {
base: '/nuxt-sample/'
}
}
```
ベースパスを変更したので確認時のURLも http://localhost:3000/nuxt-sample/ となります。
###Publish to GitHub Pages
ページが完成したら、`nuxt generate` で静的ページを生成します。
```bash
$ yarn generate
```
`dist` ディレクトリに静的ページが生成されます。
`dist` を公開用のディレクトリにコピーします。
```bash
$ cp -r dist/ gh-pages
```
`package.json` の `generate` スクリプトを以下の様にしておくと便利です。
```js
"generate": "nuxt generate && rm -rf gh-pages/* && cp -r dist/ gh-pages/",
```
公開用ディレクトリを `gh-pages` ブランチとしてpushします。
```bash
$ cd gh-pages
$ git remote add origin git@github.com:fiahfy/nuxt-sample.git
$ git checkout -b gh-pages
$ git add .
$ git commit -m "Initial commit"
$ git push -u origin gh-pages
```
公開されたページを確認します。
https://fiahfy.github.io/nuxt-sample/
Nuxt.js で簡単に GitHub Pages が作成できました。
もちろん、動的ページにもすぐに切り替えられるので、とりあえず GitHub Pages で公開して、後々自サーバで公開といった感じでも使えます。
Nuxt.js は他にも便利で、柔軟な機能があるので、Vue.js に興味のある方は GitHub Pages から使用してみてはいかがでしょうか?
##参考
* https://ja.nuxtjs.org/
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-51264178361314841952017-12-04T07:44:00.002+09:002017-12-04T07:45:35.438+09:00Azure CLI 2.0 commands<textarea class="markdown" disabled="disabled">
Azure CLI 2.0 のコマンドメモ
##VM
###可用性セットで使用可能なVMのサイズを確認
```bash
az vm availability-set list-sizes \
--resource-group myResourceGroupAvailability \
--name myAvailabilitySet \
--output table
```
##参考
* https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/tutorial-availability-sets
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-66104210199773240672017-10-16T14:25:00.003+09:002017-10-16T14:25:18.459+09:00pm2 command<textarea class="markdown" disabled="disabled">
### show config
```
pm2 conf
```
### show module config
```
pm2 conf <module-name>
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-89705877038204039192017-09-16T21:44:00.001+09:002017-09-16T21:45:31.570+09:00Electron Apps<textarea class="markdown" disabled="disabled">
###Picty
画像ビューワ
Framework: Electron, Vue.js, material component web
対応プラットフォーム: Windows, OSX
https://github.com/fiahfy/picty
###Hosty
Hostsファイル管理アプリ
Framework: Electron, React.js, Material UI
対応プラットフォーム: Windows, OSX
https://github.com/fiahfy/hosty
</textarea>
fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-57286293328268659332017-09-08T07:52:00.002+09:002017-11-21T10:27:07.990+09:00Xcode command<textarea class="markdown" disabled="disabled">
### xcodebuild のバージョンを変更する
```
xcode-select --switch /Applications/Xcode.app
```
</textarea>
fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0tag:blogger.com,1999:blog-9046402748942318862.post-51253465415699418772017-08-25T09:26:00.000+09:002017-09-08T07:54:04.978+09:00gradle command<textarea class="markdown" disabled="disabled">
### task一覧
```
./gradlew tasks [--all]
```
### run test (Unit Test)
```
./gradlew test
```
debugだけ
```
./gradlew testDebugUnitTest
```
### run androidTest (Instrumentation Test)
```
./gradlew connectedAndroidTest
```
debugだけ
```
./gradlew connectedDebugAndroidTest
```
### projectの依存関係を表示する
```
./gradlew -q dependencies app:dependencies --configuration compile
```
</textarea>fiahfyhttp://www.blogger.com/profile/00918181872782952076noreply@blogger.com0