WebStormでExpressのテンプレートのscriptタグにCannot resolve directoryと出る時

Expressでなくとも、フレームワークを使っているときあるあるだと思います。

javascript - Webstorm: "Cannot Resolve Directory" - Stack Overflow

Settings→Directories→publicを右クリックしてresource rootを左クリック

didinj/mean-angular4-chat-appについて

Building Chat Application using MEAN Stack (Angular 4) and Socket.io

上のリンクに順を追って書かれているけれど、色々抜けているのでForkしたほうがよい。

MEANスタックは、Mongo DB, Express, Angular, Node.js で構成される。

ExpressがDBアクセスとJSONAPI, Socket.ioのサーバなどのバックエンドを担当して、Angularは表示などフロントエンドをする。

ルーティングはexpressで行う。angularへのルーティングはng buildによって生成されたdist/index.htmlをrender()することになる。よって、起動コマンドはng serveではなくnode なんたらになる。好みでpackage.jsonのnpm startをnodeなんたらに変える。

Socket.ioのサーバはroutes/chat.jsで動いている。他のサンプルではbin/wwwに書いてあるものもあった。見通しが悪くなってしまうので専用のファイルを作ったほうが良いかもしれない。もしくは別プロセスで動かすのも吉かもしれない。

チャット入室時

入室後

  • http://localhost:4000のSocket.ioで発言を送受信
  • Angularがhttp://localhost:3000/chat (Express)に発言をDBにも反映するためにPOSTしている
    二度手間になるのでサーバのSocket.ioの受信イベントにまとめるべきでは?

socket.ioのメッセージがブロードキャストされていて、localStorageにあるroomと一致する時表示するという方法を取っている。セキュリティ的にもトラフィック的にもSocket.ioのroom機能を利用して不必要なところには送らないようにすべき。

JSではthisが関数の実行時のオブジェクトとなるので、.bind(this)によって宣言時のthisになるようにしている。io.onでbind()しているのはon内の関数のthisがSocket.ioとなってしまうためにangularがもつchatsにpushできないため。宣言時にはangularなのでbindしていれば問題なくpushできる。

JSON.stringify()とは、JSONJSON形式の文字列にするメソッド。逆の働きをするのがparse()。

 

 

N 実践HTTP 15~ 覚書

URL設計は基本的にモデルを基準にする。単独で操作するケースが少ないモデルは、そのモデルが従属するモデルのURLで行う。例を出すと、試験問題モデルは試験モデルのURLでよい。

 passport.serializeUser( (obj,done) => {} )でユーザオブジェクトをどのようにセッションに埋め込むかを規定できる。例えば省メモリ化するためにIDのみ埋め込むなど。

passport.initialize() middleware not in useとエラーが出た。メッセージそのまま、app.use(passsport.initialize())の前にpassport.authenticate()していたため。

Nodeでオブジェクトのプロパティを全てログ出力したいときは、util.inspect()を使う。引数はバージョンによって違うのでドキュメントを見る。

 npm package.jsonのscriptsのキーでコマンドを定義できる。npm startもそこで定義されている。

supertestによってExpressを起動することなく、routerオブジェクトをテストすることができる。

github-stubなど、OAuthのスタブのライブラリがある。

supertestではget()でGETリクエストして、expectでヘッダやbodyの内容をチェックできる。当然正規表現も使える。

 UUIDとは、全世界で(ほぼ)唯一の文字列。主キーが推測されてはいけないとき等に使える。Sequelizeではこのデータ型が用意されている。

複合主キーの順番は、インデックスによって結果を絞る順番と同じなので、慎重に設計する必要がある。

Sequelizeはsync()でCREATE TABLEする。つまり、外部キー制約に引っかからないために、A→Bという関係がある時はA.sync().then( () => { B.belongsTo(なんたら); B.sync()})のようにする必要がある。

npm start でsync()する場合、当然ターミナルは最後のSQLのログを吐いて、サーバとしての役割をするため終了しない。10分くらい待ってしまった。

