├── examples ├── index.html ├── test.js ├── all.js ├── app2.js ├── viewctrl.js ├── app.js └── allctrl.js ├── packages ├── slet-basecontroller │ ├── codecov.yml │ ├── test │ │ ├── req │ │ │ ├── fixtures │ │ │ │ ├── .name │ │ │ │ ├── % of dogs.txt │ │ │ │ ├── name.txt │ │ │ │ ├── name.tmpl │ │ │ │ ├── user.tmpl │ │ │ │ ├── blog │ │ │ │ │ ├── index.html │ │ │ │ │ └── post │ │ │ │ │ │ └── index.tmpl │ │ │ │ ├── user.html │ │ │ │ ├── default_layout │ │ │ │ │ ├── name.tmpl │ │ │ │ │ └── user.tmpl │ │ │ │ ├── email.tmpl │ │ │ │ ├── local_layout │ │ │ │ │ └── user.tmpl │ │ │ │ ├── ip.js │ │ │ │ ├── ips.js │ │ │ │ ├── path.js │ │ │ │ ├── query.js │ │ │ │ ├── query2.js │ │ │ │ ├── param2.js │ │ │ │ ├── param.js │ │ │ │ ├── reqget.js │ │ │ │ ├── reqget1.js │ │ │ │ ├── reqaccepts2.js │ │ │ │ ├── xhr.js │ │ │ │ ├── host.js │ │ │ │ ├── reqaccepts.js │ │ │ │ ├── reqfresh2.js │ │ │ │ ├── reqfresh3.js │ │ │ │ ├── hostname.js │ │ │ │ ├── param3.js │ │ │ │ ├── reqget2.js │ │ │ │ ├── host2.js │ │ │ │ ├── req.acceptsCharset.js │ │ │ │ ├── req.acceptsCharset2.js │ │ │ │ ├── req.acceptsEncoding2.js │ │ │ │ ├── req.acceptsEncodings2.js │ │ │ │ ├── reqaccepts4.js │ │ │ │ ├── hostname2.js │ │ │ │ ├── reqaccepts3.js │ │ │ │ ├── reqfresh.js │ │ │ │ ├── req.acceptsEncoding.js │ │ │ │ └── req.acceptsEncodings.js │ │ │ ├── req.path.js │ │ │ ├── req.xhr.js │ │ │ ├── req.ip.js │ │ │ ├── req.query.js │ │ │ ├── req.acceptsEncoding.js │ │ │ ├── req.acceptsEncoding2.js │ │ │ ├── req.get.js │ │ │ ├── req.fresh.js │ │ │ ├── req.acceptsCharset.js │ │ │ ├── req.acceptsCharsets.js │ │ │ ├── req.ips.js │ │ │ ├── req.hostname.js │ │ │ ├── req.host.js │ │ │ ├── req.param.js │ │ │ └── req.accepts.js │ │ ├── res │ │ │ ├── fixtures │ │ │ │ ├── send.js │ │ │ │ ├── jsonp4.js │ │ │ │ ├── jsonp11.js │ │ │ │ ├── jsonp12.js │ │ │ │ ├── jsonp8.js │ │ │ │ ├── json.js │ │ │ │ ├── jsonp17.js │ │ │ │ ├── jsonp10.js │ │ │ │ ├── jsonp15.js │ │ │ │ ├── jsonp16.js │ │ │ │ ├── jsonp9.js │ │ │ │ ├── redirect.js │ │ │ │ ├── jsonp5.js │ │ │ │ ├── jsonp6.js │ │ │ │ ├── clearCookie.js │ │ │ │ ├── jsonp.js │ │ │ │ ├── location.js │ │ │ │ ├── clearCookie2.js │ │ │ │ ├── jsonp14.js │ │ │ │ ├── jsonp2.js │ │ │ │ ├── jsonp3.js │ │ │ │ ├── json2.js │ │ │ │ ├── jsonp7.js │ │ │ │ ├── links.js │ │ │ │ ├── locals.js │ │ │ │ └── jsonp13.js │ │ │ ├── res.send.js │ │ │ ├── res.location.js │ │ │ ├── res.redirect.js │ │ │ ├── res.links.js │ │ │ ├── res.locals.js │ │ │ ├── res.json.js │ │ │ ├── res.clearCookie.js │ │ │ └── res.jsonp.js │ │ ├── fixtures │ │ │ ├── postctrl.js │ │ │ ├── queryctrl.js │ │ │ ├── paramctrl.js │ │ │ ├── basectrl2.js │ │ │ ├── basectrl.js │ │ │ └── allctrl.js │ │ ├── all.js │ │ ├── params.js │ │ ├── query.js │ │ ├── body.js │ │ └── base.js │ ├── .travis.yml │ ├── app.js │ ├── .vscode │ │ └── launch.json │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ └── index.js └── slet │ ├── test │ ├── view │ │ ├── fixtures │ │ │ ├── index.html │ │ │ ├── v2.js │ │ │ ├── v1.js │ │ │ ├── v0.js │ │ │ ├── v3.js │ │ │ └── base.js │ │ └── view.js │ ├── controller │ │ ├── fixtures │ │ │ ├── index.html │ │ │ ├── base.js │ │ │ ├── ctrl.js │ │ │ └── viewctrl.js │ │ ├── view.js │ │ └── base.js │ ├── router │ │ ├── routerDir │ │ │ ├── fixtures │ │ │ │ └── pathctrl.js │ │ │ └── 3-routerDir.1.js │ │ ├── fixtures │ │ │ ├── pathctrl.js │ │ │ ├── ctrl.js │ │ │ ├── thispath.js │ │ │ └── paramctrl.js │ │ ├── params.js │ │ ├── 2-path.js │ │ ├── 1-path.js │ │ ├── 2-controller.js │ │ ├── 1-controller.js │ │ └── 3-routerDir.1.js │ ├── filter │ │ ├── post_filter.js │ │ ├── fixtures │ │ │ ├── get.js │ │ │ └── post.js │ │ └── get_filter.js │ └── helloworld.js │ ├── index.js │ ├── app2.js │ ├── src │ ├── config.js │ └── Slet.js │ ├── .vscode │ └── launch.json │ └── package.json ├── codecov.yml ├── lerna.json ├── docs ├── tips.md └── todo.md ├── .travis.yml ├── app.async.js ├── app.js ├── .vscode └── launch.json ├── .gitignore ├── LICENSE ├── package.json └── README.md /examples/index.html: -------------------------------------------------------------------------------- 1 |

{{title}}

-------------------------------------------------------------------------------- /packages/slet-basecontroller/codecov.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/.name: -------------------------------------------------------------------------------- 1 | tobi -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/% of dogs.txt: -------------------------------------------------------------------------------- 1 | 20% -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/name.txt: -------------------------------------------------------------------------------- 1 | tobi -------------------------------------------------------------------------------- /packages/slet/test/view/fixtures/index.html: -------------------------------------------------------------------------------- 1 |

{{title}}

-------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/name.tmpl: -------------------------------------------------------------------------------- 1 |

$name

-------------------------------------------------------------------------------- /packages/slet/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./src/Slet') 2 | -------------------------------------------------------------------------------- /packages/slet/test/controller/fixtures/index.html: -------------------------------------------------------------------------------- 1 |

{{title}}

-------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/user.tmpl: -------------------------------------------------------------------------------- 1 |

$user.name

-------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/blog/index.html: -------------------------------------------------------------------------------- 1 | index -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/user.html: -------------------------------------------------------------------------------- 1 |

{{user.name}}

-------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/default_layout/name.tmpl: -------------------------------------------------------------------------------- 1 |

$name

-------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/email.tmpl: -------------------------------------------------------------------------------- 1 |

This is an email

-------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | parsers: 3 | javascript: 4 | enable_partials: no -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/blog/post/index.tmpl: -------------------------------------------------------------------------------- 1 |

blog post

-------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/default_layout/user.tmpl: -------------------------------------------------------------------------------- 1 |

$user.name

