From 4902598c64c5ba19a04070a8b74b6f54f9f03690 Mon Sep 17 00:00:00 2001 From: azu Date: Thu, 17 Sep 2015 08:32:24 +0900 Subject: [PATCH 01/11] feat(connect): add junction --- src/connect/junction.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/connect/junction.js diff --git a/src/connect/junction.js b/src/connect/junction.js new file mode 100644 index 0000000..c58d9f9 --- /dev/null +++ b/src/connect/junction.js @@ -0,0 +1,25 @@ +"use strict"; +function applyMiddleware(text, middleware, next) { + middleware(text, next); +} + +export default class Junction { + constructor() { + this.stack = []; + } + + use(middleware) { + this.stack.push(middleware); + } + + process(text, callback) { + let next = (error, data) => { + let middleware = this.stack.shift(); + if (!middleware) { + return callback(error, data); + } + applyMiddleware(data, middleware, next); + }; + next(null, text); + } +} \ No newline at end of file From 6d33c424f1546469b4d2b7149855500d039117d2 Mon Sep 17 00:00:00 2001 From: azu Date: Thu, 17 Sep 2015 09:37:01 +0900 Subject: [PATCH 02/11] feat(connect): implement junction --- src/connect/junction.js | 23 ++++++++++++++++++++--- test/connect/junction-test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 test/connect/junction-test.js diff --git a/src/connect/junction.js b/src/connect/junction.js index c58d9f9..1565c6a 100644 --- a/src/connect/junction.js +++ b/src/connect/junction.js @@ -1,6 +1,23 @@ "use strict"; -function applyMiddleware(text, middleware, next) { - middleware(text, next); +function isErrorHandingMiddleware(middleware) { + // middleware(error, text, next) + var arity = middleware.length; + return arity === 3; +} +function applyMiddleware(error, text, middleware, next) { + let errorOnMiddleware = null; + try { + if (error && isErrorHandingMiddleware(middleware)) { + middleware(error, text, next); + } else { + middleware(text, next); + } + return; + } catch (error) { + errorOnMiddleware = error; + } + // skip the middleware or Error on the middleware + next(errorOnMiddleware, text); } export default class Junction { @@ -18,7 +35,7 @@ export default class Junction { if (!middleware) { return callback(error, data); } - applyMiddleware(data, middleware, next); + applyMiddleware(error, data, middleware, next); }; next(null, text); } diff --git a/test/connect/junction-test.js b/test/connect/junction-test.js new file mode 100644 index 0000000..658b7b8 --- /dev/null +++ b/test/connect/junction-test.js @@ -0,0 +1,27 @@ +// LICENSE : MIT +"use strict"; +import assert from "power-assert"; +import Junction from "../../src/connect/junction"; +describe("junction", function () { + describe("when", function () { + it("should", function (done) { + var junction = new Junction(); + junction.use(function errorHandling(error, text, next) { + next(error); + }); + junction.use(function toUpper(text, next) { + next(null, text.toLocaleUpperCase()); + }); + junction.use(function addDesu(text, next) { + next(null, text + " suffix"); + }); + junction.process("text", (error, result) => { + if (error) { + return done(error); + } + assert.equal(result, "TEXT suffix"); + done(); + }); + }); + }); +}); \ No newline at end of file From e2fc2a06287dac8c6f9f1b85ed241b16d6726488 Mon Sep 17 00:00:00 2001 From: azu Date: Thu, 17 Sep 2015 09:37:35 +0900 Subject: [PATCH 03/11] fix(connect): use let insteadof var --- src/connect/junction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connect/junction.js b/src/connect/junction.js index 1565c6a..dc282b5 100644 --- a/src/connect/junction.js +++ b/src/connect/junction.js @@ -1,7 +1,7 @@ "use strict"; function isErrorHandingMiddleware(middleware) { // middleware(error, text, next) - var arity = middleware.length; + let arity = middleware.length; return arity === 3; } function applyMiddleware(error, text, middleware, next) { From c3a3d84e21048d43455e7db83dfb70262e269174 Mon Sep 17 00:00:00 2001 From: azu Date: Thu, 17 Sep 2015 09:41:16 +0900 Subject: [PATCH 04/11] =?UTF-8?q?refactor(connect):=20text=E3=81=A8?= =?UTF-8?q?=E3=81=84=E3=81=86type=E3=81=AB=E9=99=90=E5=AE=9A=E3=81=97?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/connect/junction.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/connect/junction.js b/src/connect/junction.js index dc282b5..9acb1e6 100644 --- a/src/connect/junction.js +++ b/src/connect/junction.js @@ -4,20 +4,20 @@ function isErrorHandingMiddleware(middleware) { let arity = middleware.length; return arity === 3; } -function applyMiddleware(error, text, middleware, next) { +function applyMiddleware(error, data, middleware, next) { let errorOnMiddleware = null; try { if (error && isErrorHandingMiddleware(middleware)) { - middleware(error, text, next); + middleware(error, data, next); } else { - middleware(text, next); + middleware(data, next); } return; } catch (error) { errorOnMiddleware = error; } // skip the middleware or Error on the middleware - next(errorOnMiddleware, text); + next(errorOnMiddleware, data); } export default class Junction { @@ -29,7 +29,7 @@ export default class Junction { this.stack.push(middleware); } - process(text, callback) { + process(initialData, callback) { let next = (error, data) => { let middleware = this.stack.shift(); if (!middleware) { @@ -37,6 +37,6 @@ export default class Junction { } applyMiddleware(error, data, middleware, next); }; - next(null, text); + next(null, initialData); } } \ No newline at end of file From 783fd57d7052bc50bad5041d7f3f080024029169 Mon Sep 17 00:00:00 2001 From: azu Date: Thu, 17 Sep 2015 10:40:32 +0900 Subject: [PATCH 05/11] test(connect): add junction test --- test/connect/junction-test.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test/connect/junction-test.js b/test/connect/junction-test.js index 658b7b8..1a4267c 100644 --- a/test/connect/junction-test.js +++ b/test/connect/junction-test.js @@ -3,8 +3,8 @@ import assert from "power-assert"; import Junction from "../../src/connect/junction"; describe("junction", function () { - describe("when", function () { - it("should", function (done) { + context("when register middlewares", function () { + it("should connect middleware, the order is register", function (done) { var junction = new Junction(); junction.use(function errorHandling(error, text, next) { next(error); @@ -24,4 +24,23 @@ describe("junction", function () { }); }); }); + context("when occur error in middleware", function () { + it("should call errorHandling middleware", function (done) { + var junction = new Junction(); + junction.use(function toUpper(text, next) { + throw new Error("ROL"); + }); + // TODO: 順番に依存してる + junction.use(function errorHandling(error, text, next) { + assert(error instanceof Error); + done(); + }); + junction.process("text", (error, result) => { + if (error) { + return done(error); + } + done(); + }); + }); + }) }); \ No newline at end of file From cbfc8d7d13d0b1e05c4a0d93bc011574957e3f0a Mon Sep 17 00:00:00 2001 From: azu Date: Thu, 17 Sep 2015 21:16:39 +0900 Subject: [PATCH 06/11] fix(connect): correct errorHandler --- src/connect/errorHandler.js | 5 +++-- test/connect/hello-test.js | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/connect/errorHandler.js b/src/connect/errorHandler.js index de79749..e34d024 100644 --- a/src/connect/errorHandler.js +++ b/src/connect/errorHandler.js @@ -1,8 +1,9 @@ "use strict"; export default function () { return function errorHandling(err, req, res, next) { - console.error(err.stack); - res.status(500).send(err.message); + res.writeHead(404); + res.write(err.message); + res.end(); next(); }; } \ No newline at end of file diff --git a/test/connect/hello-test.js b/test/connect/hello-test.js index ef25e72..02a43e2 100644 --- a/test/connect/hello-test.js +++ b/test/connect/hello-test.js @@ -14,20 +14,20 @@ describe("connect", function () { describe("errorHandler", function () { beforeEach(function (done) { let app = connect(); - app.use(errorHandler()); app.use((req, res, next) => { next(new Error("wrong")); }); + app.use(errorHandler()); server = http.createServer(app).listen(3000, done); }); afterEach(function () { server && server.close(); }); - it("should return 500 status response", function () { + it("should return 404 status response", function () { return fetch("http://localhost:3000") .then(res => res.status) .then(status => { - assert(status, 500); + assert(status, 404); }); }); From 9e0acaf1f2636ac14f2f8cbec7de5e00bb360ab5 Mon Sep 17 00:00:00 2001 From: azu Date: Thu, 17 Sep 2015 22:48:09 +0900 Subject: [PATCH 07/11] chore(connect): use response object instead of string. --- src/connect/junction.js | 19 ++++++++++--------- test/connect/junction-test.js | 31 +++++++++++++++++-------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/connect/junction.js b/src/connect/junction.js index 9acb1e6..8b379d6 100644 --- a/src/connect/junction.js +++ b/src/connect/junction.js @@ -4,20 +4,20 @@ function isErrorHandingMiddleware(middleware) { let arity = middleware.length; return arity === 3; } -function applyMiddleware(error, data, middleware, next) { +function applyMiddleware(error, response, middleware, next) { let errorOnMiddleware = null; try { if (error && isErrorHandingMiddleware(middleware)) { - middleware(error, data, next); + middleware(error, response, next); } else { - middleware(data, next); + middleware(response, next); } return; } catch (error) { errorOnMiddleware = error; } // skip the middleware or Error on the middleware - next(errorOnMiddleware, data); + next(errorOnMiddleware, response); } export default class Junction { @@ -29,14 +29,15 @@ export default class Junction { this.stack.push(middleware); } - process(initialData, callback) { - let next = (error, data) => { + process(initialValue, callback) { + let response = {value: initialValue}; + let next = (error) => { let middleware = this.stack.shift(); if (!middleware) { - return callback(error, data); + return callback(error, response); } - applyMiddleware(error, data, middleware, next); + applyMiddleware(error, response, middleware, next); }; - next(null, initialData); + next(); } } \ No newline at end of file diff --git a/test/connect/junction-test.js b/test/connect/junction-test.js index 1a4267c..22d5f30 100644 --- a/test/connect/junction-test.js +++ b/test/connect/junction-test.js @@ -5,42 +5,45 @@ import Junction from "../../src/connect/junction"; describe("junction", function () { context("when register middlewares", function () { it("should connect middleware, the order is register", function (done) { - var junction = new Junction(); + let junction = new Junction(); junction.use(function errorHandling(error, text, next) { next(error); }); - junction.use(function toUpper(text, next) { - next(null, text.toLocaleUpperCase()); + junction.use(function toUpper(res, next) { + res.value = res.value.toLocaleUpperCase(); + next(); }); - junction.use(function addDesu(text, next) { - next(null, text + " suffix"); + junction.use(function addDesu(res, next) { + res.value += " suffix"; + next(); }); junction.process("text", (error, result) => { if (error) { return done(error); } - assert.equal(result, "TEXT suffix"); + assert.equal(result.value, "TEXT suffix"); done(); }); }); }); context("when occur error in middleware", function () { it("should call errorHandling middleware", function (done) { - var junction = new Junction(); - junction.use(function toUpper(text, next) { - throw new Error("ROL"); + let junction = new Junction(); + junction.use(function toUpper(res) { + throw new Error("error on " + res); }); - // TODO: 順番に依存してる - junction.use(function errorHandling(error, text, next) { + junction.use(function errorHandling(error, res, next) { assert(error instanceof Error); - done(); + assert.equal(res.value, "text"); + next(); }); - junction.process("text", (error, result) => { + junction.process("text", (error, res) => { if (error) { return done(error); } + assert.equal(res.value, "text"); done(); }); }); - }) + }); }); \ No newline at end of file From f33eb8f502af390e7189883e707b46b719ec7498 Mon Sep 17 00:00:00 2001 From: azu Date: Thu, 17 Sep 2015 22:49:40 +0900 Subject: [PATCH 08/11] =?UTF-8?q?fix(connect):=20=E3=82=A8=E3=83=A9?= =?UTF-8?q?=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3=E3=82=B0?= =?UTF-8?q?=E3=81=AE=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97=E9=A0=86=E3=81=AB?= =?UTF-8?q?=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ja/connect/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ja/connect/README.md b/ja/connect/README.md index d3b1308..de62da8 100644 --- a/ja/connect/README.md +++ b/ja/connect/README.md @@ -36,12 +36,13 @@ Echoサーバでは `req.pipe(res);` という形でリクエストをそのま それぞれの処理を_middleware_としてファイルを分けて実装し、`app.use(middleware)`で処理を追加しています。 -[import errorHandler.js](../../src/connect/errorHandler.js) [import nosniff.js](../../src/connect/nosniff.js) [import hello.js](../../src/connect/hello.js) +[import errorHandler.js](../../src/connect/errorHandler.js) + [import connect-example.js](../../src/connect/connect-example.js) 基本的にどの_middleware_も`app.use(middleware)`という形で拡張でき、 @@ -66,9 +67,9 @@ Connectが登録された_middleware_をどう処理するかというと、 上記の例だと以下の順番で_middleware_が呼び出されることになります。 -- errorHandler - nosniff - hello +- errorHandler エラーハンドリングの_middleware_は処理中にエラーが起きた時のみ呼ばれます。 From 1352536bd76144eeeefc1315bc3393613e92a6ff Mon Sep 17 00:00:00 2001 From: azu Date: Fri, 18 Sep 2015 09:29:02 +0900 Subject: [PATCH 09/11] feat(connect): add junction example --- src/connect/junction-example.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/connect/junction-example.js diff --git a/src/connect/junction-example.js b/src/connect/junction-example.js new file mode 100644 index 0000000..c395ff8 --- /dev/null +++ b/src/connect/junction-example.js @@ -0,0 +1,25 @@ +"use strict"; +import Junction from "./junction"; +import assert from "power-assert"; +let junction = new Junction(); +junction.use(function toUpperCase(res, next) { + res.value = res.value.toUpperCase(); + next(); +}); +junction.use(function exclamationMark(res, next) { + res.value = res.value + "!"; + next(); +}); +junction.use(function (error, res, next) { + console.error(error.stack); + next(); +}); + +let text = "hello world"; +junction.process(text, function (error, result) { + if (error) { + console.error(error); + } + let value = result.value; + assert.equal(value, "HELLO WORLD!"); +}); \ No newline at end of file From 6463df7f5ec58fa489fdd0c24dd23b754f6b9b17 Mon Sep 17 00:00:00 2001 From: azu Date: Fri, 18 Sep 2015 09:48:05 +0900 Subject: [PATCH 10/11] =?UTF-8?q?feat(connect):=20=E5=AE=9F=E8=A3=85?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=81=BF=E3=82=88=E3=81=86=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ja/connect/README.md | 20 ++++++++++++++++++-- src/connect/junction-example.js | 4 ++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/ja/connect/README.md b/ja/connect/README.md index de62da8..e1830f0 100644 --- a/ja/connect/README.md +++ b/ja/connect/README.md @@ -111,6 +111,22 @@ Rackを参考にして実装されています。 - [Ruby - Rack解説 - Rackの構造とRack DSL - Qiita](http://qiita.com/higuma/items/838f4f58bc4a0645950a#2-5 "Ruby - Rack解説 - Rackの構造とRack DSL - Qiita") -次は、先ほど抽象的なコードとなっていたものを、具体的な実装にしていきます。 +次は、先ほど抽象的なコードとなっていたものを具体的な実装にしながら見ていきます。 + +## 実装してみよう + +`Junction`というConnectライクな_middleware_をサポートしたものを作成してみます。 + +`Junction`は、`use(middleware)` と `process(value, (error, result) => { });`を持っているシンプルなクラスです。 + +[import junction.js](../../src/connect/junction.js) + +実装を見てみると、`use`で_middleware_を登録して、`process`で登録したミドルウェアを順番に実行していきます。 +そのため、`Junction`自体は渡されたデータは何も処理せずに、_middleware_との中継のみをしています。 + +登録する_middleware_はConnectと同じで、処理をしたら`next`を呼んで、次の_middleware_が処理するというのを繰り返しています。 + +使い方はConnectと引数の違いはありますが、ほぼ同じような形で利用できます。 + +[import junction-example.js](../../src/connect/junction-example.js) -## 実装してみよう \ No newline at end of file diff --git a/src/connect/junction-example.js b/src/connect/junction-example.js index c395ff8..63ae6f2 100644 --- a/src/connect/junction-example.js +++ b/src/connect/junction-example.js @@ -1,6 +1,6 @@ "use strict"; import Junction from "./junction"; -import assert from "power-assert"; +import assert from "assert"; let junction = new Junction(); junction.use(function toUpperCase(res, next) { res.value = res.value.toUpperCase(); @@ -10,7 +10,7 @@ junction.use(function exclamationMark(res, next) { res.value = res.value + "!"; next(); }); -junction.use(function (error, res, next) { +junction.use(function errorHandling(error, res, next) { console.error(error.stack); next(); }); From 69d334e590d8c49750442bfd5b4828aa1f43798a Mon Sep 17 00:00:00 2001 From: azu Date: Fri, 18 Sep 2015 09:55:55 +0900 Subject: [PATCH 11/11] =?UTF-8?q?fix(connect):=20=E3=83=9F=E3=83=89?= =?UTF-8?q?=E3=83=AB=E3=82=A6=E3=82=A7=E3=82=A2=20->=20middleware?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ja/connect/README.md | 2 +- test/prh-rule.yaml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ja/connect/README.md b/ja/connect/README.md index e1830f0..e84ab02 100644 --- a/ja/connect/README.md +++ b/ja/connect/README.md @@ -121,7 +121,7 @@ Rackを参考にして実装されています。 [import junction.js](../../src/connect/junction.js) -実装を見てみると、`use`で_middleware_を登録して、`process`で登録したミドルウェアを順番に実行していきます。 +実装を見てみると、`use`で_middleware_を登録して、`process`で登録した_middleware_を順番に実行していきます。 そのため、`Junction`自体は渡されたデータは何も処理せずに、_middleware_との中継のみをしています。 登録する_middleware_はConnectと同じで、処理をしたら`next`を呼んで、次の_middleware_が処理するというのを繰り返しています。 diff --git a/test/prh-rule.yaml b/test/prh-rule.yaml index d93cc60..def02aa 100644 --- a/test/prh-rule.yaml +++ b/test/prh-rule.yaml @@ -72,3 +72,6 @@ rules: pattern: - プラグイン機構 - プラグインのアーキテクチャ + - expected: middleware + pattern: + - ミドルウェア \ No newline at end of file