UPSERTとは、レコードが存在しない場合はINSERT,存在する場合はUPDATEを行うこと。

router.get('/new', checker, (req, res, next) => {
 

このcheckerは別のrouter。checkerを通してから処理できるので、ログインが必要なページにルーティングするとき、このように記述してcheckerに認証処理等をさせる。checkerは委譲されたルーティングを元に戻さないとダメなので戻認証処理の後にnext()が必要。

slice(0, 255)によって255文字以下にする。

.map((b) => { return { a:b , c-key:1 }  })とすれば、DBで従属側に外部キーを一気につけられる。

 sequelizeは基本的にSQLインジェクションが不可能だが、where句で複雑なものが使いたい時に、条件を文字列で書くと可能になってしまう。そこはちゃんとエスケープかプレースホルダを使う。

レスポンスヘッダのX-Frame-Options:SAMEORIGINにより、外部サイトからアクセスできないようになる。

オープンリダイレクタ脆弱性とは、http://hoge.com/login?to=http://危険.xyzというリンクによってhttp://危険.xyzにリダイレクトするようなこと。
ログイン前にログインが必要なページに行く→ログインする→ログイン後にそこにリダイレクト のようなケースでは、ログインページでクエリを基にcookieにリダイレクト先を書いておき、ログイン後にそれを基にリダイレクトする。
そのときオープンリダイレクタ脆弱性をもつ可能性がある。対策はドメイン名より後のパスのみをクエリにし、かつcookieに書き込む前にスキーマが含まないことを確認すること。

<img src="URL"のURLは画像じゃなくても良い。画像が動的に生成されるページもあるので拡張子は考慮されないため。つまり勝手にGETできるということ。

CSRFとはjsで勝手にログインしているAmazonなどに向けてPOSTすること。トークンと呼ばれるセッションIDに紐付いた推測不可能な文字列(ハッシュで作れる)をhiddenで埋め込み、一緒にPOSTすることによって防ぐことができる。組み込みのモジュールを使っておけば問題ない。

Bootstrap Form おさらい - Qiita

N 実践HTTP ~14 覚書

PORT=8000 npm startはLinuxでの書式。
Windowsではset PORT=8000 & npm start とする。このsetコマンドとは、実行中の環境(プロンプト)でのみ有効な環境変数を設定するコマンド。「&(アンパサンド)」はコマンドの区切り文字。複数のコマンドを連続で実行できる。

 

ExpressはデフォルトではX-powered-by ヘッダにExpressを書き込む。
つまり閲覧者にExpressを使用していることを知られてしまう。
helmetモジュールによってこれを送信しないように設定できる。
他にもいくつかセキュリティに有用なHTTPヘッダがあり、helmetによって有効化される。
Node.jsのセキュリティ・チェックリスト | プログラミング | POSTD
なお、X-powered-byを隠したいだけならhelmetを使用せずapp.disable('x-powered-by');でも良い。

express実践入門 · GitHub

 

router.get('/', function(req, res, next) {});のnextはnext()のように使う。次に一致する、このルートの次に対象範囲が広いルートに処理を渡す。

Express - node Webフレームワーク | 日本語ドキュメンテーション

 

Applicationクラスのuseメソッドは、新しくrouterオブジェクトやミドルウェアを登録したり、設定をしたりするもの。設定にはテンプレートのパスやテンプレートエンジン、ログなどがある。

app.get('env')で、開発環境かリリース環境か取得できる。

 Node.jsでは、エンコードなどCPUに負荷がかかる処理はイベントループを妨げるためしてはいけない。Scalajavaなどマルチスレッドの処理系に委譲すべき。

log(2);やlog(4);をconsole.log('2');に置換したい時、検索 log\((\d)\) 置換 console.log('$1')とする。数字の部分を置換後に使うため、カッコでくくった。置換後は$1,$2のように何番目か指定して使用する。

mochaでのテスト

  1. mochaはtest/test.jsを参照する。mochaのコマンドは長いので、npm testだけでmochaが実行されるようにpackage.jsonのscriptsを編集
  2. test/test.jsにテスト用のコードを書く

webpack

  • webpackとは、JSのモジュールを一つのファイルにまとめるもの。通信量削減や名前空間の隠蔽などメリットがある。
  • entry.jsはルートとなる。javaで言うとMain.java。ここから参照を始める。
  • JSを変更したらwebpackでビルドという手順。Nodeが起動している間に変更されたら自動でビルドするという設定もある。
  • uglify(JSの圧縮)も設定で可能。

 JQueryを使用したjsを最初に読み込んでしまうと、HTMLが読み込まれていないためにconst para = $('#id')が取得できない場合がある。最後に書くか、遅延読み込みか、何らかの策を講ずる必要がある。

X-Requested-withによってajaxのリクエストか判定できる。

 

N HTTPサーバ 22~26 覚書

PostgresSQLのCLI

psql -U ユーザ名 でログイン
\c データベース名 で使用するDBを決定
その後は普通にSQLを実行できる

!! Visual Studio CodeにはIDEAのキーバインドにする拡張機能がある!!

Number.MAX_SAFE_INTEGERによって、jsで正確に扱える範囲で最大の整数値が得られる。

cookieのexpiresはDateオブジェクトを設定する。

サイトのユーザにCookieでランダムの識別子(トラッキングID)を発行するものをトラッキングクッキーと言う。トラッキングIDでデータを紐付けることにより、匿名でも閲覧や書き込みの行動記録を得られるようになる。しかしCookieなので削除や改ざんができるため信用性に乏しい。

 

switch (req.method) {
case 'POST':
req.on('data', (data) => {
const decoded = decodeURIComponent(data);

これはPOSTで受信したデータをデコードする処理。
decodeURIComponent()する理由は「=」などの記号や日本語などが来ても扱えるようにするため。
関数名にURIがついているが、URI以外にも使える。
decodeURIという似たような関数があるが、これは記号をデコードしない。今回はイコールまで文字列比較を行いたい。よってdecodeURIComponent()が選ばれた。
最終的にdecodedの値はdata=somethingのようになる。

 

faviconのContentTypeは image/vnd.microsoft.icon となる。当たり前だがhtmlではない。

 

windowsにpostgreSQLのインストール

  1. 公式サイトからインストーラをダウンロードする。
  2. 普通にインストールする。スタックビルダがどうたらはしない。
  3. 環境変数にbinディレクトリを設定する。
  4. コマンドプロンプトpsql -U postgresを入力、パスワードも入力し、ログインできることを確認。

Node.jsのイベントループ

「for やめろ」またはイベントループと nextTick() - Block Rockin’ Codes

Node.jsはイベントのキューにイベントがあったら処理をする。

そしてイベントのキューにタスクがあるかどうかの確認でループし続けている(=ノンブロッキング)

イベントのキューにはIO用、setTimeout/setInterval用、setImmediate用、などの種類がある。この円の上にあるキューはlibuvで実装されていて、真ん中はnode.jsのもの。

f:id:namaza:20170807234912p:plain

Timers, Immediates and Process.nextTick— NodeJS Event Loop Part 2

 

流れとしては、キューを移動する前にnext tickキューを確認し、それが空になるまで処理し、空になったら移動する。タスク数の制限がないので注意が必要。
つまり、

開始
→next tick
→timers
→next tick
→IO
→next tick
→immediates
→next tick
→close handle

のように、毎回next tickをはさんで遷移する。

next tickにはタスク数の制限がないので、このコードは絶対に最後に「!」が出力される。こういった処理によってイベントループが回らなくなってしまう。

for (let i = 0; i < 10000; i++) {
process.nextTick( () => console.log('_'));
}

setImmediate( () => console.log('!'));