-------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/local_layout/user.tmpl: -------------------------------------------------------------------------------- 1 | $user.name -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.0.0-beta.31", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "version": "1.4.8" 7 | } 8 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - stable 5 | script: 6 | - npm test 7 | after_success: 8 | - npm run report-coverage -------------------------------------------------------------------------------- /docs/tips.md: -------------------------------------------------------------------------------- 1 | # Tips 2 | 3 | ## 测试 4 | 5 | 脚本需要先lerna bootstrap 6 | 7 | > "test": "lerna bootstrap && lerna run test", 8 | 9 | 自测的时候,最好 10 | 11 | > "test": "lerna run test", 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - stable 5 | - 4 6 | - 5 7 | - 6 8 | script: 9 | - npm test 10 | after_success: 11 | - npm run report-coverage -------------------------------------------------------------------------------- /examples/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | 4 | var A = require('./test/router/fixtures/thispath') 5 | var a = new A({ 6 | request:{ 7 | body: { 8 | 9 | } 10 | } 11 | }, function(){}) 12 | 13 | console.log(a.path) -------------------------------------------------------------------------------- /packages/slet/test/controller/fixtures/base.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../slet-basecontroller') 4 | const vt = require('nunjucks') 5 | 6 | module.exports = class MyViewController extends BaseController { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/send.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.send(); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet/app2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Slet = require('./') 4 | const app = new Slet({ 5 | root: __dirname, 6 | debug: true, 7 | views:{ 8 | path: '/test/controller/fixtures/', 9 | extension: 'html' 10 | } 11 | }) 12 | 13 | app.router('/', require('./test/controller/fixtures/viewctrl.js')) 14 | 15 | app.start(3000) 16 | -------------------------------------------------------------------------------- /packages/slet/test/router/routerDir/fixtures/pathctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../../slet-basecontroller') 4 | 5 | class PathController extends BaseController { 6 | get() { 7 | return { 8 | a:1 9 | } 10 | } 11 | } 12 | 13 | PathController.path = '/path/a' 14 | 15 | module.exports = PathController -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/ip.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | post (req, res) { 13 | res.send(req.ip); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/ips.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | post (req, res) { 13 | res.send(req.ips); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp4.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/4' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp({}); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/path.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/:any' 10 | } 11 | 12 | get (req, res) { 13 | res.send(req.path) 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/query.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.send(req.query) 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/query2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | } 11 | 12 | get (req, res) { 13 | res.send(req.qs) 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp11.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/11' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp(300); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp12.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/12' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp('str'); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp8.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/8' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp(null); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/json.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.json({ foo: 'bar' }); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp17.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/17' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp(200, 201); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet/test/view/fixtures/v2.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseViewController = require('./base') 4 | 5 | module.exports = class MyViewController extends BaseViewController { 6 | 7 | get() { 8 | var a = this.query.a 9 | 10 | // use tpl && data 11 | return this.render('index', { 12 | title: 'ssddssdd a= ' + a 13 | }) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/all.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Slet = require('../'); 4 | const app = new Slet({ 5 | root: __dirname, 6 | debug: true, 7 | auto:true, 8 | "views" :{ 9 | "path" : __dirname, 10 | "option": { "map": {"html": "nunjucks" }} 11 | } 12 | }); 13 | 14 | 15 | 16 | app.router('./allctrl') 17 | 18 | 19 | app.start(3000) 20 | 21 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/param2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | post (req, res) { 13 | res.end(req.param('name')); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp10.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/10' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp({ name: 'tobi' }); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp15.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/15' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp(201, { id: 1 }); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp16.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/16' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp({ id: 1 }, 201); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/param.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | post (req, res) { 13 | res.end(req.param('name', 'tj')); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqget.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | post (req, res) { 13 | res.end(req.get('Content-Type')); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqget1.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/refer' 10 | } 11 | 12 | post (req, res) { 13 | res.send(req.get('Referer')) 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp9.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/9' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp(['foo', 'bar', 'baz']) 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/redirect.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.redirect('http://google.com'); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/app.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Slet = require('../slet') 4 | 5 | const app = new Slet({ 6 | root: __dirname, 7 | debug: true 8 | }) 9 | 10 | // app.defineController(require('.')) 11 | 12 | app.router('test/fixtures/basectrl') 13 | 14 | app.router('test/fixtures/postctrl') 15 | 16 | app.router('test/fixtures/allctrl') 17 | 18 | app.start(4005) 19 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp5.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/5' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp({str: '\u2028 \u2029 woot' }) 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet/test/view/fixtures/v1.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseViewController = require('./base') 4 | 5 | module.exports = class MyViewController extends BaseViewController { 6 | 7 | get() { 8 | var a = this.query.a 9 | 10 | // use tpl 11 | this.data = { 12 | title: 'ssddssdd a= ' + a 13 | } 14 | return this.render('index') 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqaccepts2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | } 11 | 12 | get (req, res) { 13 | res.end(req.accepts('json', 'html')); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/xhr.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | // console.dir(req) 14 | res.send(req.xhr) 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp6.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/6' 10 | } 11 | 12 | get (req, res) { 13 | res.jsonp({ str: '\u2028 \u2029 woot' }); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/host.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | post (req, res) { 13 | // console.log(req.get()) 14 | res.end(req.host) 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqaccepts.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.end(req.accepts('json') ? 'yes' : 'no'); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/clearCookie.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.clearCookie('sid') 14 | res.end(); 15 | } 16 | } -------------------------------------------------------------------------------- /docs/todo.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | - [ ] defineMiddleware从配置里读取 4 | - [x] Controller机制,类似于插件,将依赖移到controller模块里去,精简 5 | 6 | 7 | 8 | ## 可视化todo 9 | 10 | - 全局中间件 11 | - 创建Controller 12 | - path 13 | - get|post等方法 14 | - 方法前后,配置中间件 15 | 16 | 17 | 根据path决定,是否走全局路由,走哪些全局路由 18 | 19 | 每个请求都有自己的中间件栈 20 | 21 | 继承api 22 | - get|post 23 | - upload 24 | - sesssion 25 | - db 26 | 继承view 27 | - 28 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqfresh2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | } 11 | 12 | get (req, res) { 13 | res.etag = '"123"' 14 | res.send(req.fresh) 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqfresh3.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/3' 10 | } 11 | 12 | get (req, res) { 13 | res._headers = null 14 | res.send(req.fresh) 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | // console.log(res) 14 | res.jsonp({ count: 1 }); 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet/test/router/fixtures/pathctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../slet-basecontroller') 4 | 5 | class PathController extends BaseController { 6 | get() { 7 | var a = this.query.a 8 | 9 | return { 10 | a:1, 11 | b: a 12 | } 13 | } 14 | } 15 | 16 | PathController.path = '/path/a' 17 | 18 | module.exports = PathController -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/hostname.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | post (req, res) { 13 | // console.log(req.get()) 14 | res.end(req.hostname) 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/param3.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/user/:name' 10 | } 11 | 12 | post (req, res) { 13 | res.send(req.param('filter') + req.param('name')); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqget2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | } 11 | 12 | post (req, res) { 13 | // console.log(req.get()) 14 | res.send(req.get()) 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet/test/router/fixtures/ctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../slet-basecontroller') 4 | 5 | module.exports = class MainController extends BaseController { 6 | get() { 7 | var a = this.query.a 8 | 9 | return { 10 | a:1, 11 | b: a 12 | } 13 | } 14 | 15 | post(){ 16 | return { 17 | a:1 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/host2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | } 11 | 12 | post (req, res) { 13 | req.headers.host = undefined; 14 | res.end(String(req.host)); 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/req.acceptsCharset.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no') 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/req.acceptsCharset2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.end(req.acceptsCharsets('utf-8') ? 'yes' : 'no') 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/req.acceptsEncoding2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | req.acceptsEncoding('bogus') 14 | res.end() 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/req.acceptsEncodings2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | req.acceptsEncodings('bogus') 14 | res.end() 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqaccepts4.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/4' 10 | } 11 | 12 | get (req, res) { 13 | res.end(req.accepts(['text/html', 'application/json'])); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/location.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.location('http://google.com').end() 14 | // res.end(); 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/hostname2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | } 11 | 12 | post (req, res) { 13 | req.headers.host = null; 14 | res.send(String(req.hostname)); 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/clearCookie2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | } 11 | 12 | get (req, res) { 13 | res.clearCookie('sid', { path: '/admin' }) 14 | res.end(); 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp14.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/14' 10 | this.json_spaces = 2 11 | } 12 | 13 | get (req, res) { 14 | res.jsonp({ name: 'tobi', age: 2 }); 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | // this.jsonp_callback_name = 'clb' 11 | } 12 | 13 | get (req, res) { 14 | res.jsonp({ count: 1 }); 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp3.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/3' 10 | this.jsonp_callback_name = 'clb' 11 | } 12 | 13 | get (req, res) { 14 | res.jsonp({ count: 1 }); 15 | } 16 | } -------------------------------------------------------------------------------- /packages/slet/test/view/fixtures/v0.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseViewController = require('./base') 4 | 5 | module.exports = class MyViewController extends BaseViewController { 6 | 7 | get() { 8 | var a = this.query.a 9 | 10 | // use default 11 | this.tpl = 'index' 12 | this.data = { 13 | title: 'ssddssdd a= ' + a 14 | } 15 | 16 | return this.render() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqaccepts3.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/3' 10 | } 11 | 12 | get (req, res) { 13 | res.end(req.accepts(['text/html', 'application/json']) ? 'yup' : 'nope'); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/reqfresh.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | let etag = '"12345"' 14 | res.etag = etag 15 | res.send(req.fresh) 16 | } 17 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/json2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/2' 10 | } 11 | 12 | get (req, res) { 13 | res.type = 'application/vnd.example+json' 14 | res.json({ hello: 'world' }); 15 | } 16 | } -------------------------------------------------------------------------------- /examples/app2.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Slet = require('./'); 4 | const app = new Slet({ 5 | root: __dirname+'/test/dept', 6 | debug: true, 7 | auto:true, 8 | "views" :{ 9 | "path" : __dirname, 10 | "option": { "map": {"html": "nunjucks" }} 11 | } 12 | }); 13 | 14 | 15 | 16 | app.identifyDept().then(function(r){ 17 | console.log(r) 18 | 19 | }) 20 | 21 | 22 | app.start(3000) 23 | 24 | -------------------------------------------------------------------------------- /packages/slet/test/view/fixtures/v3.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseViewController = require('./base') 4 | 5 | module.exports = class MyViewController extends BaseViewController { 6 | 7 | get() { 8 | var a = this.query.a 9 | 10 | // custom 11 | this.renderType = 'view' 12 | 13 | return { 14 | tpl: 'index', 15 | data: { 16 | title: 'ssddssdd a= ' + a 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/req.acceptsEncoding.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | req.acceptsEncoding('gzip') 14 | req.acceptsEncoding('deflate') 15 | res.end(); 16 | } 17 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/fixtures/req.acceptsEncodings.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | req.acceptsEncodings('gzip') 14 | req.acceptsEncodings('deflate') 15 | res.end(); 16 | } 17 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/fixtures/postctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../') 4 | 5 | module.exports = class MyParamsController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/post' 10 | } 11 | 12 | post () { 13 | // matches "POST /post" 14 | // pp['name'] is 'foo' or 'bar' 15 | return `Hello ${this.reqbody['name']}!` 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/fixtures/queryctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../') 4 | 5 | module.exports = class MyParamsController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/query' 10 | } 11 | 12 | get () { 13 | // matches "GET /base" 14 | // this.end() 15 | // return ssssaaaa 16 | 17 | return this.query.a 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp7.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/7' 10 | } 11 | 12 | get (req, res) { 13 | res.type = 'application/vnd.example+json' 14 | // console.log(res.type) 15 | res.jsonp({ hello: 'world' }) 16 | } 17 | } -------------------------------------------------------------------------------- /examples/viewctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const ViewController = require('.').ViewController 4 | 5 | module.exports = class MyController extends ViewController { 6 | constructor(app, ctx, next) { 7 | super(app, ctx, next) 8 | } 9 | 10 | get() { 11 | var a = this.query.a 12 | // this.renderType='view' 13 | return { 14 | tpl: 'index', 15 | data: { 16 | title: 'ssddssdd a= ' + a 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/res.send.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('should set body to ""', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/send') 14 | 15 | sletTest(app) 16 | .get('/') 17 | .expect(200, '', t.end); 18 | }) 19 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/fixtures/paramctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../') 4 | 5 | module.exports = class MyParamsController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/hello/:name' 10 | } 11 | 12 | get () { 13 | // matches "GET /hello/foo" and "GET /hello/bar" 14 | // params['name'] is 'foo' or 'bar' 15 | return `Hello ${this.params['name']}!` 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/slet/test/controller/fixtures/ctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../slet-basecontroller') 4 | 5 | module.exports = class MainController extends BaseController { 6 | constructor(app, ctx, next) { 7 | super(app, ctx, next) 8 | } 9 | 10 | get() { 11 | var a = this.query.a 12 | 13 | return { 14 | a:1, 15 | b: a 16 | } 17 | } 18 | 19 | post(){ 20 | return { 21 | a:1 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/links.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.links({ 14 | next: 'http://api.example.com/users?page=2', 15 | last: 'http://api.example.com/users?page=5' 16 | }); 17 | res.end(); 18 | } 19 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/locals.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/' 10 | } 11 | 12 | get (req, res) { 13 | res.end(Object.keys(res.locals).join("")); 14 | } 15 | 16 | post (req, res) { 17 | res.locals.foo = 'bar'; 18 | res.json(res.locals) 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/fixtures/basectrl2.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../') 4 | 5 | module.exports = class MyParamsController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/base2' 10 | } 11 | 12 | get () { 13 | // matches "GET /base" 14 | // this.end() 15 | // return ssssaaaa 16 | this.ctx.status = 404 17 | 18 | this.write('ssss') 19 | this.end('aaaa') 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.path.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('.path should return the parsed pathname', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/path') 14 | 15 | sletTest(app) 16 | .get('/login?redirect=/post/1/comments') 17 | .expect(200, '/login', t.end); 18 | }) 19 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/res.location.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('should set the header', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/location') 14 | 15 | sletTest(app) 16 | .get('/') 17 | .expect('Location', 'http://google.com') 18 | .expect(200, t.end); 19 | }) 20 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/fixtures/jsonp13.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../..') 4 | 5 | module.exports = class MyController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/13' 10 | this.json_replacer = function(key, val){ 11 | return '_' == key[0] 12 | ? undefined 13 | : val; 14 | } 15 | } 16 | 17 | get (req, res) { 18 | res.jsonp({ name: 'tobi', _id: 12345 }); 19 | } 20 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/res.redirect.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('should default to a 302 redirect', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/redirect') 14 | 15 | sletTest(app) 16 | .get('/') 17 | .expect('Location', 'http://google.com') 18 | .expect(302, t.end); 19 | }) 20 | -------------------------------------------------------------------------------- /packages/slet/test/filter/post_filter.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../..'); 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }); 10 | 11 | app.router('fixtures/post') 12 | 13 | test.cb('GET /c', t => { 14 | sletTest(app) 15 | .post('/c') 16 | .send({a:1}) 17 | .expect(200, function (err, res) { 18 | t.ifError(err) 19 | t.is(res.text, 'some', 'res.text == Hello foo!') 20 | t.end() 21 | }) 22 | }) -------------------------------------------------------------------------------- /packages/slet/test/router/fixtures/thispath.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../slet-basecontroller') 4 | 5 | class ThisPathController extends BaseController { 6 | constructor(app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/path/this' 10 | } 11 | 12 | get() { 13 | var a = this.query.a 14 | 15 | return { 16 | a:1, 17 | b: a 18 | } 19 | } 20 | } 21 | 22 | // ThisPathController.path = '/path/this' 23 | module.exports = ThisPathController 24 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.xhr.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('.xhr should return true when X-Requested-With is xmlhttprequest', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/xhr') 14 | 15 | sletTest(app) 16 | .get('/') 17 | .set('X-Requested-With', 'xmlhttprequest') 18 | .expect(200, 'true', t.end); 19 | }) 20 | -------------------------------------------------------------------------------- /app.async.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Slet = require('./packages/slet') 4 | 5 | const app = new Slet() 6 | 7 | class MyController extends Slet.BaseController { 8 | async get (req, res) { 9 | let username = req.query.username 10 | // logic 11 | await this.sleep(300) 12 | 13 | // send to browser 14 | return res.send(`hello world ${username}`) 15 | } 16 | 17 | sleep (time) { 18 | return new Promise((resolve) => setTimeout(resolve, time)) 19 | } 20 | } 21 | 22 | app.router('/', MyController) 23 | 24 | app.start(3006) 25 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Slet = require('./packages/slet') 4 | 5 | const app = new Slet() 6 | 7 | class MyController extends Slet.BaseController { 8 | constructor (app, ctx, next) { 9 | super(app, ctx, next) 10 | 11 | this.path = '/' 12 | } 13 | 14 | get (req, res) { 15 | return ({ hello: 'world' }) 16 | } 17 | 18 | post(req, res) { 19 | var a = this.pp.a 20 | 21 | return res.body = "ssss" +a 22 | } 23 | } 24 | 25 | app.router(MyController) 26 | 27 | app.start(3000) 28 | 29 | module.exports = app.callback() 30 | -------------------------------------------------------------------------------- /packages/slet/test/router/fixtures/paramctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const BaseController = require('../../../../slet-basecontroller') 3 | 4 | module.exports = class MyParamsController extends BaseController { 5 | constructor(app, ctx, next) { 6 | super(app, ctx, next) 7 | 8 | this.path = '/hello/:name' 9 | } 10 | 11 | alias () { 12 | this.params = this.ctx.params 13 | } 14 | 15 | get () { 16 | // matches "GET /hello/foo" and "GET /hello/bar" 17 | // params['name'] is 'foo' or 'bar' 18 | return `Hello ${this.params['name']}!` 19 | } 20 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/fixtures/basectrl.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../') 4 | 5 | module.exports = class MyParamsController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/base' 10 | } 11 | 12 | get () { 13 | // matches "GET /base" 14 | // this.end() 15 | // return ssssaaaa 16 | this.ctx.status = 404 17 | 18 | // this.ctx.type = 'text'; 19 | // this.res.statusCode = 200; 20 | this.res.write('ssss') 21 | 22 | this.end('aaaa') 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/slet/test/router/routerDir/3-routerDir.1.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../..'); 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }); 10 | 11 | app.routerDir('fixtures', '/prefix') 12 | 13 | test.cb('GET /hello/foo', t => { 14 | sletTest(app) 15 | .get('/prefix/path/a?a=1') 16 | .expect(200, function (err, res) { 17 | // console.log(res) 18 | t.ifError(err) 19 | t.is(res.body.a, 1, 'res.text == Hello foo!') 20 | t.end() 21 | }) 22 | }) 23 | 24 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/all.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../slet') 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }) 10 | 11 | app.silent = true 12 | 13 | app.router('fixtures/allctrl') 14 | 15 | test.cb('GET /all test this.all()', t => { 16 | sletTest(app) 17 | .get('/all') 18 | .expect(404, function (err, res) { 19 | t.ifError(err) 20 | // console.log(res) 21 | t.is(res.text, 'ssssaaaa', 'res.text == ssssaaaa!') 22 | t.end() 23 | }) 24 | }) 25 | 26 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/res.links.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('should set Link header field', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/links') 14 | 15 | sletTest(app) 16 | .get('/') 17 | .expect('Link', '; rel="next", ; rel="last"') 18 | .expect(200,t.end); 19 | }) 20 | -------------------------------------------------------------------------------- /packages/slet/test/helloworld.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | 'use strict' 4 | 5 | const Slet = require('../') 6 | 7 | const app = new Slet() 8 | 9 | class MyController extends Slet.BaseController { 10 | get () { 11 | return `Hello world` 12 | } 13 | } 14 | 15 | app.router('/', MyController) 16 | 17 | var sletTest = require('slettest') 18 | 19 | test.cb('GET /', t => { 20 | sletTest(app) 21 | .get('/') 22 | .expect(200, function (err, res) { 23 | t.ifError(err) 24 | t.is(res.text, 'Hello world', 'res.text == Hello foo!') 25 | t.end() 26 | }) 27 | }) -------------------------------------------------------------------------------- /packages/slet/src/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "debug": false, 3 | "prefix": "", 4 | "views":{ 5 | "engine": "nunjucks", 6 | "path": "/", 7 | "extension": "html" 8 | }, 9 | "automount": { 10 | "path": "controllers", 11 | "option": { 12 | "recurse": true 13 | } 14 | }, 15 | "mockCtx": { 16 | "request":{ 17 | "body": { 18 | 19 | } 20 | } 21 | }, 22 | "logger": { 23 | // Define a custom request id function 24 | genReqId: function (req) { return req.id }, 25 | 26 | // Logger level is `info` by default 27 | useLevel: 'trace' 28 | } 29 | } -------------------------------------------------------------------------------- /packages/slet/test/filter/fixtures/get.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../slet-basecontroller') 4 | 5 | class PathController extends BaseController { 6 | constructor(app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/c' 10 | 11 | this.get_filter = [this.log] 12 | } 13 | 14 | log(ctx, next){ 15 | ctx.someText = 'some' 16 | return next().then(function(){ 17 | }) 18 | } 19 | 20 | get() { 21 | var a = this.query.a 22 | // console.log(a) 23 | setTimeout(function(){ 24 | process.exit(0) 25 | }, 100) 26 | 27 | return this.ctx.someText 28 | } 29 | } 30 | 31 | module.exports = PathController -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible Node.js debug attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceRoot}/app.js", 12 | "cwd": "${workspaceRoot}" 13 | }, 14 | { 15 | "type": "node", 16 | "request": "attach", 17 | "name": "Attach to Process", 18 | "port": 5858 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/slet/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible Node.js debug attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceRoot}/app2.js", 12 | "cwd": "${workspaceRoot}" 13 | }, 14 | { 15 | "type": "node", 16 | "request": "attach", 17 | "name": "Attach to Process", 18 | "port": 5858 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible Node.js debug attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceRoot}/app.js", 12 | "cwd": "${workspaceRoot}" 13 | }, 14 | { 15 | "type": "node", 16 | "request": "attach", 17 | "name": "Attach to Process", 18 | "port": 5858 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/res.locals.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('should be empty by default', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/locals') 14 | 15 | sletTest(app) 16 | .get('/') 17 | .expect(200, '', t.end); 18 | }) 19 | 20 | test.cb('should work when mounted', t => { 21 | const app = new Slet({ 22 | root: __dirname, 23 | debug: false 24 | }) 25 | 26 | app.router('fixtures/locals') 27 | 28 | sletTest(app) 29 | .post('/') 30 | .expect(200, '{"foo":"bar"}', t.end); 31 | }) 32 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /packages/slet/test/view/fixtures/base.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../slet-basecontroller') 4 | 5 | const vt = require('nunjucks') 6 | 7 | module.exports = class MyViewController extends BaseController { 8 | // compile (tpl, data) { 9 | // const vt = require('nunjucks') 10 | // let self = this 11 | // 12 | // return new Promise(function(resolve, reject){ 13 | // // render = function(name, ctx, cb) 14 | // vt.render(self.getTplPath(tpl), data, function(err, str){ 15 | // // str => Rendered HTML string 16 | // if (err) { 17 | // console.log(err) 18 | // reject(err) 19 | // } 20 | // 21 | // resolve(str) 22 | // }) 23 | // }) 24 | // } 25 | } 26 | -------------------------------------------------------------------------------- /packages/slet/test/router/params.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../..'); 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }); 10 | 11 | app.router('fixtures/paramctrl') 12 | 13 | test.cb('GET /hello/foo', t => { 14 | sletTest(app) 15 | .get('/hello/foo') 16 | .expect(200, function (err, res) { 17 | t.ifError(err) 18 | t.is(res.text, 'Hello foo!', 'res.text == Hello foo!') 19 | t.end() 20 | }) 21 | }) 22 | 23 | test.cb('GET /hello/bar', t => { 24 | sletTest(app) 25 | .get('/hello/bar') 26 | .expect(200, function (err, res) { 27 | t.ifError(err) 28 | t.is(res.text, 'Hello bar!', 'res.text == Hello bar!') 29 | t.end() 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /packages/slet/test/filter/get_filter.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../..'); 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }); 10 | 11 | app.router('fixtures/get') 12 | 13 | test.cb('GET /c', t => { 14 | sletTest(app) 15 | .get('/c') 16 | .expect(200, function (err, res) { 17 | t.ifError(err) 18 | t.is(res.text, 'some', 'res.text == Hello foo!') 19 | t.end() 20 | }) 21 | }) 22 | // 23 | // test.cb('GET /hello/bar', t => { 24 | // sletTest(app) 25 | // .get('/hello/bar') 26 | // .expect(200, function (err, res) { 27 | // t.ifError(err) 28 | // t.is(res.text, 'Hello bar!', 'res.text == Hello bar!') 29 | // t.end() 30 | // }) 31 | // }) 32 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/params.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../slet') 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }) 10 | 11 | app.router('fixtures/paramctrl') 12 | 13 | test.cb('GET /hello/foo', t => { 14 | sletTest(app) 15 | .get('/hello/foo') 16 | .expect(200, function (err, res) { 17 | t.ifError(err) 18 | t.is(res.text, 'Hello foo!', 'res.text == Hello foo!') 19 | t.end() 20 | }) 21 | }) 22 | 23 | test.cb('GET /hello/bar', t => { 24 | sletTest(app) 25 | .get('/hello/bar') 26 | .expect(200, function (err, res) { 27 | t.ifError(err) 28 | t.is(res.text, 'Hello bar!', 'res.text == Hello bar!') 29 | t.end() 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /packages/slet/test/filter/fixtures/post.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseController = require('../../../../slet-basecontroller') 4 | 5 | // console.log(BasicController) 6 | 7 | class PathController extends BaseController { 8 | constructor(app, ctx, next) { 9 | super(app, ctx, next) 10 | 11 | this.path = '/c' 12 | // this.global_filter.push('custom_filter') 13 | this.post_filter = [this.log] 14 | } 15 | 16 | log(ctx, next){ 17 | ctx.someText = 'some' 18 | // console.log('before') 19 | return next().then(function(){ 20 | // console.log('after') 21 | }) 22 | } 23 | 24 | post(req, res) { 25 | console.log(this.ctx.someText) 26 | var a = this.reqbody.a 27 | 28 | return res.body = this.ctx.someText 29 | } 30 | } 31 | 32 | module.exports = PathController -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/query.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../slet') 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }) 10 | 11 | app.router('fixtures/queryctrl') 12 | 13 | test.cb('GET /query?a=1', t => { 14 | sletTest(app) 15 | .get('/query?a=1') 16 | .expect(200, function (err, res) { 17 | t.ifError(err) 18 | // console.log(res) 19 | t.is(res.text, '1', 'res.text == 1!') 20 | t.end() 21 | }) 22 | }) 23 | 24 | test.cb('GET /query?a=2', t => { 25 | sletTest(app) 26 | .get('/query?a=2') 27 | .expect(200, function (err, res) { 28 | t.ifError(err) 29 | // console.log(res) 30 | t.is(res.text, '2', 'res.text == 1!') 31 | t.end() 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.ip.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | 12 | // var app = express(); 13 | // 14 | // app.enable('trust proxy'); 15 | // 16 | // app.use(function(req, res, next){ 17 | // res.send(req.ip); 18 | // }); 19 | // 20 | // request(app) 21 | // .get('/') 22 | // .set('X-Forwarded-For', 'client, p1, p2') 23 | // .expect('client', done); 24 | 25 | test.cb('should return the Host when present', t => { 26 | app.router('fixtures/ip') 27 | app.proxy = true 28 | 29 | sletTest(app) 30 | .post('/') 31 | .set('X-Forwarded-For', 'client, p1, p2') 32 | .expect('client', t.end); 33 | }) 34 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/fixtures/allctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const BaseController = require('../../') 4 | 5 | module.exports = class MyParamsController extends BaseController { 6 | constructor (app, ctx, next) { 7 | super(app, ctx, next) 8 | 9 | this.path = '/all' 10 | } 11 | 12 | all () { 13 | // matches "GET /base" 14 | // this.end() 15 | // return ssssaaaa 16 | this.ctx.status = 404 17 | 18 | // this.ctx.type = 'text'; 19 | // this.res.statusCode = 200; 20 | this.res.write('ssss') 21 | 22 | this.end('aaaa') 23 | } 24 | 25 | get () { 26 | // matches "GET /base" 27 | // this.end() 28 | // return ssssaaaa 29 | this.ctx.status = 404 30 | 31 | // this.ctx.type = 'text'; 32 | // this.res.statusCode = 200; 33 | this.res.write('ssss') 34 | 35 | this.end('aaaa') 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/body.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../slet') 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }) 10 | 11 | app.router('fixtures/postctrl') 12 | 13 | test.cb('POST /post name=foo', t => { 14 | sletTest(app) 15 | .post('/post', {name: 'foo'}) 16 | .send({name: 'foo'}) 17 | .expect(200, function (err, res) { 18 | t.ifError(err) 19 | // console.log(res) 20 | t.is(res.text, 'Hello foo!', 'res.text == Hello foo!') 21 | t.end() 22 | }) 23 | }) 24 | 25 | test.cb('GET /post name=bar', t => { 26 | sletTest(app) 27 | .post('/post') 28 | .send({name: 'bar'}) 29 | .expect(200, function (err, res) { 30 | t.ifError(err) 31 | t.is(res.text, 'Hello bar!', 'res.text == Hello bar!') 32 | t.end() 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/base.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../slet') 5 | 6 | const app = new Slet({ 7 | root: __dirname, 8 | debug: false 9 | }) 10 | 11 | app.router('fixtures/basectrl') 12 | app.router('fixtures/basectrl2') 13 | 14 | test.cb('GET /base test this.end()', t => { 15 | sletTest(app) 16 | .get('/base') 17 | .expect(404, function (err, res) { 18 | t.ifError(err) 19 | // console.log(res) 20 | t.is(res.text, 'ssssaaaa', 'res.text == ssssaaaa!') 21 | t.end() 22 | }) 23 | }) 24 | 25 | test.cb('GET /base2 test this.end() && this.write()', t => { 26 | sletTest(app) 27 | .get('/base2') 28 | .expect(404, function (err, res) { 29 | t.ifError(err) 30 | // console.log(res) 31 | t.is(res.text, 'ssssaaaa', 'res.text == ssssaaaa!') 32 | t.end() 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/res.json.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('should not support jsonp callbacks', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/json') 14 | 15 | sletTest(app) 16 | .get('/?callback=foo') 17 | .expect('Content-Type', 'application/json; charset=utf-8') 18 | .expect('{"foo":"bar"}', t.end); 19 | }) 20 | 21 | test.cb('should not override previous Content-Types', t => { 22 | const app = new Slet({ 23 | root: __dirname, 24 | debug: false 25 | }) 26 | 27 | app.router('fixtures/json2') 28 | 29 | sletTest(app) 30 | .get('/2') 31 | .expect('Content-Type', 'application/vnd.example+json') 32 | .expect(200, '{"hello":"world"}', t.end); 33 | }) 34 | 35 | -------------------------------------------------------------------------------- /packages/slet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slet", 3 | "version": "1.4.8", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "../../node_modules/.bin/nyc ../../node_modules/.bin/ava -v", 8 | "report-coverage": "../../node_modules/.bin/nyc report --reporter=lcov > coverage.lcov && codecov" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/sletjs/slet.git" 13 | }, 14 | "keywords": [], 15 | "author": "i5ting", 16 | "license": "MIT", 17 | "engines": { 18 | "node": ">= 4" 19 | }, 20 | "bugs": { 21 | "url": "https://github.com/sletjs/slet/issues" 22 | }, 23 | "homepage": "https://github.com/sletjs/slet#readme", 24 | "dependencies": { 25 | "debug": "^2.3.3", 26 | "koa": "next", 27 | "koa-bodyparser": "next", 28 | "koa-compose": "next", 29 | "koa-pino-logger": "^2.1.0", 30 | "koa-router": "next", 31 | "methods": "^1.1.2", 32 | "parsecontroller": "^1.0.1", 33 | "require-dir": "^0.3.1", 34 | "slet-basecontroller": "^1.4.8" 35 | }, 36 | "config": {} 37 | } 38 | -------------------------------------------------------------------------------- /packages/slet/test/controller/fixtures/viewctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseViewController = require('./base') 4 | 5 | module.exports = class MyViewController extends BaseViewController { 6 | 7 | get() { 8 | var a = this.query.a 9 | 10 | // if 11 | // this.renderType = 'view' 12 | 13 | // return { 14 | // tpl: 'index', 15 | // data: { 16 | // title: 'ssddssdd a= '+a 17 | // } 18 | // } 19 | 20 | // if this.render, make this.renderType = 'view' 21 | // use default 22 | // this.tpl = 'index' 23 | // this.data = { 24 | // title: 'ssddssdd a= '+a 25 | // } 26 | // return this.render() 27 | // use tpl 28 | // this.data = {} 29 | // return this.render('tpl') 30 | // use tpl && data 31 | // return this.render('tpl', { 32 | // a:1 33 | // }) 34 | // this.data = { 35 | // title: 'ssddssdd a= '+a 36 | // } 37 | // return this.render('index') 38 | this.tpl = 'index' 39 | this.data = { 40 | title: 'ssddssdd a= '+a 41 | } 42 | return this.render() 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 狼叔 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/res.clearCookie.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | test.cb('should set a cookie passed expiry', t => { 8 | const app = new Slet({ 9 | root: __dirname, 10 | debug: false 11 | }) 12 | 13 | app.router('fixtures/clearCookie') 14 | 15 | sletTest(app) 16 | .get('/') 17 | .end(function(err, res){ 18 | var val = 'sid=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; httponly'; 19 | t.regex(res.header['set-cookie'].join(""), /^sid=; path=\/;/) 20 | t.end(); 21 | }) 22 | }) 23 | 24 | test.cb('should set the given params', t => { 25 | const app = new Slet({ 26 | root: __dirname, 27 | debug: false 28 | }) 29 | 30 | app.router('fixtures/clearCookie2') 31 | 32 | sletTest(app) 33 | .get('/2') 34 | .end(function(err, res){ 35 | var val = 'sid=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; httponly'; 36 | t.regex(res.header['set-cookie'].join(""), /^sid=; path=\/admin;/) 37 | t.end(); 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Slet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/README.md: -------------------------------------------------------------------------------- 1 | # BaseController 2 | 3 | [![NPM version](https://img.shields.io/npm/v/slet-basecontroller.svg?style=flat-square)](https://www.npmjs.com/package/slet-basecontroller) 4 | [![Build](https://travis-ci.org/sletjs/BaseController.svg?branch=master)](https://travis-ci.org/sletjs/BaseController) 5 | [![codecov.io](https://codecov.io/github/sletjs/BaseController/coverage.svg?branch=master)](https://codecov.io/github/sletjs/BaseController?branch=master) 6 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) 7 | 8 | 9 | - 支持express和koa的res和req api 10 | - 集成基础模块,保证类似于express的基础功能 11 | 12 | ## api 13 | 14 | - [express req 已经整理完成](http://sletjs.com/zh-cn/api/request.html) 15 | - [express res 已经整理完成](http://sletjs.com/zh-cn/api/response.html) 16 | 17 | ## 依赖 18 | 19 | - "content-disposition": "^0.5.2", 20 | - "debug": "^2.4.5", 21 | - "encodeurl": "^1.0.1", 22 | - "koa-compress": "^2.0.0", 23 | - "koa-conditional-get": "^2.0.0", 24 | - "koa-etag": "^3.0.0", 25 | - "koa-favicon": "^2.0.0", 26 | - "mime": "^1.3.4", 27 | - "qs": "^6.3.0", 28 | - "range-parser": "^1.2.0", 29 | - "slet-send": "^3.2.0", 30 | - "utils-merge": "^1.0.0", 31 | - "vary": "^1.1.0" -------------------------------------------------------------------------------- /packages/slet-basecontroller/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slet-basecontroller", 3 | "version": "1.4.8", 4 | "description": "basecontroller", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "../../node_modules/.bin/nyc ../../node_modules/.bin/ava -v", 8 | "report-coverage": "../../node_modules/.bin/nyc report --reporter=lcov > coverage.lcov && codecov" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/sletjs/BaseController.git" 13 | }, 14 | "keywords": [ 15 | "slet", 16 | "servlet" 17 | ], 18 | "author": "i5ting", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/sletjs/BaseController/issues" 22 | }, 23 | "homepage": "https://github.com/sletjs/BaseController#readme", 24 | "config": {}, 25 | "dependencies": { 26 | "consolidate": "^0.14.5", 27 | "content-disposition": "^0.5.2", 28 | "debug": "^2.4.5", 29 | "encodeurl": "^1.0.1", 30 | "koa-compress": "^2.0.0", 31 | "koa-conditional-get": "^2.0.0", 32 | "koa-etag": "^3.0.0", 33 | "koa-favicon": "^2.0.0", 34 | "mime": "^1.3.4", 35 | "qs": "^6.3.0", 36 | "range-parser": "^1.2.0", 37 | "slet-send": "^3.2.0", 38 | "utils-merge": "^1.0.0", 39 | "vary": "^1.1.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/slet/test/controller/view.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | const axios = require('axios') 4 | const Slet = require('../..'); 5 | const app = new Slet({ 6 | root: __dirname + '/fixtures', 7 | debug: false, 8 | views:{ 9 | engine: "nunjucks", 10 | path: '', 11 | extension: 'html' 12 | } 13 | }); 14 | 15 | app.start(5001) 16 | // support file path or Controller 17 | app.router('/r', require('./fixtures/viewctrl')) 18 | 19 | test.cb('GET /r?a=1 return view', t => { 20 | axios.get('http://127.0.0.1:5001/r?a=1') 21 | .then(function (response) { 22 | // console.log(response); 23 | t.true(response.status === 200) 24 | t.is(response.data, '

ssddssdd a= 1

') 25 | t.pass(); 26 | t.end() 27 | }) 28 | .catch(function (error) { 29 | console.log(error); 30 | t.fail(); 31 | t.end() 32 | }); 33 | }) 34 | 35 | test.cb('GET /r?a=2 return view', t => { 36 | axios.get('http://127.0.0.1:5001/r?a=2') 37 | .then(function (response) { 38 | // console.log(response); 39 | t.true(response.status === 200) 40 | t.is(response.data, '

ssddssdd a= 2

') 41 | t.pass(); 42 | t.end() 43 | }) 44 | .catch(function (error) { 45 | console.log(error); 46 | t.fail(); 47 | t.end() 48 | }); 49 | }) -------------------------------------------------------------------------------- /packages/slet/test/controller/base.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | const axios = require('axios') 4 | const Slet = require('../..'); 5 | const app = new Slet({ 6 | root: __dirname, 7 | debug: false, 8 | views:{ 9 | engine: "nunjucks", 10 | path: 'fixtures', 11 | extension: 'html' 12 | } 13 | }); 14 | 15 | app.start(5000) 16 | // support file path or Controller 17 | app.router('/r', require('./fixtures/ctrl')) 18 | 19 | test.cb('GET /r?a=1 return json', t => { 20 | axios.get('http://127.0.0.1:5000/r?a=1') 21 | .then(function (response) { 22 | // console.log(response); 23 | t.true(response.status === 200) 24 | t.is(response.data.a, 1) 25 | t.is(parseInt(response.data.b), 1) 26 | t.pass(); 27 | t.end() 28 | }) 29 | .catch(function (error) { 30 | console.log(error); 31 | t.fail(); 32 | t.end() 33 | }); 34 | }) 35 | 36 | test.cb('POST /r?a=1 return json', t => { 37 | axios.post('http://127.0.0.1:5000/r', {a:1}) 38 | .then(function (response) { 39 | // console.log(response); 40 | t.true(response.status === 200) 41 | t.is(response.data.a, 1) 42 | // t.is(parseInt(response.data.b), 1) 43 | t.pass(); 44 | t.end() 45 | }) 46 | .catch(function (error) { 47 | console.log(error); 48 | t.fail(); 49 | t.end() 50 | }); 51 | }) 52 | -------------------------------------------------------------------------------- /packages/slet/test/router/2-path.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | // ### 第二种,将path写到controller里 4 | 5 | // ``` 6 | // app.router(require('./pathctrl') ) 7 | // ``` 8 | 9 | // or 10 | 11 | // ``` 12 | // app.router('./pathctrl') 13 | // ``` 14 | 15 | const axios = require('axios') 16 | const Slet = require('../..'); 17 | const app = new Slet({ 18 | root: __dirname, 19 | debug: false 20 | }); 21 | 22 | app.start(4003) 23 | // support file path or Controller 24 | app.router('./fixtures/pathctrl') 25 | 26 | test.cb('GET http://127.0.0.1:4003/path/a?a=1', t => { 27 | axios.get('http://127.0.0.1:4003/path/a?a=1') 28 | .then(function (response) { 29 | // console.log(response); 30 | t.true(response.status === 200) 31 | t.is(response.data.a, 1) 32 | t.is(parseInt(response.data.b), 1) 33 | t.pass(); 34 | t.end() 35 | }) 36 | .catch(function (error) { 37 | console.log(error); 38 | t.fail(); 39 | t.end() 40 | }); 41 | }) 42 | 43 | 44 | test.cb('GET http://127.0.0.1:4003/path/a?a=2', t => { 45 | axios.get('http://127.0.0.1:4003/path/a?a=2') 46 | .then(function (response) { 47 | // console.log(response.data); 48 | t.true(response.status === 200) 49 | t.is(response.data.a, 1) 50 | t.is(parseInt(response.data.b), 2) 51 | t.pass(); 52 | t.end() 53 | }) 54 | .catch(function (error) { 55 | console.log(error); 56 | t.fail(); 57 | t.end() 58 | }); 59 | }) 60 | -------------------------------------------------------------------------------- /packages/slet/test/router/1-path.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | // ### 第一种,暴露path和controller 4 | // (controller内部不需要path) 5 | 6 | // ``` 7 | // app.router('/', require('./ctrl') ) 8 | // ``` 9 | 10 | // or 11 | 12 | // ``` 13 | // app.router('/', './ctrl') 14 | // ``` 15 | const axios = require('axios') 16 | const Slet = require('../..'); 17 | const app = new Slet({ 18 | root: __dirname, 19 | debug: false 20 | }) 21 | 22 | app.start(4000) 23 | 24 | // support file path or Controller 25 | app.router('/', './fixtures/ctrl' ) 26 | 27 | test.cb('GET http://127.0.0.1:4000/?a=1', t => { 28 | axios.get('http://127.0.0.1:4000/?a=1') 29 | .then(function (response) { 30 | // console.log(response); 31 | t.true(response.status === 200) 32 | t.is(response.data.a, 1) 33 | t.is(parseInt(response.data.b), 1) 34 | t.pass(); 35 | t.end() 36 | }) 37 | .catch(function (error) { 38 | console.log(error); 39 | t.fail(); 40 | t.end() 41 | }); 42 | }) 43 | 44 | 45 | test.cb('GET http://127.0.0.1:4000/?a=2', t => { 46 | axios.get('http://127.0.0.1:4000/?a=2') 47 | .then(function (response) { 48 | // console.log(response.data); 49 | t.true(response.status === 200) 50 | t.is(response.data.a, 1) 51 | t.is(parseInt(response.data.b), 2) 52 | t.pass(); 53 | t.end() 54 | }) 55 | .catch(function (error) { 56 | console.log(error); 57 | t.fail(); 58 | t.end() 59 | }); 60 | }) 61 | -------------------------------------------------------------------------------- /packages/slet/test/router/2-controller.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | // ### 第二种,将path写到controller里 4 | 5 | // ``` 6 | // app.router(require('./pathctrl') ) 7 | // ``` 8 | 9 | // or 10 | 11 | // ``` 12 | // app.router('./pathctrl') 13 | // ``` 14 | 15 | const axios = require('axios') 16 | const Slet = require('../..'); 17 | const app = new Slet({ 18 | root: __dirname, 19 | debug: false 20 | }) 21 | 22 | app.start(4002) 23 | // support file path or Controller 24 | app.router(require('./fixtures/pathctrl') ) 25 | 26 | test.cb('GET http://127.0.0.1:4002/path/a?a=1', t => { 27 | axios.get('http://127.0.0.1:4002/path/a?a=1') 28 | .then(function (response) { 29 | // console.log(response); 30 | t.true(response.status === 200) 31 | t.is(response.data.a, 1) 32 | t.is(parseInt(response.data.b), 1) 33 | t.pass(); 34 | t.end() 35 | }) 36 | .catch(function (error) { 37 | console.log(error); 38 | t.fail(); 39 | t.end() 40 | }); 41 | }) 42 | 43 | 44 | test.cb('GET http://127.0.0.1:4002/path/a?a=2', t => { 45 | axios.get('http://127.0.0.1:4002/path/a?a=2') 46 | .then(function (response) { 47 | // console.log(response.data); 48 | t.true(response.status === 200) 49 | t.is(response.data.a, 1) 50 | t.is(parseInt(response.data.b), 2) 51 | t.pass(); 52 | t.end() 53 | }) 54 | .catch(function (error) { 55 | console.log(error); 56 | t.fail(); 57 | t.end() 58 | }); 59 | }) 60 | -------------------------------------------------------------------------------- /packages/slet/test/router/1-controller.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | // ### 第一种,暴露path和controller 4 | // (controller内部不需要path) 5 | 6 | // ``` 7 | // app.router('/', require('./ctrl') ) 8 | // ``` 9 | 10 | // or 11 | 12 | // ``` 13 | // app.router('/', './ctrl') 14 | // ``` 15 | const axios = require('axios') 16 | const Slet = require('../..'); 17 | const app = new Slet({ 18 | root: __dirname, 19 | debug: false 20 | }) 21 | 22 | app.start(4001) 23 | 24 | // support file path or Controller 25 | app.router('/r', require('./fixtures/ctrl')) 26 | 27 | test.cb('GET http://127.0.0.1:4001/r?a=1', t => { 28 | axios.get('http://127.0.0.1:4001/r?a=1') 29 | .then(function (response) { 30 | // console.log(response); 31 | t.true(response.status === 200) 32 | t.is(response.data.a, 1) 33 | t.is(parseInt(response.data.b), 1) 34 | t.pass(); 35 | t.end() 36 | }) 37 | .catch(function (error) { 38 | console.log(error); 39 | t.fail(); 40 | t.end() 41 | }); 42 | }) 43 | 44 | test.cb('GET http://127.0.0.1:4001/r?a=2', t => { 45 | axios.get('http://127.0.0.1:4001/r?a=2') 46 | .then(function (response) { 47 | // console.log(response.data); 48 | t.true(response.status === 200) 49 | t.is(response.data.a, 1) 50 | t.is(parseInt(response.data.b), 2) 51 | t.pass(); 52 | t.end() 53 | }) 54 | .catch(function (error) { 55 | console.log(error); 56 | t.fail(); 57 | t.end() 58 | }); 59 | }) 60 | -------------------------------------------------------------------------------- /examples/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Slet = require('./'); 4 | const app = new Slet({ 5 | root: __dirname, 6 | debug: true, 7 | auto:true, 8 | "views" :{ 9 | "path" : __dirname, 10 | "option": { "map": {"html": "nunjucks" }} 11 | } 12 | }); 13 | 14 | // const views = require('koa-views'); 15 | // 16 | // var _views = views(__dirname,{ "map": {"html": "nunjucks" }}) 17 | // // app.defineMiddleware('koa-views', _views) 18 | // 19 | // app.use(_views) 20 | // 21 | // app.defineController(require('slet-viewcontroller')) 22 | // app.router('/2', require('./viewctrl') ) 23 | 24 | // app.use(function (ctx, next) { 25 | // return ctx.render('index', { 26 | // title : "1" 27 | // }) 28 | // }) 29 | 30 | // app.defineMiddleware('custom_filter', function(ctx, next){ 31 | // console.log('a before') 32 | // return next().then(function(){ 33 | // console.log('a after') 34 | // }) 35 | // }) 36 | 37 | // // support file path or Controller 38 | // app.router('/', './ctrl' ) 39 | 40 | app.router('/', ('./viewctrl') ) 41 | 42 | // app.router('/2', ('./viewctrl') ) 43 | app.asyncRouter(function(){ 44 | app.router('/2', require('./viewctrl') ) 45 | }) 46 | 47 | // app.router(require('./pathctrl') ) 48 | 49 | // app.router('./pathctrl') 50 | 51 | // app.routerDir('test/controller/fixtures') 52 | app.routerDir('test/router/fixtures') 53 | 54 | 55 | // app.router('/d', './controller/a') 56 | 57 | 58 | 59 | app.start(3000) 60 | 61 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.query.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | 8 | 9 | // describe('.query', function(){ 10 | // it('should default to {}', function(done){ 11 | // var app = createApp(); 12 | // 13 | // request(app) 14 | // .get('/') 15 | // .expect(200, '{}', done); 16 | // }); 17 | 18 | test.cb('.query should default to {}', t => { 19 | const app = new Slet({ 20 | root: __dirname, 21 | debug: false 22 | }) 23 | 24 | app.router('fixtures/query') 25 | 26 | sletTest(app) 27 | .get('/') 28 | .expect(200, '{}', t.end); 29 | }) 30 | 31 | // it('should default to parse complex keys', function (done) { 32 | // var app = createApp(); 33 | // 34 | // request(app) 35 | // .get('/?user[name]=tj') 36 | // .expect(200, '{"user":{"name":"tj"}}', done); 37 | // }); 38 | 39 | 40 | test.cb('.query should default to parse keys', t => { 41 | const app = new Slet({ 42 | root: __dirname, 43 | debug: false 44 | }) 45 | 46 | app.router('fixtures/query') 47 | 48 | sletTest(app) 49 | .get('/?user[name]=tj') 50 | .expect(200, '{"user[name]":"tj"}', t.end); 51 | }) 52 | 53 | 54 | test.cb('.qs should default to parse complex keys', t => { 55 | const app = new Slet({ 56 | root: __dirname, 57 | debug: false 58 | }) 59 | 60 | app.router('fixtures/query2') 61 | 62 | sletTest(app) 63 | .get('/2?user[name]=tj') 64 | .expect(200, '{"user":{"name":"tj"}}', t.end); 65 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slet", 3 | "version": "1.0.11", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "async": "node --harmony-async-await app.async.js", 8 | "t": "lerna run test", 9 | "test": "lerna bootstrap && lerna run test", 10 | "p": "yrm use npm && lerna publish --skip-git && yrm use cnpm", 11 | "report-coverage": "/node_modules/.bin/nyc report --reporter=lcov > coverage.lcov && codecov", 12 | "standard": "./node_modules/.bin/standard packages/slet/src/Slet.js --fix" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/sletjs/slet.git" 17 | }, 18 | "keywords": [], 19 | "author": "i5ting", 20 | "license": "MIT", 21 | "engines": { 22 | "node": ">= 7" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/sletjs/slet/issues" 26 | }, 27 | "homepage": "https://github.com/sletjs/slet#readme", 28 | "dependencies": { 29 | "debug": "^3.0.0", 30 | "koa": "next", 31 | "koa-bodyparser": "next", 32 | "koa-compose": "next", 33 | "koa-router": "next", 34 | "methods": "^1.1.2", 35 | "parsecontroller": "^1.0.1", 36 | "require-dir": "^0.3.1", 37 | "slet-basecontroller": "^1.3.0", 38 | "v7": "^1.0.1" 39 | }, 40 | "devDependencies": { 41 | "ava": "^0.17.0", 42 | "axios": "^0.16.0", 43 | "codecov": "^1.0.1", 44 | "ghooks": "^1.3.2", 45 | "lerna": "2.0.0-beta.31", 46 | "nunjucks": "^3.0.0", 47 | "nyc": "^11.0.2", 48 | "slettest": "^1.0.4", 49 | "standard": "^9.0.2" 50 | }, 51 | "config": { 52 | "ghooks": { 53 | 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.acceptsEncoding.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | 12 | // it('should be true if encoding accpeted', function(done){ 13 | // var app = express(); 14 | 15 | // app.use(function(req, res){ 16 | // req.acceptsEncoding('gzip').should.be.ok; 17 | // req.acceptsEncoding('deflate').should.be.ok; 18 | // res.end(); 19 | // }); 20 | 21 | // request(app) 22 | // .get('/') 23 | // .set('Accept-Encoding', ' gzip, deflate') 24 | // .expect(200, done); 25 | // }) 26 | 27 | test.cb('should be true if encoding accpeted', t => { 28 | app.router('fixtures/req.acceptsEncoding') 29 | 30 | sletTest(app) 31 | .get('/') 32 | .set('Accept-Encoding', ' gzip, deflate') 33 | .expect('200', t.end); 34 | }) 35 | 36 | 37 | // it('should be false if encoding not accpeted', function(done){ 38 | // var app = express(); 39 | 40 | // app.use(function(req, res){ 41 | // req.acceptsEncoding('bogus').should.not.be.ok; 42 | // res.end(); 43 | // }); 44 | 45 | // request(app) 46 | // .get('/') 47 | // .set('Accept-Encoding', ' gzip, deflate') 48 | // .expect(200, done); 49 | // }) 50 | test.cb('should be false if encoding not accpeted', t => { 51 | app.router('fixtures/req.acceptsEncoding2') 52 | 53 | sletTest(app) 54 | .get('/') 55 | .set('Accept-Encoding', ' gzip, deflate') 56 | .expect('200', t.end); 57 | }) -------------------------------------------------------------------------------- /examples/allctrl.js: -------------------------------------------------------------------------------- 1 | // 'use strict' 2 | // 3 | const BasicController = require('../').BasicController 4 | // 5 | // module.exports = class MyParamsController extends BasicController { 6 | // constructor (app, ctx, next) { 7 | // super(app, ctx, next) 8 | // 9 | // this.path = '/all' 10 | // } 11 | // 12 | // all () { 13 | // // matches "GET /base" 14 | // // this.end() 15 | // // return ssssaaaa 16 | // console.log(this.body) 17 | // this.ctx.status = 404 18 | // 19 | // // this.ctx.type = 'text'; 20 | // // this.res.statusCode = 200; 21 | // this.res.write('ssss') 22 | // 23 | // this.end('aaaa') 24 | // } 25 | // 26 | // get () { 27 | // // matches "GET /base" 28 | // // this.end() 29 | // // return ssssaaaa 30 | // this.ctx.status = 404 31 | // 32 | // // this.ctx.type = 'text'; 33 | // // this.res.statusCode = 200; 34 | // this.res.write('ssss') 35 | // 36 | // this.end('aaaa') 37 | // } 38 | // 39 | // } 40 | 41 | 42 | class PathController extends BasicController { 43 | constructor(app, ctx, next) { 44 | super(app, ctx, next) 45 | 46 | this.path = '/c' 47 | // this.global_filter.push('custom_filter') 48 | this.post_filter = [this.log] 49 | } 50 | 51 | log(ctx, next){ 52 | console.log('before') 53 | return next().then(function(){ 54 | console.log('after') 55 | }) 56 | } 57 | 58 | post() { 59 | console.log(this) 60 | var a = this.body.a 61 | console.log(a) 62 | setTimeout(function(){ 63 | process.exit(0) 64 | }, 100) 65 | 66 | return { 67 | dddd:1 68 | } 69 | } 70 | } 71 | 72 | module.exports = PathController -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.acceptsEncoding2.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | 12 | // it('should be true if encoding accpeted', function(done){ 13 | // var app = express(); 14 | 15 | // app.use(function(req, res){ 16 | // req.acceptsEncoding('gzip').should.be.ok; 17 | // req.acceptsEncoding('deflate').should.be.ok; 18 | // res.end(); 19 | // }); 20 | 21 | // request(app) 22 | // .get('/') 23 | // .set('Accept-Encoding', ' gzip, deflate') 24 | // .expect(200, done); 25 | // }) 26 | 27 | test.cb('should be true if encoding accpeted', t => { 28 | app.router('fixtures/req.acceptsEncodings') 29 | 30 | sletTest(app) 31 | .get('/') 32 | .set('Accept-Encoding', ' gzip, deflate') 33 | .expect('200', t.end); 34 | }) 35 | 36 | 37 | // it('should be false if encoding not accpeted', function(done){ 38 | // var app = express(); 39 | 40 | // app.use(function(req, res){ 41 | // req.acceptsEncoding('bogus').should.not.be.ok; 42 | // res.end(); 43 | // }); 44 | 45 | // request(app) 46 | // .get('/') 47 | // .set('Accept-Encoding', ' gzip, deflate') 48 | // .expect(200, done); 49 | // }) 50 | test.cb('should be false if encoding not accpeted', t => { 51 | app.router('fixtures/req.acceptsEncodings2') 52 | 53 | sletTest(app) 54 | .get('/') 55 | .set('Accept-Encoding', ' gzip, deflate') 56 | .expect('200', t.end); 57 | }) -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.get.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | 12 | // it('should return the header field value', function(done){ 13 | // var app = express(); 14 | // 15 | // app.use(function(req, res){ 16 | // assert(req.get('Something-Else') === undefined); 17 | // res.end(req.get('Content-Type')); 18 | // }); 19 | // 20 | // request(app) 21 | // .post('/') 22 | // .set('Content-Type', 'application/json') 23 | // .expect('application/json', done); 24 | // }) 25 | test.cb('should return the header field value', t => { 26 | app.router('fixtures/reqget') 27 | 28 | sletTest(app) 29 | .post('/') 30 | .set('Content-Type', 'application/json') 31 | .expect('application/json', t.end); 32 | }) 33 | 34 | 35 | // it('should special-case Referer', function(done){ 36 | // var app = express(); 37 | // 38 | // app.use(function(req, res){ 39 | // res.end(req.get('Referer')); 40 | // }); 41 | // 42 | // request(app) 43 | // .post('/') 44 | // .set('Referrer', 'http://foobar.com') 45 | // .expect('http://foobar.com', done); 46 | // }) 47 | 48 | test.cb('should special-case Referer', t => { 49 | app.router('fixtures/reqget1') 50 | 51 | sletTest(app) 52 | .post('/refer') 53 | .set('Referrer', 'http://foobar.com') 54 | .expect('http://foobar.com', t.end); 55 | }) 56 | 57 | 58 | // it('should throw missing header name', function (done) { 59 | // var app = express() 60 | // 61 | // app.use(function (req, res) { 62 | // res.end(req.get()) 63 | // }) 64 | // 65 | // request(app) 66 | // .get('/') 67 | // .expect(500, /TypeError: name argument is required to req.get/, done) 68 | // }) 69 | 70 | // test.cb('should throw missing header name', t => { 71 | // app.router('fixtures/reqget2') 72 | // 73 | // sletTest(app) 74 | // .post('/2') 75 | // .expect(500, /TypeError: name argument is required to req.get/, t.end); 76 | // }) 77 | 78 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.fresh.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | 12 | // it('should return true when the resource is not modified', function(done){ 13 | // var app = express(); 14 | // var etag = '"12345"'; 15 | 16 | // app.use(function(req, res){ 17 | // res.set('ETag', etag); 18 | // res.send(req.fresh); 19 | // }); 20 | 21 | // request(app) 22 | // .get('/') 23 | // .set('If-None-Match', etag) 24 | // .expect(304, done); 25 | // }) 26 | test.cb('should return true when the resource is not modified', t => { 27 | app.router('fixtures/reqfresh') 28 | 29 | let etag = '"12345"'; 30 | 31 | sletTest(app) 32 | .get('/') 33 | .set('If-None-Match', etag) 34 | .expect(304, t.end); 35 | }) 36 | 37 | // it('should return false when the resource is modified', function(done){ 38 | // var app = express(); 39 | 40 | // app.use(function(req, res){ 41 | // res.set('ETag', '"123"'); 42 | // res.send(req.fresh); 43 | // }); 44 | 45 | // request(app) 46 | // .get('/') 47 | // .set('If-None-Match', '"12345"') 48 | // .expect(200, 'false', done); 49 | // }) 50 | 51 | test.cb('should return false when the resource is modified', t => { 52 | app.router('fixtures/reqfresh2') 53 | 54 | sletTest(app) 55 | .get('/2') 56 | .set('If-None-Match', '"12345"') 57 | .expect(200, 'false', t.end) 58 | }) 59 | 60 | // it('should return false without response headers', function(done){ 61 | // var app = express(); 62 | 63 | // app.use(function(req, res){ 64 | // res._headers = null; 65 | // res.send(req.fresh); 66 | // }); 67 | 68 | // request(app) 69 | // .get('/') 70 | // .expect(200, 'false', done); 71 | // }) 72 | 73 | test.cb('should return false without response headers', t => { 74 | app.router('fixtures/reqfresh3') 75 | 76 | sletTest(app) 77 | .get('/3') 78 | .expect(200, 'false', t.end) 79 | }) 80 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.acceptsCharset.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | 12 | // it('should return true', function(done){ 13 | // var app = express(); 14 | 15 | // app.use(function(req, res, next){ 16 | // res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); 17 | // }); 18 | 19 | // request(app) 20 | // .get('/') 21 | // .expect('yes', done); 22 | // }) 23 | 24 | test.cb('when Accept-Charset is not present should return true when Accept is not present', t => { 25 | app.router('fixtures/req.acceptsCharset') 26 | 27 | sletTest(app) 28 | .get('/') 29 | .expect('yes', t.end); 30 | }) 31 | 32 | 33 | // describe('when Accept-Charset is not present', function(){ 34 | // it('should return true when present', function(done){ 35 | // var app = express(); 36 | 37 | // app.use(function(req, res, next){ 38 | // res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); 39 | // }); 40 | 41 | // request(app) 42 | // .get('/') 43 | // .set('Accept-Charset', 'foo, bar, utf-8') 44 | // .expect('yes', done); 45 | // }) 46 | 47 | test.cb('when Accept-Charset is not present should return true when present', t => { 48 | app.router('fixtures/req.acceptsCharset') 49 | 50 | sletTest(app) 51 | .get('/') 52 | .set('Accept-Charset', 'foo, bar, utf-8') 53 | .expect('yes', t.end); 54 | }) 55 | 56 | // it('should return false otherwise', function(done){ 57 | // var app = express(); 58 | 59 | // app.use(function(req, res, next){ 60 | // res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); 61 | // }); 62 | 63 | // request(app) 64 | // .get('/') 65 | // .set('Accept-Charset', 'foo, bar') 66 | // .expect('no', done); 67 | // }) 68 | // }) 69 | 70 | test.cb('when Accept-Charset is not present should return false otherwise', t => { 71 | app.router('fixtures/req.acceptsCharset') 72 | 73 | sletTest(app) 74 | .get('/') 75 | .set('Accept-Charset', 'foo, bar') 76 | .expect('no', t.end); 77 | }) -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.acceptsCharsets.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | 12 | // it('should return true', function(done){ 13 | // var app = express(); 14 | 15 | // app.use(function(req, res, next){ 16 | // res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); 17 | // }); 18 | 19 | // request(app) 20 | // .get('/') 21 | // .expect('yes', done); 22 | // }) 23 | 24 | test.cb('when Accept-Charset is not present should return true when Accept is not present', t => { 25 | app.router('fixtures/req.acceptsCharset') 26 | 27 | sletTest(app) 28 | .get('/') 29 | .expect('yes', t.end); 30 | }) 31 | 32 | 33 | // describe('when Accept-Charset is not present', function(){ 34 | // it('should return true when present', function(done){ 35 | // var app = express(); 36 | 37 | // app.use(function(req, res, next){ 38 | // res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); 39 | // }); 40 | 41 | // request(app) 42 | // .get('/') 43 | // .set('Accept-Charset', 'foo, bar, utf-8') 44 | // .expect('yes', done); 45 | // }) 46 | 47 | test.cb('when Accept-Charset is not present should return true when present', t => { 48 | app.router('fixtures/req.acceptsCharset') 49 | 50 | sletTest(app) 51 | .get('/') 52 | .set('Accept-Charset', 'foo, bar, utf-8') 53 | .expect('yes', t.end); 54 | }) 55 | 56 | // it('should return false otherwise', function(done){ 57 | // var app = express(); 58 | 59 | // app.use(function(req, res, next){ 60 | // res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); 61 | // }); 62 | 63 | // request(app) 64 | // .get('/') 65 | // .set('Accept-Charset', 'foo, bar') 66 | // .expect('no', done); 67 | // }) 68 | // }) 69 | 70 | test.cb('when Accept-Charset is not present should return false otherwise', t => { 71 | app.router('fixtures/req.acceptsCharset') 72 | 73 | sletTest(app) 74 | .get('/') 75 | .set('Accept-Charset', 'foo, bar') 76 | .expect('no', t.end); 77 | }) -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.ips.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | 8 | 9 | // it('should return an array of the specified addresses', function(done){ 10 | // var app = express(); 11 | // 12 | // app.enable('trust proxy'); 13 | // 14 | // app.use(function(req, res, next){ 15 | // res.send(req.ips); 16 | // }); 17 | // 18 | // request(app) 19 | // .get('/') 20 | // .set('X-Forwarded-For', 'client, p1, p2') 21 | // .expect('["client","p1","p2"]', done); 22 | // }) 23 | 24 | test.cb('should return an array of the specified addresses', t => { 25 | const app = new Slet({ 26 | root: __dirname, 27 | debug: false 28 | }) 29 | 30 | app.router('fixtures/ips') 31 | app.proxy = true 32 | 33 | sletTest(app) 34 | .post('/') 35 | .set('X-Forwarded-For', 'client, p1, p2') 36 | .expect('["client","p1","p2"]', t.end); 37 | }) 38 | 39 | // it('should return an empty array', function(done){ 40 | // var app = express(); 41 | // 42 | // app.use(function(req, res, next){ 43 | // res.send(req.ips); 44 | // }); 45 | // 46 | // request(app) 47 | // .get('/') 48 | // .set('X-Forwarded-For', 'client, p1, p2') 49 | // .expect('[]', done); 50 | // }) 51 | // }) 52 | 53 | test.cb('should return an empty array', t => { 54 | const app = new Slet({ 55 | root: __dirname, 56 | debug: false 57 | }) 58 | 59 | app.router('fixtures/ips') 60 | app.proxy = false 61 | 62 | sletTest(app) 63 | .post('/') 64 | .set('X-Forwarded-For', 'client, p1, p2') 65 | .expect('[]', t.end); 66 | }) 67 | 68 | 69 | // 70 | // describe('when X-Forwarded-For is not present', function(){ 71 | // it('should return []', function(done){ 72 | // var app = express(); 73 | // 74 | // app.use(function(req, res, next){ 75 | // res.send(req.ips); 76 | // }); 77 | // 78 | // request(app) 79 | // .get('/') 80 | // .expect('[]', done); 81 | // }) 82 | // }) 83 | // 84 | 85 | test.cb('when X-Forwarded-For is not present should return []', t => { 86 | const app = new Slet({ 87 | root: __dirname, 88 | debug: false 89 | }) 90 | 91 | app.router('fixtures/ips') 92 | app.proxy = false 93 | 94 | sletTest(app) 95 | .post('/') 96 | .expect('[]', t.end); 97 | }) 98 | -------------------------------------------------------------------------------- /packages/slet/test/view/view.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | // ### 第一种,暴露path和controller 4 | // (controller内部不需要path) 5 | 6 | // ``` 7 | // app.router('/', require('./ctrl') ) 8 | // ``` 9 | 10 | // or 11 | 12 | // ``` 13 | // app.router('/', './ctrl') 14 | // ``` 15 | const axios = require('axios') 16 | const Slet = require('../..') 17 | const app = new Slet({ 18 | root: __dirname + '/fixtures', 19 | debug: false, 20 | views:{ 21 | engine: "nunjucks", 22 | path: '', 23 | extension: 'html' 24 | } 25 | }) 26 | 27 | app.start(7001) 28 | // support file path or Controller 29 | app.router('/0', require('./fixtures/v0')) 30 | app.router('/1', require('./fixtures/v1')) 31 | app.router('/2', require('./fixtures/v2')) 32 | app.router('/3', require('./fixtures/v3')) 33 | 34 | test.cb('GET /0?a=1 return view', t => { 35 | axios.get('http://127.0.0.1:7001/0?a=1') 36 | .then(function (response) { 37 | // console.log(response) 38 | t.true(response.status === 200) 39 | t.is(response.data, '

ssddssdd a= 1

') 40 | t.pass() 41 | t.end() 42 | }) 43 | .catch(function (error) { 44 | console.log(error) 45 | t.fail() 46 | t.end() 47 | }) 48 | }) 49 | 50 | test.cb('GET /1?a=1 return view', t => { 51 | axios.get('http://127.0.0.1:7001/1?a=1') 52 | .then(function (response) { 53 | // console.log(response) 54 | t.true(response.status === 200) 55 | t.is(response.data, '

ssddssdd a= 1

') 56 | t.pass() 57 | t.end() 58 | }) 59 | .catch(function (error) { 60 | console.log(error) 61 | t.fail() 62 | t.end() 63 | }) 64 | }) 65 | 66 | test.cb('GET /2?a=1 return view', t => { 67 | axios.get('http://127.0.0.1:7001/2?a=1') 68 | .then(function (response) { 69 | // console.log(response) 70 | t.true(response.status === 200) 71 | t.is(response.data, '

ssddssdd a= 1

') 72 | t.pass() 73 | t.end() 74 | }) 75 | .catch(function (error) { 76 | console.log(error) 77 | t.fail() 78 | t.end() 79 | }) 80 | }) 81 | 82 | test.cb('GET /3?a=1 return view', t => { 83 | axios.get('http://127.0.0.1:7001/3?a=1') 84 | .then(function (response) { 85 | // console.log(response) 86 | t.true(response.status === 200) 87 | t.is(response.data, '

ssddssdd a= 1

') 88 | t.pass() 89 | t.end() 90 | }) 91 | .catch(function (error) { 92 | console.log(error) 93 | t.fail() 94 | t.end() 95 | }) 96 | }) 97 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.hostname.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | // it('should return the Host when present', function(done){ 12 | // var app = express(); 13 | 14 | // app.use(function(req, res){ 15 | // res.end(req.host); 16 | // }); 17 | 18 | // request(app) 19 | // .post('/') 20 | // .set('Host', 'example.com') 21 | // .expect('example.com', done); 22 | // }) 23 | 24 | test.cb('should return the Host when present', t => { 25 | app.router('fixtures/hostname') 26 | 27 | sletTest(app) 28 | .post('/') 29 | .set('Host', 'example.com') 30 | .expect('example.com', t.end); 31 | }) 32 | 33 | // 34 | // it('should strip port number', function(done){ 35 | // var app = express(); 36 | // 37 | // app.use(function(req, res){ 38 | // res.end(req.hostname); 39 | // }); 40 | // 41 | // request(app) 42 | // .post('/') 43 | // .set('Host', 'example.com:3000') 44 | // .expect('example.com', done); 45 | // }) 46 | 47 | test.cb('should strip port number', t => { 48 | app.router('fixtures/hostname') 49 | 50 | sletTest(app) 51 | .post('/') 52 | .set('Host', 'example.com:3000') 53 | .expect('example.com', t.end); 54 | }) 55 | 56 | // it('should return undefined otherwise', function(done){ 57 | // var app = express(); 58 | // 59 | // app.use(function(req, res){ 60 | // req.headers.host = null; 61 | // res.end(String(req.hostname)); 62 | // }); 63 | // 64 | // request(app) 65 | // .post('/') 66 | // .expect('undefined', done); 67 | // }) 68 | 69 | test.cb('should return empty string otherwise', t => { 70 | app.router('fixtures/hostname2') 71 | 72 | sletTest(app) 73 | .post('/2') 74 | .expect('', t.end); 75 | }) 76 | 77 | // it('should work with IPv6 Host', function(done){ 78 | // var app = express(); 79 | // 80 | // app.use(function(req, res){ 81 | // res.end(req.hostname); 82 | // }); 83 | // 84 | // request(app) 85 | // .post('/') 86 | // .set('Host', '[::1]') 87 | // .expect('[::1]', done); 88 | // }) 89 | // 目前版本koa还不支持,已经提了pr 90 | // test.cb('should work with IPv6 Host', t => { 91 | // app.router('fixtures/hostname') 92 | // 93 | // sletTest(app) 94 | // .post('/') 95 | // .set('Host', '[::1]:3000') 96 | // .expect('[::1]', t.end); 97 | // }) 98 | 99 | 100 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.host.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | // it('should return the Host when present', function(done){ 12 | // var app = express(); 13 | 14 | // app.use(function(req, res){ 15 | // res.end(req.host); 16 | // }); 17 | 18 | // request(app) 19 | // .post('/') 20 | // .set('Host', 'example.com') 21 | // .expect('example.com', done); 22 | // }) 23 | 24 | test.cb('should return the Host when present', t => { 25 | app.router('fixtures/host') 26 | 27 | sletTest(app) 28 | .post('/') 29 | .set('Host', 'example.com') 30 | .expect('example.com', t.end); 31 | }) 32 | 33 | // it('should strip port number', function(done){ 34 | // var app = express(); 35 | 36 | // app.use(function(req, res){ 37 | // res.end(req.host); 38 | // }); 39 | 40 | // request(app) 41 | // .post('/') 42 | // .set('Host', 'example.com:3000') 43 | // .expect('example.com', done); 44 | // }) 45 | 46 | test.cb('should strip port number', t => { 47 | app.router('fixtures/host') 48 | 49 | sletTest(app) 50 | .post('/') 51 | .set('Host', 'example.com:3000') 52 | .expect('example.com:3000', t.end); 53 | }) 54 | 55 | 56 | // it('should return undefined otherwise', function(done){ 57 | // var app = express(); 58 | 59 | // app.use(function(req, res){ 60 | // req.headers.host = null; 61 | // res.end(String(req.host)); 62 | // }); 63 | 64 | // request(app) 65 | // .post('/') 66 | // .expect('undefined', done); 67 | // }) 68 | 69 | // in express return undefined 70 | // in koa return '' 71 | test.cb('should return undefined otherwise', t => { 72 | app.router('fixtures/host2') 73 | 74 | sletTest(app) 75 | .post('/2') 76 | .expect('', t.end); 77 | }) 78 | 79 | 80 | // it('should work with IPv6 Host', function(done){ 81 | // var app = express(); 82 | // 83 | // app.use(function(req, res){ 84 | // res.end(req.host); 85 | // }); 86 | // 87 | // request(app) 88 | // .post('/') 89 | // .set('Host', '[::1]') 90 | // .expect('[::1]', done); 91 | // }) 92 | // 93 | test.cb('should work with IPv6 Host', t => { 94 | app.router('fixtures/host') 95 | 96 | sletTest(app) 97 | .post('/') 98 | .set('Host', '[::1]') 99 | .expect('[::1]', t.end); 100 | }) 101 | -------------------------------------------------------------------------------- /packages/slet/test/router/3-routerDir.1.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | // ### 第三种,指定路径加载 4 | 5 | // ``` 6 | // app.routerDir('app/controller' ) 7 | // ``` 8 | 9 | // 此种情况会默认加载某个目录下的controller,请确保你的controller里有path,无论是属性,还是static属性方式都行。 10 | // ` 11 | 12 | const axios = require('axios') 13 | const Slet = require('../..'); 14 | const app = new Slet({ 15 | root: __dirname, 16 | debug: false 17 | }); 18 | app.start(4004) 19 | // support file path or Controller 20 | app.routerDir('./fixtures') 21 | 22 | 23 | test.cb('GET /path/a?a=1 static.path', t => { 24 | axios.get('http://127.0.0.1:4004/path/a?a=1') 25 | .then(function (response) { 26 | // console.log(response); 27 | t.true(response.status === 200) 28 | t.is(response.data.a, 1) 29 | t.is(parseInt(response.data.b), 1) 30 | t.pass(); 31 | t.end() 32 | }) 33 | .catch(function (error) { 34 | console.log(error); 35 | t.fail(); 36 | t.end() 37 | }); 38 | }) 39 | 40 | test.cb('GET /path/a?a=2 static.path', t => { 41 | axios.get('http://127.0.0.1:4004/path/a?a=2') 42 | .then(function (response) { 43 | // console.log(response.data); 44 | t.true(response.status === 200) 45 | t.is(response.data.a, 1) 46 | t.is(parseInt(response.data.b), 2) 47 | t.pass(); 48 | t.end() 49 | }) 50 | .catch(function (error) { 51 | console.log(error); 52 | t.fail(); 53 | t.end() 54 | }); 55 | }) 56 | 57 | 58 | test.cb('GET /path/this?a=1object.path', t => { 59 | axios.get('http://127.0.0.1:4004/path/this?a=1') 60 | .then(function (response) { 61 | // console.log(response); 62 | t.true(response.status === 200) 63 | t.is(response.data.a, 1) 64 | t.is(parseInt(response.data.b), 1) 65 | t.pass(); 66 | t.end() 67 | }) 68 | .catch(function (error) { 69 | // console.log(error); 70 | t.fail(); 71 | t.end() 72 | }); 73 | }) 74 | 75 | 76 | test.cb('GET /path/this?a=2 object.path', t => { 77 | axios.get('http://127.0.0.1:4004/path/this?a=2') 78 | .then(function (response) { 79 | // console.log(response.data); 80 | t.true(response.status === 200) 81 | t.is(response.data.a, 1) 82 | t.is(parseInt(response.data.b), 2) 83 | t.pass(); 84 | t.end() 85 | }) 86 | .catch(function (error) { 87 | // console.log(error); 88 | t.fail(); 89 | t.end() 90 | }); 91 | }) 92 | 93 | 94 | // fixtures/ctrl 没有path,所以routerDir不生效的 95 | test.cb('fixtures/ctrl 没有path,所以routerDir不生效的', t => { 96 | axios.get('http://127.0.0.1:4004/?a=2') 97 | .then(function (response) { 98 | // console.log(response); 99 | t.fail(); 100 | t.end() 101 | }) 102 | .catch(function (error) { 103 | // console.log(error); 104 | t.pass(); 105 | t.end() 106 | }); 107 | }) 108 | 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slet 2 | 3 | > slet = servlet in Node.js 4.x+ 4 | 5 | [![NPM version](https://img.shields.io/npm/v/slet.svg?style=flat-square)](https://www.npmjs.com/package/slet) 6 | [![Build](https://travis-ci.org/sletjs/slet.svg?branch=master)](https://travis-ci.org/sletjs/slet) 7 | [![codecov.io](https://codecov.io/github/sletjs/slet/coverage.svg?branch=master)](https://codecov.io/github/sletjs/slet?branch=master) 8 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) 9 | [![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/licenses/MIT/) 10 | 11 | - slet 12 | - slet-basecontroller 13 | 14 | ## Features 15 | 16 | - Micro Kernel 17 | - Pluggable Controller 18 | - Build-in Router && Auto-mount Router 19 | - Auto-inject Controller Dependency 20 | - Custom View Render 21 | - Convention over Configuration 22 | - Use Express or Koa req && res api 23 | 24 | ## Usages 25 | 26 | ### Basic 27 | 28 | app.js 29 | 30 | ```js 31 | 'use strict' 32 | 33 | const Slet = require('slet') 34 | 35 | const app = new Slet() 36 | 37 | class MyController extends Slet.BaseController { 38 | get (req, res) { 39 | let username = req.query.username 40 | 41 | return res.send(`hello world ${username}`) 42 | } 43 | } 44 | 45 | app.router('/', MyController) 46 | 47 | app.start(3000) 48 | 49 | ``` 50 | 51 | you run it at Node.js 4.0 + 52 | 53 | ``` 54 | $ node app.js 55 | ``` 56 | 57 | 58 | ### Use Async/Await 59 | 60 | you can also use Async function in Controller 61 | 62 | you can use it in 63 | 64 | - Node.js 7.0 + 65 | - Babel 66 | - Typescript 67 | 68 | app.async.js 69 | 70 | ```js 71 | 'use strict' 72 | 73 | const Slet = require('slet') 74 | 75 | const app = new Slet() 76 | 77 | class MyController extends Slet.BaseController { 78 | async get (req, res) { 79 | let username = req.query.username 80 | // logic 81 | await this.sleep(300) 82 | 83 | // send to browser 84 | return res.send(`hello world ${username}`) 85 | } 86 | 87 | sleep (time) { 88 | return new Promise((resolve) => setTimeout(resolve, time)) 89 | } 90 | } 91 | 92 | app.router('/', MyController) 93 | 94 | app.start(3006) 95 | 96 | ``` 97 | 98 | start app server in terminal 99 | 100 | ``` 101 | $ node --harmony-async-await app.async.js 102 | ``` 103 | 104 | ## Contributing 105 | 106 | 1. Fork it 107 | 2. Create your feature branch (`git checkout -b my-new-feature`) 108 | 3. Commit your changes (`git commit -am 'Add some feature'`) 109 | 4. Push to the branch (`git push origin my-new-feature`) 110 | 5. Create new Pull Request 111 | 112 | ## Welcome fork or feedback 113 | 114 | - write by `i5ting` i5ting@126.com 115 | 116 | ## License 117 | 118 | this repo is released under the [MIT 119 | License](http://www.opensource.org/licenses/MIT). 120 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.param.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | 8 | 9 | // escribe('.param(name, default)', function(){ 10 | // it('should use the default value unless defined', function(done){ 11 | // var app = express(); 12 | // 13 | // app.use(function(req, res){ 14 | // res.end(req.param('name', 'tj')); 15 | // }); 16 | // 17 | // request(app) 18 | // .get('/') 19 | // .expect('tj', done); 20 | // }) 21 | 22 | test.cb('.param(name, default) should use the default value unless defined', t => { 23 | const app = new Slet({ 24 | root: __dirname, 25 | debug: false 26 | }) 27 | 28 | app.router('fixtures/param') 29 | 30 | sletTest(app) 31 | .post('/') 32 | 33 | .expect('tj', t.end); 34 | }) 35 | 36 | 37 | // describe('.param(name)', function(){ 38 | // it('should check req.query', function(done){ 39 | // var app = express(); 40 | // 41 | // app.use(function(req, res){ 42 | // res.end(req.param('name')); 43 | // }); 44 | // 45 | // request(app) 46 | // .get('/?name=tj') 47 | // .expect('tj', done); 48 | // }) 49 | 50 | test.cb('.param(name) should check req.query', t => { 51 | const app = new Slet({ 52 | root: __dirname, 53 | debug: false 54 | }) 55 | 56 | app.router('fixtures/param2') 57 | 58 | sletTest(app) 59 | .post('/?name=tj') 60 | .expect('tj', t.end); 61 | }) 62 | 63 | 64 | 65 | // 66 | // it('should check req.body', function(done){ 67 | // var app = express(); 68 | // 69 | // app.use(bodyParser.json()); 70 | // 71 | // app.use(function(req, res){ 72 | // res.end(req.param('name')); 73 | // }); 74 | // 75 | // request(app) 76 | // .post('/') 77 | // .send({ name: 'tj' }) 78 | // .expect('tj', done); 79 | // }) 80 | // 81 | 82 | test.cb('.param(name) should check req.body', t => { 83 | const app = new Slet({ 84 | root: __dirname, 85 | debug: false 86 | }) 87 | 88 | app.router('fixtures/param2') 89 | 90 | sletTest(app) 91 | .post('/') 92 | .send({ name: 'tj' }) 93 | .expect('tj', t.end); 94 | }) 95 | 96 | 97 | // it('should check req.params', function(done){ 98 | // var app = express(); 99 | // 100 | // app.get('/user/:name', function(req, res){ 101 | // res.end(req.param('filter') + req.param('name')); 102 | // }); 103 | // 104 | // request(app) 105 | // .get('/user/tj') 106 | // .expect('undefinedtj', done); 107 | // }) 108 | // }) 109 | // }) 110 | 111 | test.cb('.param(name) should check req.params', t => { 112 | const app = new Slet({ 113 | root: __dirname, 114 | debug: false 115 | }) 116 | 117 | app.router('fixtures/param3') 118 | 119 | sletTest(app) 120 | .post('/user/tj') 121 | .expect('undefinedtj', t.end); 122 | }) 123 | 124 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/req/req.accepts.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | const app = new Slet({ 8 | root: __dirname, 9 | debug: false 10 | }) 11 | 12 | test.cb('should return true when Accept is not present', t => { 13 | app.router('fixtures/reqaccepts') 14 | 15 | sletTest(app) 16 | .get('/') 17 | .expect('yes', t.end); 18 | }) 19 | 20 | 21 | // it('should return true when present', function(done){ 22 | // var app = express(); 23 | // 24 | // app.use(function(req, res, next){ 25 | // res.end(req.accepts('json') ? 'yes' : 'no'); 26 | // }); 27 | // 28 | // request(app) 29 | // .get('/') 30 | // .set('Accept', 'application/json') 31 | // .expect('yes', done); 32 | // }) 33 | test.cb('should return true when present', t => { 34 | app.router('fixtures/reqaccepts') 35 | 36 | sletTest(app) 37 | .get('/') 38 | .set('Accept', 'application/json') 39 | .expect('yes', t.end); 40 | }) 41 | 42 | // it('should return false otherwise', function(done){ 43 | // var app = express(); 44 | // 45 | // app.use(function(req, res, next){ 46 | // res.end(req.accepts('json') ? 'yes' : 'no'); 47 | // }); 48 | // 49 | // request(app) 50 | // .get('/') 51 | // .set('Accept', 'text/html') 52 | // .expect('no', done); 53 | // }) 54 | // }) 55 | test.cb('should return false otherwise', t => { 56 | app.router('fixtures/reqaccepts') 57 | 58 | sletTest(app) 59 | .get('/') 60 | .set('Accept', 'text/html') 61 | .expect('no', t.end); 62 | }) 63 | 64 | // it('should accept an argument list of type names', function(done){ 65 | // var app = express(); 66 | // 67 | // app.use(function(req, res, next){ 68 | // res.end(req.accepts('json', 'html')); 69 | // }); 70 | // 71 | // request(app) 72 | // .get('/') 73 | // .set('Accept', 'application/json') 74 | // .expect('json', done); 75 | // }) 76 | 77 | // app.defineController(require('../..')) 78 | 79 | 80 | test.cb('should accept an argument list of type names', t => { 81 | app.router('fixtures/reqaccepts2') 82 | 83 | sletTest(app) 84 | .get('/2') 85 | .set('Accept', 'application/json') 86 | .expect('json', t.end); 87 | }) 88 | 89 | // it('should return the first when Accept is not present', function(done){ 90 | // var app = express(); 91 | // 92 | // app.use(function(req, res, next){ 93 | // res.end(req.accepts(['json', 'html'])); 94 | // }); 95 | // 96 | // request(app) 97 | // .get('/') 98 | // .expect('json', done); 99 | // }) 100 | test.cb('should return the first when Accept is not present', t => { 101 | app.router('fixtures/reqaccepts2') 102 | 103 | sletTest(app) 104 | .get('/2') 105 | // .set('Accept', 'application/json') 106 | .expect('json', t.end); 107 | }) 108 | 109 | // it('should return the first acceptable type', function(done){ 110 | // var app = express(); 111 | // 112 | // app.use(function(req, res, next){ 113 | // res.end(req.accepts(['json', 'html'])); 114 | // }); 115 | // 116 | // request(app) 117 | // .get('/') 118 | // .set('Accept', 'text/html') 119 | // .expect('html', done); 120 | // }) 121 | 122 | test.cb('should return the first acceptable type', t => { 123 | app.router('fixtures/reqaccepts2') 124 | 125 | sletTest(app) 126 | .get('/2') 127 | .set('Accept', 'text/html') 128 | .expect('html', t.end); 129 | }) 130 | 131 | 132 | 133 | // it('should return false when no match is made', function(done){ 134 | // var app = express(); 135 | // 136 | // app.use(function(req, res, next){ 137 | // res.end(req.accepts(['text/html', 'application/json']) ? 'yup' : 'nope'); 138 | // }); 139 | // 140 | // request(app) 141 | // .get('/') 142 | // .set('Accept', 'foo/bar, bar/baz') 143 | // .expect('nope', done); 144 | // }) 145 | test.cb('should return false when no match is made', t => { 146 | app.router('fixtures/reqaccepts3') 147 | 148 | sletTest(app) 149 | .get('/3') 150 | .set('Accept', 'foo/bar, bar/baz') 151 | .expect('nope', t.end); 152 | }) 153 | 154 | // it('should take quality into account', function(done){ 155 | // var app = express(); 156 | // 157 | // app.use(function(req, res, next){ 158 | // res.end(req.accepts(['text/html', 'application/json'])); 159 | // }); 160 | // 161 | // request(app) 162 | // .get('/') 163 | // .set('Accept', '*/html; q=.5, application/json') 164 | // .expect('application/json', done); 165 | // }) 166 | 167 | 168 | test.cb('should take quality into account', t => { 169 | app.router('fixtures/reqaccepts4') 170 | 171 | sletTest(app) 172 | .get('/4') 173 | .set('Accept', '*/html; q=.5, application/json') 174 | .expect('application/json', t.end); 175 | }) 176 | 177 | // it('should return the first acceptable type with canonical mime types', function(done){ 178 | // var app = express(); 179 | // 180 | // app.use(function(req, res, next){ 181 | // res.end(req.accepts(['application/json', 'text/html'])); 182 | // }); 183 | // 184 | // request(app) 185 | // .get('/') 186 | // .set('Accept', '*/html') 187 | // .expect('text/html', done); 188 | // }) 189 | 190 | test.cb('should return the first acceptable type with canonical mime types', t => { 191 | app.router('fixtures/reqaccepts4') 192 | 193 | sletTest(app) 194 | .get('/4') 195 | .set('Accept', '*/html') 196 | .expect('text/html', t.end); 197 | }) 198 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/test/res/res.jsonp.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | var sletTest = require('slettest') 4 | const Slet = require('../../../slet') 5 | const BaseController = require('../..') 6 | 7 | // all express jsonp test done! 8 | 9 | test.cb('should respond with jsonp', t => { 10 | const app = new Slet({ 11 | root: __dirname, 12 | debug: false 13 | }) 14 | 15 | app.router('fixtures/jsonp') 16 | 17 | sletTest(app) 18 | .get('/?callback=something') 19 | .expect('Content-Type', 'text/javascript; charset=utf-8') 20 | .expect(200, /something\(\{\"count\":1\}\);/, t.end); 21 | }) 22 | 23 | test.cb('should use first callback parameter with jsonp', t => { 24 | const app = new Slet({ 25 | root: __dirname, 26 | debug: false 27 | }) 28 | 29 | app.router('fixtures/jsonp') 30 | 31 | sletTest(app) 32 | .get('/?callback=something&callback=somethingelse') 33 | .expect('Content-Type', 'text/javascript; charset=utf-8') 34 | .expect(200, /something\(\{"count":1\}\);/, t.end); 35 | }) 36 | 37 | test.cb('should ignore object callback parameter with jsonp', t => { 38 | const app = new Slet({ 39 | root: __dirname, 40 | debug: false 41 | }) 42 | 43 | app.router('fixtures/jsonp') 44 | 45 | sletTest(app) 46 | .get('/?callback[a]=something') 47 | .expect('Content-Type', 'application/json; charset=utf-8') 48 | .expect(200, '{"count":1}', t.end); 49 | }) 50 | 51 | test.cb('should allow []', t => { 52 | const app = new Slet({ 53 | root: __dirname, 54 | debug: false 55 | }) 56 | 57 | app.router('fixtures/jsonp2') 58 | 59 | sletTest(app) 60 | .get('/?callback=callbacks[123]') 61 | .expect('Content-Type', 'text/javascript; charset=utf-8') 62 | .expect(200, /callbacks\[123\]\(\{"count":1\}\);/, t.end); 63 | }) 64 | 65 | test.cb('should ignore object callback parameter with jsonp', t => { 66 | const app = new Slet({ 67 | root: __dirname, 68 | debug: false 69 | }) 70 | 71 | app.router('fixtures/jsonp2') 72 | 73 | sletTest(app) 74 | .get('/2?clb=something') 75 | // .expect('Content-Type', 'application/json') 76 | .expect(200, '{"count":1}', t.end); 77 | }) 78 | 79 | 80 | test.cb('should allow renaming callback', t => { 81 | const app = new Slet({ 82 | root: __dirname, 83 | debug: false 84 | }) 85 | 86 | app.router('fixtures/jsonp3') 87 | 88 | sletTest(app) 89 | .get('/3?clb=something') 90 | .expect('Content-Type', 'text/javascript; charset=utf-8') 91 | .expect(200, /something\(\{"count":1\}\);/, t.end); 92 | }) 93 | 94 | 95 | test.cb('should disallow arbitrary js', t => { 96 | const app = new Slet({ 97 | root: __dirname, 98 | debug: false 99 | }) 100 | 101 | app.router('fixtures/jsonp4') 102 | 103 | sletTest(app) 104 | .get('/4?callback=foo;bar()') 105 | .expect('Content-Type', 'text/javascript; charset=utf-8') 106 | .expect(200, /foobar\(\{\}\);/, t.end); 107 | }) 108 | 109 | 110 | test.cb('should escape utf whitespace', t => { 111 | const app = new Slet({ 112 | root: __dirname, 113 | debug: false 114 | }) 115 | 116 | app.router('fixtures/jsonp5') 117 | 118 | sletTest(app) 119 | .get('/5?callback=foo') 120 | .expect('Content-Type', 'text/javascript; charset=utf-8') 121 | .expect(200, /foo\(\{"str":"\\u2028 \\u2029 woot"\}\);/, t.end); 122 | }) 123 | 124 | test.cb('should not escape utf whitespace for json fallback', t => { 125 | const app = new Slet({ 126 | root: __dirname, 127 | debug: false 128 | }) 129 | 130 | app.router('fixtures/jsonp6') 131 | 132 | sletTest(app) 133 | .get('/6') 134 | .expect('Content-Type', 'application/json; charset=utf-8') 135 | .expect(200, '{"str":"\u2028 \u2029 woot"}', t.end); 136 | }) 137 | 138 | test.cb('should include security header and prologue', t => { 139 | const app = new Slet({ 140 | root: __dirname, 141 | debug: false 142 | }) 143 | 144 | app.router('fixtures/jsonp') 145 | 146 | sletTest(app) 147 | .get('/?callback=something') 148 | .expect('Content-Type', 'text/javascript; charset=utf-8') 149 | .expect('X-Content-Type-Options', 'nosniff') 150 | .expect(200, /^\/\*\*\//, t.end); 151 | }) 152 | 153 | test.cb('should not override previous Content-Types with no callback', t => { 154 | const app = new Slet({ 155 | root: __dirname, 156 | debug: false 157 | }) 158 | 159 | app.router('fixtures/jsonp7') 160 | 161 | sletTest(app) 162 | .get('/7') 163 | .expect('Content-Type', 'application/vnd.example+json') 164 | // .expect(shouldNotHaveHeader('X-Content-Type-Options')) 165 | .expect(200, '{"hello":"world"}', t.end); 166 | }) 167 | 168 | 169 | test.cb('should override previous Content-Types with callback', t => { 170 | const app = new Slet({ 171 | root: __dirname, 172 | debug: false 173 | }) 174 | 175 | app.router('fixtures/jsonp7') 176 | 177 | sletTest(app) 178 | .get('/7?callback=cb') 179 | .expect('Content-Type', 'text/javascript; charset=utf-8') 180 | .expect('X-Content-Type-Options', 'nosniff') 181 | .expect(200, /cb\(\{"hello":"world"\}\);$/, t.end); 182 | }) 183 | 184 | test.cb('when given primitives', t => { 185 | const app = new Slet({ 186 | root: __dirname, 187 | debug: false 188 | }) 189 | 190 | app.router('fixtures/jsonp8') 191 | 192 | sletTest(app) 193 | .get('/8') 194 | .expect('Content-Type', 'application/json; charset=utf-8') 195 | .expect(200, 'null', t.end); 196 | }) 197 | 198 | test.cb('when given an array', t => { 199 | const app = new Slet({ 200 | root: __dirname, 201 | debug: false 202 | }) 203 | 204 | app.router('fixtures/jsonp9') 205 | 206 | sletTest(app) 207 | .get('/9') 208 | .expect('Content-Type', 'application/json; charset=utf-8') 209 | .expect(200, '["foo","bar","baz"]', t.end); 210 | }) 211 | 212 | test.cb('when given an object', t => { 213 | const app = new Slet({ 214 | root: __dirname, 215 | debug: false 216 | }) 217 | 218 | app.router('fixtures/jsonp10') 219 | 220 | sletTest(app) 221 | .get('/10') 222 | .expect('Content-Type', 'application/json; charset=utf-8') 223 | .expect(200, '{"name":"tobi"}', t.end); 224 | }) 225 | 226 | 227 | test.cb('should respond with json for null', t => { 228 | const app = new Slet({ 229 | root: __dirname, 230 | debug: false 231 | }) 232 | 233 | app.router('fixtures/jsonp8') 234 | 235 | sletTest(app) 236 | .get('/8') 237 | .expect('Content-Type', 'application/json; charset=utf-8') 238 | .expect(200, 'null', t.end); 239 | }) 240 | 241 | test.cb('should respond with json for Number', t => { 242 | const app = new Slet({ 243 | root: __dirname, 244 | debug: false 245 | }) 246 | 247 | app.router('fixtures/jsonp11') 248 | 249 | sletTest(app) 250 | .get('/11') 251 | .expect('Content-Type', 'application/json; charset=utf-8') 252 | .expect(200, '300', t.end); 253 | }) 254 | 255 | test.cb('should respond with json for String', t => { 256 | const app = new Slet({ 257 | root: __dirname, 258 | debug: false 259 | }) 260 | 261 | app.router('fixtures/jsonp12') 262 | 263 | sletTest(app) 264 | .get('/12') 265 | .expect('Content-Type', 'application/json; charset=utf-8') 266 | .expect(200, '"str"', t.end); 267 | }) 268 | 269 | test.cb('should be passed to JSON.stringify()', t => { 270 | const app = new Slet({ 271 | root: __dirname, 272 | debug: false 273 | }) 274 | 275 | app.router('fixtures/jsonp13') 276 | 277 | sletTest(app) 278 | .get('/13') 279 | .expect('Content-Type', 'application/json; charset=utf-8') 280 | .expect(200, '{"name":"tobi"}', t.end); 281 | }) 282 | 283 | test.cb('should be passed to JSON.stringify()', t => { 284 | const app = new Slet({ 285 | root: __dirname, 286 | debug: false 287 | }) 288 | 289 | app.router('fixtures/jsonp14') 290 | 291 | sletTest(app) 292 | .get('/14') 293 | .expect('Content-Type', 'application/json; charset=utf-8') 294 | .expect(200, '{\n "name": "tobi",\n "age": 2\n}', t.end); 295 | }) 296 | 297 | test.cb('should respond with json and set the .statusCode', t => { 298 | const app = new Slet({ 299 | root: __dirname, 300 | debug: false 301 | }) 302 | 303 | app.router('fixtures/jsonp15') 304 | 305 | sletTest(app) 306 | .get('/15') 307 | .expect('Content-Type', 'application/json; charset=utf-8') 308 | .expect(201, '{"id":1}', t.end); 309 | }) 310 | 311 | test.cb('should respond with json and set the .statusCode for backwards compat', t => { 312 | const app = new Slet({ 313 | root: __dirname, 314 | debug: false 315 | }) 316 | 317 | app.router('fixtures/jsonp16') 318 | 319 | sletTest(app) 320 | .get('/16') 321 | .expect('Content-Type', 'application/json; charset=utf-8') 322 | .expect(201, '{"id":1}', t.end); 323 | }) 324 | 325 | test.cb('should use status as second number for backwards compat', t => { 326 | const app = new Slet({ 327 | root: __dirname, 328 | debug: false 329 | }) 330 | 331 | app.router('fixtures/jsonp17') 332 | 333 | sletTest(app) 334 | .get('/17') 335 | .expect('Content-Type', 'application/json; charset=utf-8') 336 | .expect(201, '200', t.end); 337 | }) 338 | 339 | test.cb('should not override previous Content-Types', t => { 340 | const app = new Slet({ 341 | root: __dirname, 342 | debug: false 343 | }) 344 | 345 | app.router('fixtures/jsonp17') 346 | 347 | sletTest(app) 348 | .get('/17') 349 | .expect('Content-Type', 'application/json; charset=utf-8') 350 | .expect(201, '200', t.end); 351 | }) 352 | -------------------------------------------------------------------------------- /packages/slet/src/Slet.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const debug = require('debug')('slet') 4 | const http = require('http') 5 | const fs = require('fs') 6 | const dirname = require('path').dirname 7 | const resolve = require('path').resolve 8 | const Koa = require('koa') 9 | const methods = require('methods') 10 | const slice = Array.prototype.slice 11 | const router = require('koa-router')() 12 | const bodyParser = require('koa-bodyparser') 13 | const logger = require('koa-pino-logger') 14 | const compose = require('koa-compose') 15 | const parseController = require('parsecontroller') 16 | 17 | // local 18 | const defaultConfig = require('./config') 19 | const _ctx = defaultConfig.mockCtx 20 | const _next = function () {} 21 | 22 | class Slet { 23 | constructor (opts, root) { 24 | this.opts = Object.assign(defaultConfig, opts) 25 | if (this.opts.root) this.root = this.opts.root 26 | 27 | if (!root) { 28 | this.root = dirname(require.main.filename) 29 | // this.opts.root = this.root 30 | } else { 31 | this.root = root 32 | } 33 | 34 | this.viewPath = resolve(this.opts.root, this.opts.views.path) 35 | 36 | // 37 | this.app = new Koa() 38 | this.routes = [] 39 | this.controllers = [] 40 | this.scanedControllerArray = [] // 扫码opts.root得到的所有的controller信息 41 | this.controllerDependency = [] 42 | this.middlewares = {} 43 | 44 | if (this.opts.debug === true) { 45 | console.log('require.main.filename = ' + require.main.filename) 46 | console.log(this.opts) 47 | } 48 | 49 | let self = this 50 | self.defineController(require('slet-basecontroller')) 51 | self._initMiddleware() 52 | self.routerDir(this.opts.automount.path) 53 | } 54 | 55 | // identifyDept () { 56 | // let self = this 57 | // return new Promise(function (resolve, reject) { 58 | // // console.log(self.opts.root) 59 | // parseController(self.opts.root, function (resultArray) { 60 | // // console.log(resultArray) 61 | // self.scanedControllerArray = resultArray 62 | // resolve(resultArray) 63 | // }) 64 | // }) 65 | // } 66 | 67 | // buildDept (path) { 68 | // let self = this 69 | // return new Promise(function (resolve, reject) { 70 | // parseController(path, function (resultArray) { 71 | // // console.log(resultArray) 72 | // resolve(resultArray) 73 | // }) 74 | // }).then(function (resultArray) { 75 | // // console.log(resultArray) 76 | // for (var i in resultArray) { 77 | // var lib = resultArray[i].dep_controller 78 | // self.defineController(require(lib)) 79 | // } 80 | // }) 81 | // } 82 | 83 | _initMiddleware () { 84 | // post参数的解析,最常用的是其中的json和urlencoded的parser,可分别对以JSON格式的post参数和urlencoeded的post参数进行解析,均可获得一个JSON化的req.body 85 | // TODO: 细化 86 | this.middlewares['koa-bodyparser'] = bodyParser() 87 | this.middlewares['logger'] = logger(this.opts.logger) 88 | } 89 | 90 | defineMiddleware (name, fn) { 91 | this.middlewares[name] = fn 92 | } 93 | 94 | defineController (controller) { 95 | if (typeof controller === 'function') { 96 | this.controllers.push(controller) 97 | this._registerControllerClass(controller) 98 | } else { 99 | console.log('please use class Controller') 100 | } 101 | } 102 | 103 | // global middleware && application filter 104 | use (middleware) { 105 | this.app.use(middleware) 106 | } 107 | 108 | set silent (k){ 109 | this.app.silent = k 110 | } 111 | 112 | get context () { 113 | return this.app.context 114 | } 115 | 116 | set name (k){ 117 | this.app.name = k 118 | } 119 | 120 | get name () { 121 | return this.app.name 122 | } 123 | 124 | set env (k){ 125 | this.app.env = k 126 | } 127 | 128 | get env () { 129 | return this.app.env 130 | } 131 | 132 | set proxy (k){ 133 | this.app.proxy = k 134 | } 135 | 136 | get proxy () { 137 | return this.proxy.env 138 | } 139 | 140 | set subdomainOffset (k){ 141 | this.app.subdomainOffset = k 142 | } 143 | 144 | get subdomainOffset () { 145 | return this.subdomainOffset.env 146 | } 147 | 148 | set keys (k){ 149 | this.app.keys = k 150 | } 151 | 152 | get keys () { 153 | return this.app.keys 154 | } 155 | 156 | // routerDir ('webapp', '/web') 157 | // prefix[optional] 158 | routerDir (dir, prefix) { 159 | var self = this 160 | this.routerPath = resolve(this.opts.root ? this.opts.root : this.root, dir) 161 | 162 | if (fs.existsSync(this.routerPath) === false) { 163 | if (this.opts.debug === true) console.log('router path is not exists: ' + this.routerPath) 164 | return 165 | } 166 | 167 | return Promise.resolve().then(function () { 168 | var requireDir = require('require-dir') 169 | var controllers = requireDir(self.routerPath, self.opts.automount.option) 170 | 171 | for (let i in controllers) { 172 | if (i === '.git' || i === 'package.json') { 173 | return 174 | } 175 | 176 | let Controller = controllers[i] 177 | let mockCtx = new Controller(self, _ctx, _next) 178 | 179 | // 兼容static.path 180 | if (Controller.path) { 181 | if (prefix) { 182 | Controller.prefix = prefix 183 | } 184 | self.router(Controller) 185 | } else if (mockCtx.path) { 186 | // 兼容object.path 187 | if (prefix) { 188 | Controller.prefix = prefix 189 | } 190 | self.router(Controller) 191 | } else { 192 | // warn log 193 | console.warn('[WARNING] routerDir at ' + self.routerPath + ' no path config in ' + Controller) 194 | } 195 | } 196 | }) 197 | } 198 | 199 | asyncRouter (cb) { 200 | let self = this 201 | return self.buildDept(this.opts.root).then(function () { 202 | // must before this.routerDir() 203 | cb() 204 | }) 205 | } 206 | 207 | router () { 208 | let self = this 209 | let path, controller 210 | 211 | if (arguments.length === 1) { 212 | // (controller) 213 | // path = arguments[0] from controller.path 214 | controller = arguments[0] 215 | } else if (arguments.length >= 2) { 216 | // (path, controller) 217 | path = arguments[0] 218 | controller = arguments[1] 219 | } else { 220 | console.log('error') 221 | } 222 | 223 | var Controller = controller 224 | if (typeof controller === 'string') { 225 | // 注意.ctrl && ctrl 226 | // file.exists 227 | let file = resolve(this.opts.root ? this.opts.root : this.root, controller) 228 | // 229 | // 自动注入依赖 230 | var _file = /.js$/.test(file) ? file : file + '.js' 231 | var info = parseController(_file) 232 | // console.log(info) 233 | self.defineController(require(info.dep_controller)) 234 | Controller = require(file) 235 | } 236 | 237 | if (typeof Controller === 'object'){ 238 | console.error('fatal error: you need add module.exports = class xxx') 239 | return 240 | } 241 | 242 | // if (this.opts.auto) { 243 | // let lib = this._getControllerBaseName(Controller) 244 | // this.controllerDependency.push(lib) 245 | // this.defineController(require(lib)) 246 | // } 247 | 248 | var mockCtx = new Controller(self, _ctx, _next) 249 | var avaiableMethods = this._avaiableMethods(mockCtx) 250 | 251 | // 如果attr controller this.path =xxx 252 | if (!path && mockCtx.path) { 253 | path = (Controller.prefix ? Controller.prefix : '') + mockCtx.path 254 | } 255 | 256 | // 如果static controller.path =xxx 257 | if (!path) { 258 | path = (Controller.prefix ? Controller.prefix : '') + Controller.path 259 | } 260 | 261 | if (!path) { 262 | console.log('you must spec a path to controller') 263 | } 264 | 265 | if (this.opts.debug) { 266 | let t = (Controller + '').split(' extends')[0] 267 | 268 | this.routes.push({ 269 | path: path, 270 | class: controller, 271 | avaiableMethods: avaiableMethods, 272 | type: t, 273 | global_filter: mockCtx.global_filter 274 | }) 275 | } 276 | // console.log(path) 277 | debug(this.opts['prefix'] + path) 278 | router.all(this.opts['prefix'] + path, function (ctx, next) { 279 | let verb = ctx.request.method.toLowerCase() 280 | var ctrl = new Controller(self, ctx, next) 281 | debug(ctx.request.method) 282 | debug(ctx.request.path) 283 | // http://expressjs.com/en/4x/api.html#req.route 284 | ctx.request.route = router 285 | 286 | var match = avaiableMethods.find(function (n) { 287 | return n === verb 288 | }) 289 | if (!match && ctrl.all === undefined) { 290 | console.log(path + ' ' + (Controller + '').split(' extends')[0] + ' #' + verb + '() not impl') 291 | ctx.body = { 292 | code: 1, 293 | msg: { 294 | 'text': path + ' ' + verb + ' not impl', 295 | 'controller': (Controller + '').split(' extends')[0] 296 | } 297 | } 298 | 299 | return ctx.body 300 | } 301 | 302 | var _middlewares = [] 303 | 304 | for (var i in ctrl.global_filter) { 305 | _middlewares.push(self.middlewares[ctrl.global_filter[i]]) 306 | } 307 | 308 | debug(_middlewares) 309 | 310 | let filter = ctrl[verb + '_filter'] || [] 311 | for (var j in filter) { 312 | _middlewares.push(filter[j]) 313 | } 314 | 315 | debug(_middlewares) 316 | 317 | _middlewares.push(function last (ctx, next) { 318 | let req = ctx.request 319 | let res = ctx.response 320 | 321 | // before 322 | ctrl.before() 323 | 324 | // bind alias req.xxx and res.yyy 325 | ctrl.__bindAlias(req, res) 326 | 327 | // 如果有all方法,也有对应的verb请求,此种情况下,只会执行all() 328 | if (ctrl['all']) { 329 | ctrl.result = ctrl['all'](req, res, next) 330 | } else { 331 | // execute {verb}() 332 | ctrl.result = ctrl[verb](req, res, next) 333 | } 334 | 335 | // renderType: default | view 336 | return ctrl.__execute().then(function (str) { 337 | if (str) ctx.body = str 338 | // after 339 | ctrl.after() 340 | }) 341 | }) 342 | 343 | debug(_middlewares) 344 | 345 | return compose(_middlewares)(ctx, next).catch(function (error) { 346 | console.log(error) 347 | }) 348 | }) 349 | } 350 | 351 | _avaiableMethods (obj) { 352 | let m = Object.getOwnPropertyNames(Object.getPrototypeOf(obj)) 353 | m.shift() 354 | 355 | let re = [] 356 | // methods 357 | m.forEach(function (method) { 358 | var a = methods.find(function (n) { 359 | return n === method 360 | }) 361 | if (a) re.push(a) 362 | }) 363 | 364 | return re 365 | } 366 | 367 | _getControllerName (Controller) { 368 | let i = (Controller + '').split(' extends')[0] 369 | return i.split('{')[0].replace('class', '').trim() 370 | } 371 | 372 | _getControllerBaseName (Controller) { 373 | if (typeof Controller === 'function'){ 374 | console.log("Controller") 375 | return 376 | } 377 | let i = (Controller + '').split(' extends')[1] 378 | console.log(i) 379 | let j = i.split('{')[0] 380 | 381 | let base = j.trim() 382 | 383 | debug('slet-' + base.toLowerCase()) 384 | 385 | return 'slet-' + base.toLowerCase() 386 | } 387 | 388 | _registerControllerClass (Controller) { 389 | let clz = this._getControllerName(Controller) 390 | Slet[clz] = Controller 391 | } 392 | 393 | callback () { 394 | if (this.opts.debug) { 395 | console.log(this.routes) 396 | console.log(this.controllerDependency) 397 | } 398 | 399 | this.app 400 | .use(router.routes()) 401 | .use(router.allowedMethods()) 402 | 403 | debug('listen') 404 | return this.app.callback() 405 | } 406 | 407 | start () { 408 | if (this.opts.debug) { 409 | console.log(this.routes) 410 | console.log(this.controllerDependency) 411 | } 412 | 413 | this.app 414 | .use(router.routes()) 415 | .use(router.allowedMethods()) 416 | 417 | debug('listen') 418 | const server = http.createServer(this.app.callback()) 419 | return server.listen.apply(server, arguments) 420 | } 421 | 422 | listen () { 423 | return this.start() 424 | } 425 | 426 | run () { 427 | let self = this 428 | 429 | return this.start(function () { 430 | self.port = this.address().port 431 | console.log('Slet listening on port', this.address().port) 432 | }) 433 | } 434 | 435 | plugin () { 436 | let args = slice.call(arguments, 1) 437 | return Slet.plugin.apply(Slet.plugin, args) 438 | } 439 | } 440 | 441 | Slet.plugin = function (Parent) { 442 | // Use slice as node 4 does not support param spread. 443 | let mixins = slice.call(arguments, 1) 444 | class Mixed extends Parent {} 445 | for (let mixin of mixins) { 446 | for (let prop in mixin) { 447 | Mixed.prototype[prop] = mixin[prop] 448 | } 449 | } 450 | return Mixed 451 | } 452 | 453 | module.exports = Slet 454 | -------------------------------------------------------------------------------- /packages/slet-basecontroller/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const debug = require('debug')('slet-basecontroller') 4 | const http = require('http') 5 | const merge = require('utils-merge') 6 | const contentDisposition = require('content-disposition') 7 | const koasend = require('slet-send') 8 | const resolve = require('path').resolve 9 | const vary = require('vary') 10 | const consolidate = require('consolidate') 11 | const statusCodes = http.STATUS_CODES 12 | const slice = Array.prototype.slice 13 | 14 | class Base { 15 | constructor (app, ctx, next) { 16 | this.app = app 17 | this.ctx = ctx 18 | this.res = this.ctx.res 19 | this.next = next 20 | this.renderType = 'default' 21 | this.data = {} 22 | this.tpl = 'index' 23 | this.result = '{verb}() call result' 24 | this.url = 'redirect url' 25 | 26 | //for alias 27 | this.alias = { 28 | req: { 29 | 30 | }, 31 | res: {} 32 | } 33 | 34 | let self = this 35 | this.app.defineMiddleware('registerBaseAlias', function registerBaseAlias(ctx, next) { 36 | if (ctx.request.body) { 37 | self.reqbody = ctx.request.body 38 | self.alias.req.body = ctx.request.body 39 | } 40 | 41 | if (self.ctx.request.query) { 42 | self.query = ctx.request.query 43 | } 44 | 45 | // matches "GET /hello/foo" and "GET /hello/bar" 46 | // self.params['name'] is 'foo' or 'bar' 47 | if (self.ctx.params) { 48 | self.params = ctx.params 49 | self.alias.req.params = ctx.params 50 | } 51 | 52 | if (ctx.response.redirect) { 53 | self.alias.res.redirect = ctx.response.redirect 54 | self.redirect = ctx.redirect 55 | } 56 | // request 57 | self.alias.req.qs = self.qs 58 | // cookies 59 | self.alias.req.cookies = ctx.cookies 60 | self.alias.res.cookie = ctx.cookies 61 | self.alias.res.clearCookie = self.clearCookie 62 | // xhr 63 | self.alias.req.xhr = self.xhr 64 | // param 65 | self.alias.req.param = self.param 66 | // range 67 | self.alias.req.range = self.range 68 | // acceptsCharset 69 | self.alias.req.acceptsCharset = self.acceptsCharset 70 | // acceptsEncoding 71 | self.alias.req.acceptsEncoding = self.acceptsEncoding 72 | // acceptsLanguage 73 | self.alias.req.acceptsLanguage = self.acceptsLanguage 74 | // throw 75 | self.alias.req.throw = ctx.throw 76 | self.alias.res.throw = ctx.throw 77 | 78 | // stringify 79 | self.alias.req.stringify = self.stringify 80 | self.alias.res.stringify = self.stringify 81 | 82 | //logger 83 | 84 | // response 85 | // send 86 | self.alias.res.send = self.send 87 | self.alias.res.locals = self.locals 88 | self.alias.res.sendFile = self.sendFile 89 | self.alias.res.download = self.download 90 | self.alias.res.end = self.end 91 | self.alias.res.write = self.write 92 | self.alias.res.setStatus = self.setStatus 93 | self.alias.res.sendStatus = self.sendStatus 94 | self.alias.res.vary = self.vary 95 | self.alias.res.links = self.links 96 | self.alias.res.location = self.location 97 | self.alias.res.json = self.json 98 | self.alias.res.json_replacer = self.json_replacer 99 | self.alias.res.json_spaces = self.json_spaces 100 | self.alias.res.jsonp = self.jsonp 101 | self.alias.res.jsonp_callback_name = self.jsonp_callback_name 102 | self.alias.res.format = self.format 103 | self.alias.res.getHeader = self.getHeader 104 | self.alias.res.setHeader = self.setHeader 105 | 106 | return next() 107 | }) 108 | 109 | this.app.defineMiddleware('conditional', require('koa-conditional-get')()) 110 | this.app.defineMiddleware('etag', require('koa-etag')()) 111 | 112 | this.global_filter = ['logger','conditional', 'etag', 'koa-bodyparser', 'registerBaseAlias'] 113 | } 114 | 115 | 116 | /** 117 | * 118 | * 119 | * 120 | * @memberOf Base 121 | */ 122 | before () { 123 | 124 | } 125 | 126 | // only for app 127 | __bindAlias (req, res) { 128 | for(var k in this.alias.req) { 129 | let v = this.alias.req[k] 130 | req[k] = v 131 | } 132 | 133 | for(var k in this.alias.res) { 134 | let v = this.alias.res[k] 135 | res[k] = v 136 | } 137 | } 138 | 139 | after () { 140 | 141 | } 142 | 143 | write () { 144 | let write = this.res.write.bind(this.res) 145 | write.apply(write, arguments) 146 | } 147 | 148 | end () { 149 | // default 150 | if (this.headerSent === false && this.res.statusCode === 404) { 151 | this.res.statusCode = 200 152 | } 153 | this.renderType = 'customEnd' 154 | let end = this.res.end.bind(this.res) 155 | 156 | if (arguments.length > 0) { 157 | end.apply(end, arguments) 158 | } else { 159 | end.apply(end, [this.ctx.response.status + '']) 160 | } 161 | } 162 | 163 | get qs () { 164 | const qs = require('qs') 165 | return this.qs = qs.parse(this.ctx.request.querystring) 166 | } 167 | 168 | set qs (q) { 169 | // this.qs = q 170 | } 171 | 172 | get jsonp_callback_name () { 173 | return this._jsonp_callback_name || 'callback' 174 | } 175 | 176 | set jsonp_callback_name (q) { 177 | this._jsonp_callback_name = q 178 | } 179 | 180 | // request 181 | get xhr () { 182 | let val = this.ctx.request.header['x-requested-with'] || '' 183 | if (val) return val.toLowerCase() === 'xmlhttprequest' 184 | } 185 | 186 | range (size, options) { 187 | var range = this.ctx.get('Range') 188 | if (!range) return 189 | return require('range-parser')(size, range, options) 190 | } 191 | 192 | param (name, defaultValue) { 193 | let params = this.params || {} 194 | let body = this.body || {} 195 | let query = this.query || {} 196 | 197 | let args = arguments.length === 1 198 | ? 'name' 199 | : 'name, default'; 200 | //console.log('req.param(' + args + '): Use req.params, req.body, or req.query instead') 201 | 202 | if (null != params[name] && params.hasOwnProperty(name)) return params[name] 203 | if (null != body[name]) return body[name] 204 | if (null != query[name]) return query[name] 205 | 206 | return defaultValue 207 | } 208 | // response 209 | send (text) { 210 | if (typeof text === 'boolean'){ 211 | this.ctx.body = text 212 | return this 213 | } 214 | text !== undefined ? this.ctx.body = text : this.ctx.body = '' 215 | return this 216 | } 217 | 218 | get locals () { 219 | return this.ctx.state 220 | } 221 | 222 | set locals (val){ 223 | return this.ctx.state = val 224 | } 225 | 226 | get acceptsCharset () { 227 | return this.ctx.request.acceptsCharsets 228 | } 229 | 230 | set acceptsCharset (val) { 231 | return this.ctx.request.acceptsCharsets = val 232 | } 233 | 234 | get acceptsEncoding () { 235 | return this.ctx.request.acceptsEncodings 236 | } 237 | 238 | set acceptsEncoding (val) { 239 | return this.ctx.request.acceptsEncodings = val 240 | } 241 | 242 | get acceptsLanguage () { 243 | return this.ctx.request.acceptsLanguages 244 | } 245 | 246 | set acceptsLanguage (val) { 247 | return this.ctx.request.acceptsLanguages = val 248 | } 249 | 250 | clearCookie (name, options) { 251 | var opts = merge({ expires: new Date(1), path: '/' }, options) 252 | 253 | this.ctx.cookies.set(name, '', opts) 254 | return this 255 | } 256 | 257 | download (path, filename) { 258 | var name = filename 259 | 260 | // support function as second arg 261 | if (typeof filename === 'function') { 262 | done = filename 263 | name = null 264 | } 265 | 266 | // set Content-Disposition when file is sent 267 | var headers = { 268 | 'Content-Disposition': contentDisposition(name || path) 269 | } 270 | 271 | // Resolve the full path for sendFile 272 | var fullPath = resolve(path) 273 | 274 | return this.sendFile(fullPath, { headers: headers }) 275 | } 276 | 277 | sendFile (filepath, options) { 278 | let _filepath = filepath || this.ctx.path 279 | let _options = options || {} 280 | return koasend(this.ctx, _filepath, _options) 281 | } 282 | 283 | getHeader (field) { 284 | return this.ctx.get[field] 285 | } 286 | 287 | setHeader (field, value) { 288 | return this.ctx.set(field, value) 289 | } 290 | 291 | setStatus (code) { 292 | this.ctx.status= parseInt(code) 293 | return this 294 | } 295 | 296 | sendStatus (code) { 297 | this.ctx.status= parseInt(code) 298 | let txt = statusCodes[statusCode] || String(statusCode); 299 | 300 | return this.ctx.body = txt 301 | } 302 | 303 | vary (field) { 304 | // checks for back-compat 305 | if (!field || (Array.isArray(field) && !field.length)) { 306 | console.log('res.vary(): Provide a field name'); 307 | return this; 308 | } 309 | 310 | vary(this.ctx.response, field); 311 | 312 | return this; 313 | } 314 | 315 | links (links) { 316 | var link = this.ctx.response.get('Link') || '' 317 | if (link) link += ', ' 318 | 319 | this.ctx.response.set('Link', link + Object.keys(links).map(function(rel){ 320 | return '<' + links[rel] + '>; rel="' + rel + '"'; 321 | }).join(', ')) 322 | return this 323 | } 324 | 325 | location (url) { 326 | const encodeUrl = require('encodeurl') 327 | var loc = url 328 | 329 | // "back" is an alias for the referrer 330 | if (url === 'back') { 331 | loc = this.ctx.request.get('Referrer') || '/' 332 | } 333 | 334 | // set location 335 | this.ctx.response.set('Location', encodeUrl(loc)) 336 | return this 337 | } 338 | 339 | json (obj) { 340 | if (obj === null) { 341 | obj = {} 342 | } 343 | if (!this.ctx.response.type) { 344 | this.ctx.response.remove('Content-Length'); 345 | this.ctx.response.type = 'json' 346 | } 347 | this.res.statusCode = 200 348 | return this.end(this.stringify(obj)) 349 | } 350 | 351 | /** 352 | * Send JSON response with JSONP callback support. 353 | * 354 | * Examples: 355 | * 356 | * res.jsonp(null); 357 | * res.jsonp({ user: 'tj' }); 358 | * 359 | * @param {string|number|boolean|object} obj 360 | * @public 361 | */ 362 | jsonp (obj) { 363 | var val = obj; 364 | this.res.statusCode = 200 365 | // allow status / body 366 | if (arguments.length === 2) { 367 | // res.json(body, status) backwards compat 368 | if (typeof arguments[1] === 'number') { 369 | // deprecate('res.jsonp(obj, status): Use res.status(status).json(obj) instead'); 370 | this.statusCode = arguments[1]; 371 | } else { 372 | // deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead'); 373 | this.statusCode = arguments[0]; 374 | val = arguments[1]; 375 | } 376 | } 377 | 378 | // settings 379 | var app = this.app; 380 | var replacer = this.json_replacer; 381 | var spaces = this.json_spaces; 382 | // console.log(this.ctx.response) 383 | 384 | var body = this.stringify(val, replacer, spaces); 385 | var callback = this.ctx.request.qs[this.jsonp_callback_name]; 386 | 387 | // content-type 388 | if (!this.ctx.type) { 389 | this.ctx.set('X-Content-Type-Options', 'nosniff'); 390 | this.ctx.set('Content-Type', 'application/json; charset=utf-8'); 391 | } 392 | 393 | // fixup callback 394 | if (Array.isArray(callback)) { 395 | callback = callback[0]; 396 | } 397 | 398 | // jsonp 399 | if (typeof callback === 'string' && callback.length !== 0) { 400 | // this.ctx.charset = 'utf-8'; 401 | this.ctx.set('X-Content-Type-Options', 'nosniff'); 402 | this.ctx.set('Content-Type', 'text/javascript; charset=utf-8'); 403 | 404 | // restrict callback charset 405 | callback = callback.replace(/[^\[\]\w$.]/g, ''); 406 | 407 | // replace chars not allowed in JavaScript that are in JSON 408 | body = body 409 | .replace(/\u2028/g, '\\u2028') 410 | .replace(/\u2029/g, '\\u2029'); 411 | 412 | // the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse" 413 | // the typeof check is just to reduce client error noise 414 | body = '/**/ typeof ' + callback + ' === \'function\' && ' + callback + '(' + body + ');'; 415 | } 416 | 417 | if (this.statusCode) { 418 | this.res.statusCode = this.statusCode 419 | } 420 | 421 | return this.end(body) 422 | } 423 | 424 | get json_replacer () { 425 | return this._json_replacer|| null 426 | } 427 | 428 | set json_replacer (fn) { 429 | return this._json_replacer = fn 430 | } 431 | 432 | get json_spaces () { 433 | return this._json_spaces || 0 434 | } 435 | 436 | set json_spaces (val) { 437 | return this._json_spaces = val 438 | } 439 | 440 | /** 441 | * 442 | * 443 | * @param {any} obj 444 | * 445 | * @memberOf Base 446 | */ 447 | format (obj) { 448 | var req = this.ctx.request; 449 | var next = req.next; 450 | 451 | function acceptParams(str, index) { 452 | var parts = str.split(/ *; */); 453 | var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index }; 454 | 455 | for (var i = 1; i < parts.length; ++i) { 456 | var pms = parts[i].split(/ *= */); 457 | if ('q' === pms[0]) { 458 | ret.quality = parseFloat(pms[1]); 459 | } else { 460 | ret.params[pms[0]] = pms[1]; 461 | } 462 | } 463 | 464 | return ret; 465 | } 466 | 467 | function normalizeType(type){ 468 | return ~type.indexOf('/') 469 | ? acceptParams(type) 470 | : { value: mime.lookup(type), params: {} }; 471 | } 472 | 473 | function normalizeTypes(types){ 474 | var ret = []; 475 | 476 | for (var i = 0; i < types.length; ++i) { 477 | ret.push(exports.normalizeType(types[i])); 478 | } 479 | 480 | return ret; 481 | } 482 | 483 | var fn = obj.default; 484 | if (fn) delete obj.default; 485 | var keys = Object.keys(obj); 486 | 487 | var key = keys.length > 0 488 | ? req.accepts(keys) 489 | : false; 490 | 491 | this.ctx.response.vary("Accept"); 492 | 493 | let _body = {} 494 | if (key) { 495 | this.ctx.response.set('Content-Type', normalizeType(key).value); 496 | _body = obj[key](req, this.ctx.response, this.next); 497 | } else if (fn) { 498 | _body = fn(); 499 | } else { 500 | var err = new Error('Not Acceptable'); 501 | err.status = err.statusCode = 406; 502 | err.types = normalizeTypes(keys).map(function(o){ return o.value }); 503 | this.throw(err); 504 | } 505 | } 506 | 507 | /** 508 | * Stringify JSON, like JSON.stringify, but v8 optimized. 509 | * @private 510 | */ 511 | 512 | stringify (value, replacer, spaces) { 513 | // v8 checks arguments.length for optimizing simple call 514 | // https://bugs.chromium.org/p/v8/issues/detail?id=4730 515 | return replacer || spaces 516 | ? JSON.stringify(value, replacer, spaces) 517 | : JSON.stringify(value) 518 | } 519 | 520 | __execute () { 521 | let self = this; 522 | if (this.renderType === 'default') { 523 | return new Promise(function (resolve, reject) { 524 | resolve(self.result) 525 | }) 526 | } 527 | 528 | if (this.renderType === 'view') { 529 | var obj = { 530 | data: this.data, 531 | tpl: this.tpl 532 | } 533 | Object.assign(obj, this.result) 534 | 535 | return this.compile(obj.tpl, obj.data).then(function (html) { 536 | return new Promise(function (resolve, reject) { 537 | resolve(html ? html : self.result) 538 | }) 539 | }) 540 | } 541 | 542 | // for this.redirect() 543 | if (this.renderType === 'redirect') { 544 | return new Promise(function (resolve, reject) { 545 | resolve(true) 546 | }) 547 | } 548 | 549 | // for this.end() 550 | if (this.renderType === 'customEnd') { 551 | return new Promise(function (resolve, reject) { 552 | resolve(true) 553 | }) 554 | } 555 | } 556 | } 557 | 558 | module.exports = class BaseController extends Base { 559 | constructor (app, ctx, next) { 560 | super(app, ctx, next) 561 | 562 | let self = this 563 | this.app.defineMiddleware('registerBaseControllerAlias', function registerBaseControllerAlias(ctx, next) { 564 | self.alias.res.render = self.render.bind(self) 565 | self.alias.res.getTplPath = self.getTplPath.bind(self) 566 | return next() 567 | }) 568 | 569 | this.global_filter.push('registerBaseControllerAlias') 570 | } 571 | 572 | getTplPath (tpl) { 573 | let self = this 574 | return self.app.viewPath + '/' + tpl + '.' + self.app.opts.views.extension 575 | } 576 | 577 | compile (tpl, data) { 578 | let self = this 579 | let engine = self.app.opts.views.engine 580 | debug(self.app.opts) 581 | return consolidate[engine](self.getTplPath (tpl), data) 582 | } 583 | 584 | render (tpl, data) { 585 | this.renderType = 'view' 586 | let _data = data ? data : this.ctx.state 587 | if (tpl) this.tpl = tpl 588 | if (data) this.data = _data 589 | } 590 | } 591 | 592 | --------------------------------------------------------------------------------