-
-
Notifications
You must be signed in to change notification settings - Fork 10
Connectの仕組み #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Connectの仕組み #60
Changes from 6 commits
089c2af
8cb4914
b97fb1c
88e6f18
7bbc99c
1a5fd36
2337d17
ad819cb
1d51181
eaad6be
712a4f2
ef91224
db48a29
230f403
4ae56e4
5d460d0
c521902
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,7 @@ Echoサーバとは、送られてきたリクエストの内容をそのまま | |
``` | ||
|
||
`app.use(middleware)` という形で、_middleware_と呼ばれる関数には`request`や`response`といったオブジェクトが渡されます。 | ||
そのため、リクエストみてフィルタリングしたり、任意のレスポンスを返したり出来るようになっています。 | ||
この`request`や`response`を_middleware_で処理することでログを取ったり、任意のレスポンスを返したり出来るようになっています。 | ||
|
||
Echoサーバでは `req.pipe(res);` という形でリクエストをそのままレスポンスとして流す事で実現されています。 | ||
|
||
|
@@ -47,4 +47,68 @@ Echoサーバでは `req.pipe(res);` という形でリクエストをそのま | |
基本的にどの_middleware_も`app.use(middleware)`という形で拡張でき、 | ||
モジュールとして実装すれば再利用もしやすい形となっています。 | ||
|
||
> **Note** _middleware_となる関数の引数が4つであると、それはエラーハンドリングの_middleware_とするという、Connectの独自のルールがあります。 | ||
> **Note** _middleware_となる関数の引数が4つであると、それはエラーハンドリングの_middleware_とするという、Connect独自のルールがあります。 | ||
|
||
## どういう仕組み | ||
|
||
Connectの_middleware_がどのような仕組みで動いているのかを見ていきます。 | ||
|
||
`app`に登録した_middleware_は、リクエスト時に呼び出されているので、 | ||
`app`のどこかに利用する_middleware_を保持していることは推測できると思います。 | ||
|
||
Connectでは`app.stack`にまだに_middleware_が保持されています。 | ||
次のような`app.stack`の中身を表示見ることで、_middleware_が登録順で保持されていることがわかります。 | ||
|
||
[import connect-trace-example.js](../../src/connect/connect-trace-example.js) | ||
|
||
後は、サーバへリクエストがやってきた時に、それぞれの_middleware_を順番に呼び出しています。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. リクエストされた時に There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. でもこれはConnect視点で書いたほうがいいか There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. サーバがリクエストを受け取った時に が良さそう |
||
|
||
上記の例だと以下の順番で_middleware_が呼び出されることになります。 | ||
|
||
- errorHandler | ||
- nosniff | ||
- hello | ||
|
||
エラーハンドリングの_middleware_はエラー時のみ呼ばれるため例外なので、 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. なので => となるので |
||
[nosniff.js](#nosniff.js) -> [hello.js](#hello.js) と呼び出されます。 | ||
|
||
[import nosniff.js](../../src/connect/nosniff.js) | ||
|
||
`nosniff.js`は、処理が終わったら`next()`を呼び出していて、 | ||
この`next()`が次の_middleware_へ行くという意味になります。 | ||
|
||
次に、`hello.js`を見てみると、`next()`がないことがわかります。 | ||
|
||
[import hello.js](../../src/connect/hello.js) | ||
|
||
`next()`がないということは`hello.js`がこの連続する_middleware_の最後となっていることがわかります。 | ||
仮に、これより先に_middleware_が登録されていたとしても無視されます。 | ||
|
||
つまり、処理的には以下のようにstackを先頭から一個づつ取り出して、処理していくという方法が取られています。 | ||
|
||
```js | ||
let req = "...", | ||
res = "..."; | ||
function next(){ | ||
let middleware = app.stack.shift(); | ||
// nextが呼ばれれば次のmiddleware | ||
middleware(req, res, next); | ||
} | ||
next();// 初回 | ||
``` | ||
|
||
|
||
このような_middleware_を繋げた形を_middleware stack_と呼ぶことがあります。 | ||
|
||
HTTPサーバではこのような_middleware stack_を作って使うものは既にあり、 | ||
PythonのWSGI MiddlewareやRubyのRackなどが該当します。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. このような_middleware stack_を作って使うものは => HTTPサーバ => 設計思想として |
||
|
||
Connectは`use`というメソッドで_middleware_を使うことからも分かりますが、 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rackを触ったことがある人はお気づきかもしれませんが? |
||
Rackを参考にして実装されています。 | ||
|
||
- [Ruby - Rack解説 - Rackの構造とRack DSL - Qiita](http://qiita.com/higuma/items/838f4f58bc4a0645950a#2-5 "Ruby - Rack解説 - Rackの構造とRack DSL - Qiita") | ||
|
||
次に、この_middleware stack_をどう処理しているのかを、 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. を を となってる |
||
具体的な実装を書きながら見て行きましょう。 | ||
|
||
## 実装してみよう |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
"use strict"; | ||
import errorHandler from "./errorHandler"; | ||
import hello from "./hello"; | ||
import nosniff from "./nosniff"; | ||
import connect from "connect"; | ||
|
||
const responseText = "response text"; | ||
let app = connect(); | ||
// add Error handling | ||
app.use(errorHandler()); | ||
// add "X-Content-Type-Options" to response | ||
app.use(nosniff()); | ||
// respond to all requests | ||
app.use(hello(responseText)); | ||
|
||
// print middleware list | ||
app.stack.map(({handle}) => console.log(handle)); | ||
/* => | ||
[Function: errorHandling] | ||
[Function: nosniff] | ||
[Function: hello] | ||
*/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
"use strict"; | ||
export default function (text) { | ||
return function (req, res) { | ||
return function hello(req, res) { | ||
res.end(text); | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
少し飛躍がある気がする