├── .autod.conf.js ├── .eslintignore ├── .eslintrc ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── README.zh_CN.md ├── app.js ├── appveyor.yml ├── config └── config.default.js ├── index.d.ts ├── lib └── index.js ├── package.json └── test ├── fixtures └── apps │ └── router-group-test │ ├── app │ ├── controller │ │ ├── group.js │ │ ├── home.js │ │ ├── middlew.js │ │ ├── name.js │ │ ├── posts.js │ │ └── prefix.js │ ├── middleware │ │ ├── glob.js │ │ ├── m1.js │ │ └── m2.js │ └── router.js │ ├── config │ └── config.default.js │ └── package.json └── router-group.test.js /.autod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | write: true, 5 | prefix: '^', 6 | plugin: 'autod-egg', 7 | test: [ 8 | 'test', 9 | 'benchmark', 10 | ], 11 | devdep: [ 12 | 'egg', 13 | 'egg-ci', 14 | 'egg-bin', 15 | 'autod', 16 | 'autod-egg', 17 | 'eslint', 18 | 'eslint-config-egg', 19 | 'webstorm-disable-index', 20 | ], 21 | exclude: [ 22 | './test/fixtures', 23 | './docs', 24 | './coverage', 25 | ], 26 | }; 27 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-egg", 3 | "rules": { 4 | "linebreak-style": [0, "error", "windows"] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ##### Checklist 12 | 13 | 14 | - [ ] `npm test` passes 15 | - [ ] tests and/or benchmarks are included 16 | - [ ] documentation is changed or added 17 | - [ ] commit message follows commit guidelines 18 | 19 | ##### Affected core subsystem(s) 20 | 21 | 22 | 23 | ##### Description of change 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | npm-debug.log 3 | node_modules/ 4 | coverage/ 5 | .idea/ 6 | run/ 7 | .DS_Store 8 | *.swp 9 | package-lock.json 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '8' 5 | - '9' 6 | install: 7 | - npm i npminstall && npminstall 8 | script: 9 | - npm run ci 10 | after_script: 11 | - npminstall codecov && codecov 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Alibaba Group Holding Limited and other contributors. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # egg-router-group 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![build status][travis-image]][travis-url] 5 | [![Test coverage][codecov-image]][codecov-url] 6 | [![David deps][david-image]][david-url] 7 | [![Known Vulnerabilities][snyk-image]][snyk-url] 8 | [![npm download][download-image]][download-url] 9 | 10 | [npm-image]: https://img.shields.io/npm/v/egg-router-group.svg?style=flat-square 11 | [npm-url]: https://npmjs.org/package/egg-router-group 12 | [travis-image]: https://img.shields.io/travis/zzzs/egg-router-group.svg?style=flat-square 13 | [travis-url]: https://travis-ci.org/zzzs/egg-router-group 14 | [codecov-image]: https://img.shields.io/codecov/c/github/zzzs/egg-router-group.svg?style=flat-square 15 | [codecov-url]: https://codecov.io/github/zzzs/egg-router-group?branch=master 16 | [david-image]: https://img.shields.io/david/zzzs/egg-router-group.svg?style=flat-square 17 | [david-url]: https://david-dm.org/zzzs/egg-router-group 18 | [snyk-image]: https://snyk.io/test/github/zzzs/egg-router-group/badge.svg?targetFile=package.json 19 | [snyk-url]: https://snyk.io/test/github/zzzs/egg-router-group?targetFile=package.json 20 | [download-image]: https://img.shields.io/npm/dm/egg-router-group.svg?style=flat-square 21 | [download-url]: https://npmjs.org/package/egg-router-group 22 | 23 | have the ability to route group operations for eggjs. 24 | 25 | 赋予eggjs路由群组操作的能力。 26 | 27 | 28 | ## Install 29 | 30 | ```bash 31 | $ npm i egg-router-group --save 32 | ``` 33 | 34 | ## Mount 35 | 36 | ```js 37 | // {app_root}/config/plugin.js 38 | exports.routerGroup = { 39 | enable: true, 40 | package: 'egg-router-group', 41 | }; 42 | ``` 43 | 44 | ## Features 45 | > 为 app.router 注入了路由群组 group(options, cb) 方法, options: 路由群组公用属性, cb: 路由回调。 46 | 47 | 路由群组允许你共用路由属性,例如:路由别名前缀,路由url前缀,中间件等,你可以利用路由群组统一为多个路由设置共同属性,而不需在每个路由上都设置一次。共用属性被指定为对象格式,当作 app.router.group 方法的第一个参数,具体路由群组的相关内容,可参考下面几个常用样例来熟悉这些特性。 48 | 49 | **目前支持这三种属性** 50 | 51 | * 路由别名前缀: name 52 | * 路由url前缀: prefix 53 | * 中间件: middlewares 54 | 55 | ## Usage 56 | 57 | ### 基本用法 58 | 59 | ```js 60 | // {app_root}/app/router.js 61 | module.exports = app => { 62 | const { router, controller, middleware } = app; 63 | const m1 = middleware.m1(); 64 | const m2 = middleware.m2({ key: 'value' }); 65 | const m3 = middleware.m3(); 66 | 67 | router.group({ name: 'home::', prefix: '/pre', middlewares: [ m1, m2 ] }, router => { 68 | // router-path: /pre/test, middlewares: m1, m2 69 | // router-path: /pre/test2, middlewares: m1, m2 70 | router.get('/test', controller.home.test).get('/test2', controller.home.test); 71 | // router-name: home::post, router-path: /pre/post, middlewares: m1, m2, m3 72 | router.post('post', '/post', m3, controller.home.post); 73 | 74 | // others 75 | router.all('/test', controller.home.all1); 76 | router.all('testname', '/test2', controller.home.all2); 77 | router.put('/put', controller.home.put); 78 | router.delete('/delete', controller.home.delete); 79 | router.del('/del', controller.home.del); 80 | router.options('/options', controller.home.options); 81 | router.patch('/patch', controller.home.patch); 82 | router.redirect('/redirect', '/'); 83 | router.redirect('/redirect2', 'home::testname', 302); 84 | }); 85 | 86 | // 设置单个属性 87 | router.group({ name: 'home::' }, router => { 88 | // router-path: /test 89 | router.get('/test', controller.home.test); 90 | // router-name: home::post, router-path: /post 91 | router.post('post', '/post', controller.home.post); 92 | }); 93 | 94 | // group 同样支持链式操作 95 | router.group({ name: 'home::', prefix: '/pre', middlewares: [ m1, m2 ] }, router => { 96 | // router-path: /pre/test, middlewares: m1, m2 97 | // router-path: /pre/test2, middlewares: m1, m2 ⚠️这里🈶️group 设置的属性哦 98 | router.get('/test', controller.home.test).get('/test2', controller.home.test); 99 | }) 100 | .get('/test3', controller.home.test); // router-path: /test3 ⚠️这里🈚group 设置的属性哦 101 | }; 102 | ``` 103 | 104 | ### 中间件 105 | 106 | > 支持传单个中间件或数组的形式 107 | 108 | ```js 109 | // {app_root}/app/router.js 110 | module.exports = app => { 111 | const { router, controller, middleware } = app; 112 | const m1 = middleware.m1(); 113 | const m2 = middleware.m2({ key: 'value' }); 114 | 115 | router.group({ middlewares: [ m1, m2 ] }, router => { 116 | router.get('/test_m1', controller.home.test_m1); 117 | router.post('/test_m2/:id', controller.home.test_m2); 118 | }); 119 | router.group({ middlewares: m1 }, router => { 120 | router.get('/test_m3', controller.home.test_m3); 121 | router.post('/test_m4/:id', controller.home.test_m4); 122 | }); 123 | }; 124 | ``` 125 | 126 | ### 路由别名前缀 & 路由url前缀 127 | > 路由别名前缀 & 路由url前缀 只支持string类型 128 | 129 | ```js 130 | // {app_root}/app/router.js 131 | module.exports = app => { 132 | // name 133 | router.group({ name: 'home::' }, router => { 134 | // router-name: home::post 135 | router.post('post', '/test/:id', controller.home.t1); 136 | }); 137 | 138 | // prefix 139 | router.group({ prefix: '/pre' }, router => { 140 | // router-name: test, router-path: /pre/test2 141 | router.get('test', '/test2', controller.home.t2); 142 | }); 143 | }; 144 | ``` 145 | 146 | ### Advanced Usage 147 | > 路由子群组,顾名思义,即路由群组内也可以使用路由群组功能,很适用于大型项目,当路由到达一定量级时,也能轻松维护管理。如果你想的话,路由群组可以一直嵌套下去。 148 | 149 | 150 | **注:如果出现设置重复的中间件,该中间件也会被执行多次,这部分自由度还是会开放给用户,不做特殊处理。** 151 | 152 | ```js 153 | 154 | // {app_root}/app/router.js 155 | router.group({ name: 'home1::', prefix: '/pre1', middlewares: m1 }, router => { 156 | // router-name: home1::name_g1, router-path: /pre1/test_g1, middlewares: m1, m2 157 | router.get('name_g1', '/test_g1', m2, controller.group.g1); 158 | 159 | router.group({ prefix: '/pre2', middlewares: m2 }, router => { 160 | // router-path: /pre1/pre2/test_g3, middlewares: m1, m2, m2 161 | router.get('/test_g3', m2, controller.group.g1); 162 | 163 | // router-path: /pre1/pre2/test_g4/:id, middlewares: m1, m2 164 | // router-path: /pre1/pre2/test_g4_1/:id, middlewares: m1, m2 165 | router.post('/test_g4/:id', controller.group.g2).get('/test_g4_1', controller.group.g2); 166 | 167 | router.group({ name: 'home2::' }, router => { 168 | // router-name: home1::home2::name_g6, router-path: /pre1/pre2/test_g6/:id, middlewares: m1, m2 169 | router.post('name_g6', '/test_g6/:id', controller.group.g2); 170 | // ... 171 | }); 172 | }) 173 | .get('/test_g2_1', controller.group.g1); // router-path: /pre1/test_g2_1, middlewares: m1 174 | }); 175 | ``` 176 | 177 | ## Questions & Suggestions 178 | 179 | Please open an issue [here](https://github.com/zzzs/egg-router-group/issues). 180 | 181 | ## License 182 | 183 | [MIT](LICENSE) 184 | -------------------------------------------------------------------------------- /README.zh_CN.md: -------------------------------------------------------------------------------- 1 | # egg-router-group 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![build status][travis-image]][travis-url] 5 | [![Test coverage][codecov-image]][codecov-url] 6 | [![David deps][david-image]][david-url] 7 | [![Known Vulnerabilities][snyk-image]][snyk-url] 8 | [![npm download][download-image]][download-url] 9 | 10 | [npm-image]: https://img.shields.io/npm/v/egg-router-group.svg?style=flat-square 11 | [npm-url]: https://npmjs.org/package/egg-router-group 12 | [travis-image]: https://img.shields.io/travis/eggjs/egg-router-group.svg?style=flat-square 13 | [travis-url]: https://travis-ci.org/eggjs/egg-router-group 14 | [codecov-image]: https://img.shields.io/codecov/c/github/eggjs/egg-router-group.svg?style=flat-square 15 | [codecov-url]: https://codecov.io/github/eggjs/egg-router-group?branch=master 16 | [david-image]: https://img.shields.io/david/eggjs/egg-router-group.svg?style=flat-square 17 | [david-url]: https://david-dm.org/eggjs/egg-router-group 18 | [snyk-image]: https://snyk.io/test/npm/egg-router-group/badge.svg?style=flat-square 19 | [snyk-url]: https://snyk.io/test/npm/egg-router-group 20 | [download-image]: https://img.shields.io/npm/dm/egg-router-group.svg?style=flat-square 21 | [download-url]: https://npmjs.org/package/egg-router-group 22 | 23 | 26 | 27 | ## 依赖说明 28 | 29 | ### 依赖的 egg 版本 30 | 31 | egg-router-group 版本 | egg 1.x 32 | --- | --- 33 | 1.x | 😁 34 | 0.x | ❌ 35 | 36 | ### 依赖的插件 37 | 45 | 46 | ## 开启插件 47 | 48 | ```js 49 | // config/plugin.js 50 | exports.routerGroup = { 51 | enable: true, 52 | package: 'egg-router-group', 53 | }; 54 | ``` 55 | 56 | ## 使用场景 57 | 58 | - Why and What: 描述为什么会有这个插件,它主要在完成一件什么事情。 59 | 尽可能描述详细。 60 | - How: 描述这个插件是怎样使用的,具体的示例代码,甚至提供一个完整的示例,并给出链接。 61 | 62 | ## 详细配置 63 | 64 | 请到 [config/config.default.js](config/config.default.js) 查看详细配置项说明。 65 | 66 | ## 单元测试 67 | 68 | 69 | 70 | ## 提问交流 71 | 72 | 请到 [egg issues](https://github.com/eggjs/egg/issues) 异步交流。 73 | 74 | ## License 75 | 76 | [MIT](LICENSE) 77 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Router = require('./lib/index'); 3 | 4 | module.exports = app => { 5 | const router = new Router(app); 6 | 7 | /** 8 | * 路由群组操作 9 | * @param {Object} options { name: 'aaa', prefix: '/pre', middlewares: [ m1, m2 ] } [群组属性] 10 | * @param {Function} cb [回调] 11 | * @return {undefined} [undefined] 12 | */ 13 | app.router.group = (options, cb) => { 14 | return router.group(options, cb); 15 | }; 16 | }; 17 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '8' 4 | - nodejs_version: '9' 5 | 6 | install: 7 | - ps: Install-Product node $env:nodejs_version 8 | - npm i npminstall && node_modules\.bin\npminstall 9 | 10 | test_script: 11 | - node --version 12 | - npm --version 13 | - npm run test 14 | 15 | build: off 16 | -------------------------------------------------------------------------------- /config/config.default.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * egg-router-group default config 5 | * @member Config#routerGroup 6 | * @property {String} SOME_KEY - some description 7 | */ 8 | exports.routerGroup = { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import { Router, Context } from 'egg'; 2 | import { IMiddleware } from 'koa-router' 3 | 4 | interface RouterGroupOptions { 5 | name?: string; 6 | prefix?: string; 7 | middlewares?: IMiddleware | IMiddleware[]; 8 | } 9 | 10 | type groupFunction = (router: RouterGroup) => void; 11 | 12 | interface RouterGroup extends Router { 13 | group(options: RouterGroupOptions, cb: groupFunction): RouterGroup; 14 | } 15 | 16 | declare module 'egg' { 17 | interface Application { 18 | router: RouterGroup; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const is = require('is-type-of'); 4 | const assert = require('assert'); 5 | 6 | // except redirect, because be equal to all 7 | // https://eggjs.org/zh-cn/basics/router.html 8 | const methods = [ 'head', 'options', 'get', 'put', 'patch', 'post', 'delete', 'del', 'all', 'resources' ]; 9 | 10 | class Router { 11 | constructor(app) { 12 | this.app = app; 13 | } 14 | 15 | /** 16 | * [路由群组操作] 17 | * @param {Object} options { name: 'aaa', prefix: '/pre', middlewares: [ m1, m2 ] } [群组属性] 18 | * @param {Function} cb [回调] 19 | * @return {undefined} undefined 20 | */ 21 | group(options, cb) { 22 | const name = options.name || ''; 23 | const prefix = options.prefix || ''; 24 | let middlewares = options.middlewares || []; 25 | // params validate 26 | if (!is.array(middlewares)) { 27 | assert(is.function(middlewares), `middlewares must be function or array, but got ${middlewares}`); 28 | middlewares = [ middlewares ]; 29 | } 30 | 31 | assert(is.string(name), `name must be string, but got ${name}`); 32 | assert(is.string(prefix), `prefix must be string, but got ${prefix}`); 33 | 34 | // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy 35 | const proxy = new Proxy(this.app.router, { 36 | get(target, property) { 37 | const funcTarget = target[property]; 38 | // group 递归 39 | if (property === 'group') { 40 | return groupProxy(funcTarget, name, prefix, middlewares, proxy); 41 | } 42 | 43 | if (!methods.includes(property) || (name === '' && prefix === '' && middlewares.length === 0)) { 44 | return funcTarget; 45 | } 46 | 47 | return funcProxy(funcTarget, name, prefix, middlewares, proxy); 48 | }, 49 | }); 50 | 51 | cb(proxy); 52 | 53 | return this.app.router; 54 | } 55 | } 56 | 57 | module.exports = Router; 58 | 59 | /** 60 | * [router.verb Proxy] 61 | * @param {Function}funcTarget router.verb 路由方法 62 | * @param {String} name 路由别名前缀 63 | * @param {String} prefix 路由前缀 64 | * @param {Function/Array} middlewares 中间件 65 | * @param {Object} proxy 路由 66 | * @return {Object} return router.verb Proxy 67 | */ 68 | function funcProxy(funcTarget, name, prefix, middlewares, proxy) { 69 | return new Proxy(funcTarget, { 70 | apply(target, ctx, args) { 71 | // egg-core\lib\utils\router.js#spliteAndResolveRouterParams() 72 | if (args.length >= 3 && (is.string(args[1]) || is.regExp(args[1]))) { 73 | // app.get(name, url, [...middleware], controller) 74 | assert(is.string(args[0]), `router-name must be string, but got ${args[0]}`); 75 | assert(is.string(args[1]), `router-path must be string, but got ${args[1]}`); 76 | 77 | args[0] = joinPrefix(name, args[0]); 78 | args[1] = joinPrefix(prefix, args[1]); 79 | args.splice(2, 0, ...middlewares); 80 | } else { 81 | // app.get(url, [...middleware], controller) 82 | assert(is.string(args[0]), `router-path must be string, but got ${args[0]}`); 83 | args[0] = joinPrefix(prefix, args[0]); 84 | args.splice(1, 0, ...middlewares); 85 | } 86 | 87 | // return target.apply(ctx, args); 88 | // es6 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect 89 | Reflect.apply(target, ctx, args); 90 | return proxy; 91 | }, 92 | }); 93 | } 94 | 95 | /** 96 | * [router.group Proxy] 97 | * @param {Function}funcTarget router.verb 路由方法 98 | * @param {String} name 路由别名前缀 99 | * @param {String} prefix 路由前缀 100 | * @param {Function/Array} middlewares 中间件 101 | * @param {Object} proxy 路由 102 | * @return {Object} return router.verb Proxy 103 | */ 104 | function groupProxy(funcTarget, name, prefix, middlewares, proxy) { 105 | return new Proxy(funcTarget, { 106 | apply(target, ctx, args) { 107 | if ('name' in args[0]) { 108 | name += args[0].name; 109 | } 110 | if ('prefix' in args[0]) { 111 | prefix += args[0].prefix; 112 | } 113 | if ('middlewares' in args[0]) { 114 | const middlewareItem = args[0].middlewares; 115 | if (!is.array(middlewareItem)) { 116 | assert(is.function(middlewareItem), `middlewares must be function or array, but got ${middlewareItem}`); 117 | middlewares = [ ...middlewares, middlewareItem ]; 118 | } else { 119 | middlewares = [ ...middlewares, ...middlewareItem ]; 120 | } 121 | } 122 | 123 | args[0] = { 124 | name, 125 | prefix, 126 | middlewares, 127 | }; 128 | Reflect.apply(target, ctx, args); 129 | return proxy; 130 | }, 131 | }); 132 | } 133 | 134 | /** 135 | * [joinPrefix description] 136 | * @param {[type]} prefix [description] 137 | * @param {[type]} str [description] 138 | * @return {[type]} [description] 139 | */ 140 | function joinPrefix(prefix, str) { 141 | return prefix + str; 142 | } 143 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "egg-router-group", 3 | "version": "1.1.0", 4 | "description": "have the ability to route group operations for eggjs (使eggjs具有路由群组操作的能力)", 5 | "eggPlugin": { 6 | "name": "routerGroup" 7 | }, 8 | "keywords": [ 9 | "egg", 10 | "egg-router", 11 | "router", 12 | "eggPlugin", 13 | "egg-plugin", 14 | "javascript", 15 | "node" 16 | ], 17 | "dependencies": {}, 18 | "devDependencies": { 19 | "autod": "^3.0.0", 20 | "autod-egg": "^1.0.0", 21 | "egg": "^2.0.0", 22 | "egg-bin": "^4.3.0", 23 | "egg-ci": "^1.8.0", 24 | "egg-mock": "^3.13.0", 25 | "eslint": "^4.11.0", 26 | "eslint-config-egg": "^5.1.0", 27 | "webstorm-disable-index": "^1.2.0" 28 | }, 29 | "engines": { 30 | "node": ">=8.0.0" 31 | }, 32 | "scripts": { 33 | "test": "npm run lint -- --fix && egg-bin pkgfiles && npm run test-local", 34 | "test-local": "egg-bin test", 35 | "cov": "egg-bin cov", 36 | "lint": "eslint .", 37 | "ci": "egg-bin pkgfiles --check && npm run lint && npm run cov", 38 | "pkgfiles": "egg-bin pkgfiles", 39 | "autod": "autod" 40 | }, 41 | "files": [ 42 | "config", 43 | "app.js", 44 | "lib", 45 | "index.d.ts" 46 | ], 47 | "ci": { 48 | "version": "8, 9" 49 | }, 50 | "repository": { 51 | "type": "git", 52 | "url": "git+https://github.com/zzzs/egg-router-group.git" 53 | }, 54 | "bugs": { 55 | "url": "https://github.com/zzzs/egg/issues" 56 | }, 57 | "homepage": "https://github.com/zzzs/egg-router-group#readme", 58 | "author": "xl", 59 | "license": "MIT", 60 | "types": "index.d.ts" 61 | } 62 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/controller/group.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class GroupController extends Controller { 6 | async g1() { 7 | this.ctx.status = 200; 8 | this.ctx.set('h-key', 'value'); 9 | const path = this.ctx.helper.pathFor('home1::name_g1', { bar: 'foo' }); 10 | this.ctx.set('h-path', path); 11 | } 12 | 13 | async g2() { 14 | this.ctx.status = 200; 15 | this.ctx.set('h-qid', this.ctx.params.id); 16 | this.ctx.set('h-key', 'value'); 17 | const path = this.ctx.helper.pathFor('home1::home2::name_g6', { bar: 'foo' }); 18 | this.ctx.set('h-path', path); 19 | } 20 | } 21 | 22 | module.exports = GroupController; 23 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/controller/home.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class HomeController extends Controller { 6 | async index() { 7 | this.ctx.body = 'hi, ' + this.app.plugins.routerGroup.name; 8 | } 9 | 10 | async all1() { 11 | this.ctx.status = 200; 12 | this.ctx.set('h-key', 'value'); 13 | } 14 | 15 | async all2() { 16 | this.ctx.status = 200; 17 | this.ctx.set('h-key', 'value'); 18 | const path = this.ctx.helper.pathFor('home::testname', { bar: 'foo' }); 19 | this.ctx.set('h-path', path); 20 | } 21 | 22 | async get() { 23 | this.ctx.status = 200; 24 | this.ctx.body = 'body: get'; 25 | } 26 | async post() { 27 | this.ctx.status = 200; 28 | this.ctx.body = 'body: post'; 29 | } 30 | async put() { 31 | this.ctx.status = 200; 32 | this.ctx.body = 'body: put'; 33 | } 34 | async del() { 35 | this.ctx.status = 200; 36 | this.ctx.body = 'body: del'; 37 | } 38 | async delete() { 39 | this.ctx.status = 200; 40 | this.ctx.body = 'body: delete'; 41 | } 42 | async options() { 43 | this.ctx.status = 200; 44 | this.ctx.body = 'body: options'; 45 | } 46 | async patch() { 47 | this.ctx.status = 200; 48 | this.ctx.body = 'body: patch'; 49 | } 50 | } 51 | 52 | module.exports = HomeController; 53 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/controller/middlew.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class MiddlewController extends Controller { 6 | async m1() { 7 | this.ctx.status = 200; 8 | this.ctx.set('h-key', 'value'); 9 | } 10 | 11 | async m2() { 12 | this.ctx.status = 200; 13 | this.ctx.set('h-qid', this.ctx.params.id); 14 | this.ctx.set('h-key', 'value'); 15 | } 16 | } 17 | 18 | module.exports = MiddlewController; 19 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/controller/name.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class NameController extends Controller { 6 | async n1() { 7 | this.ctx.status = 200; 8 | this.ctx.set('h-key', 'value'); 9 | const path = this.ctx.helper.pathFor('home::test_n1', { bar: 'foo' }); 10 | this.ctx.set('h-path', path); 11 | } 12 | 13 | async n2() { 14 | this.ctx.status = 200; 15 | this.ctx.set('h-qid', this.ctx.params.id); 16 | this.ctx.set('h-key', 'value'); 17 | const path = this.ctx.helper.pathFor('home::test_n2', { bar: 'foo' }); 18 | this.ctx.set('h-path', path); 19 | } 20 | } 21 | 22 | module.exports = NameController; 23 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/controller/posts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class ResourcesController extends Controller { 6 | async index() { 7 | this.ctx.body = 'post index'; 8 | const path = this.ctx.helper.pathFor('home::posts', { bar: 'foo' }); 9 | this.ctx.set('h-path', path); 10 | } 11 | 12 | async new() { 13 | const path = this.ctx.helper.pathFor('new_home::post', { bar: 'foo' }); 14 | this.ctx.set('h-path', path); 15 | this.ctx.body = 'post new'; 16 | } 17 | 18 | async show() { 19 | const path = this.ctx.helper.pathFor('home::post', { bar: 'foo' }); 20 | this.ctx.set('h-path', path); 21 | this.ctx.body = `post show ${this.ctx.params.id}`; 22 | } 23 | 24 | async edit() { 25 | const path = this.ctx.helper.pathFor('edit_home::post', { bar: 'foo' }); 26 | this.ctx.set('h-path', path); 27 | this.ctx.body = `post edit ${this.ctx.params.id}`; 28 | } 29 | 30 | async create() { 31 | this.ctx.body = 'post create'; 32 | } 33 | 34 | async update() { 35 | this.ctx.body = `post update ${this.ctx.params.id}`; 36 | } 37 | 38 | async destroy() { 39 | this.ctx.body = `post destroy ${this.ctx.params.id}`; 40 | } 41 | } 42 | 43 | module.exports = ResourcesController; 44 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/controller/prefix.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class PrefixController extends Controller { 6 | async p1() { 7 | this.ctx.status = 200; 8 | this.ctx.set('h-key', 'value'); 9 | } 10 | 11 | async p2() { 12 | this.ctx.status = 200; 13 | this.ctx.set('h-qid', this.ctx.params.id); 14 | this.ctx.set('h-key', 'value'); 15 | } 16 | } 17 | 18 | module.exports = PrefixController; 19 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/middleware/glob.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = () => { 4 | return async (ctx, next) => { 5 | ctx.set('h-global', 'h-global-value'); 6 | return await next(); 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/middleware/m1.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = () => { 4 | return async (ctx, next) => { 5 | ctx.set('h-m1', 'h-m1-value'); 6 | return await next(); 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/middleware/m2.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = options => { 4 | return async (ctx, next) => { 5 | ctx.set('h-m2', options.value); 6 | return await next(); 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/app/router.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = app => { 4 | const { router, controller, middleware } = app; 5 | const m1 = middleware.m1(); 6 | const m2 = middleware.m2({ value: 'h-m2-value' }); 7 | 8 | router.get('/', controller.home.index); 9 | 10 | // all 11 | router.group({ name: 'home::', prefix: '/pre', middlewares: m1 }, router => { 12 | router.all('/test', controller.home.all1); 13 | router.all('testname', '/test2', controller.home.all2); 14 | router.get('/get', controller.home.get).get('/get2', controller.home.get); 15 | router.post('/post', controller.home.post); 16 | router.put('/put', controller.home.put); 17 | router.delete('/delete', controller.home.delete); 18 | router.del('/del', controller.home.del); 19 | router.options('/options', controller.home.options); 20 | router.patch('/patch', controller.home.patch); 21 | router.redirect('/redirect', '/'); 22 | router.redirect('/redirect2', 'home::testname', 302); 23 | }).get('/get3', m2, controller.home.get); 24 | 25 | // resources 26 | // https://eggjs.org/zh-cn/basics/router.html 27 | router.group({ name: 'home::', prefix: '/pre', middlewares: m1 }, router => { 28 | router.resources('posts', '/api/posts', controller.posts); 29 | }); 30 | 31 | // name 32 | router.group({ name: 'home::' }, router => { 33 | router.get('test_n1', '/test_n1', controller.name.n1); 34 | router.post('test_n2', '/test_n2/:id', controller.name.n2); 35 | }); 36 | 37 | // prefix 38 | router.group({ prefix: '/pre' }, router => { 39 | router.get('test_p1', '/test_p1', controller.prefix.p1); 40 | router.post('test_p2', '/test_p2/:id', controller.prefix.p2); 41 | }); 42 | 43 | // middlewares 44 | router.group({ middlewares: [ m1, m2 ] }, router => { 45 | router.get('/test_m1', controller.middlew.m1); 46 | router.post('/test_m2/:id', controller.middlew.m2); 47 | }); 48 | router.group({ middlewares: m1 }, router => { 49 | router.get('/test_m3', m2, controller.middlew.m1); 50 | router.post('/test_m4/:id', controller.middlew.m2); 51 | }); 52 | 53 | // group 54 | router.group({ name: 'home1::', prefix: '/pre1', middlewares: m1 }, router => { 55 | router.get('name_g1', '/test_g1', m2, controller.group.g1); 56 | router.post('/test_g2/:id', controller.group.g2); 57 | 58 | router.group({ prefix: '/pre2', middlewares: m2 }, router => { 59 | router.get('/test_g3', m2, controller.group.g1); 60 | router.post('/test_g4/:id', controller.group.g2); 61 | 62 | router.group({ name: 'home2::' }, router => { 63 | router.get('/test_g5', m2, controller.group.g1).get('/test_g5_1', controller.group.g1); 64 | router.post('name_g6', '/test_g6/:id', controller.group.g2); 65 | }); 66 | }) 67 | .get('/test_g2_1', controller.group.g1); 68 | }); 69 | 70 | router.group({ name: 'home1::', prefix: '/pre1' }, router => { 71 | router.group({ prefix: '/pre2', middlewares: [ m1 ] }, router => { 72 | router.get('/test_g7', controller.group.g1); 73 | router.group({ name: 'home2::', middlewares: m2 }, router => { 74 | router.get('/test_g8', controller.group.g1); 75 | }); 76 | }); 77 | }); 78 | }; 79 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/config/config.default.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.keys = '123456'; 4 | 5 | exports.security = { 6 | methodnoallow: false, 7 | }; 8 | 9 | exports.middleware = [ 'glob' ]; 10 | -------------------------------------------------------------------------------- /test/fixtures/apps/router-group-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "router-group-test", 3 | "version": "0.0.1" 4 | } -------------------------------------------------------------------------------- /test/router-group.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mock = require('egg-mock'); 4 | const assert = require('assert'); 5 | 6 | describe('test/router-group.test.js', () => { 7 | let app; 8 | before(() => { 9 | app = mock.app({ 10 | baseDir: 'apps/router-group-test', 11 | }); 12 | return app.ready(); 13 | }); 14 | 15 | beforeEach(() => app.mockCsrf()); 16 | after(() => app.close()); 17 | afterEach(mock.restore); 18 | 19 | it('should GET /', () => { 20 | return app.httpRequest() 21 | .get('/') 22 | .expect('hi, routerGroup') 23 | .expect(200); 24 | }); 25 | 26 | describe('case: exception', () => { 27 | it('name must be string', () => { 28 | try { 29 | app.router.group({ name: /^test\/.*/, prefix: '/pre', middlewares: [] }, router => { 30 | router.get('/test', app.controller.home.all1); 31 | }); 32 | throw new Error('another exception'); 33 | } catch (err) { 34 | assert(err.message.includes('name must be string, but got')); 35 | } 36 | }); 37 | 38 | it('prefix must be string', () => { 39 | try { 40 | app.router.group({ name: 'home::', prefix: /^test\/.*/, middlewares: [] }, router => { 41 | router.get('/test', app.controller.home.all1); 42 | }); 43 | throw new Error('another exception'); 44 | } catch (err) { 45 | assert(err.message.includes('prefix must be string, but got')); 46 | } 47 | }); 48 | 49 | it('middlewares must be function or array', () => { 50 | try { 51 | app.router.group({ name: 'home::', prefix: '/pre', middlewares: 'hhh' }, router => { 52 | router.get('/test', app.controller.home.all1); 53 | }); 54 | throw new Error('another exception'); 55 | } catch (err) { 56 | assert(err.message.includes('middlewares must be function or array, but got')); 57 | } 58 | }); 59 | 60 | it('router-name must be string', () => { 61 | try { 62 | app.router.group({ name: 'home::', prefix: '/pre' }, router => { 63 | router.get(/^test\/.*/, '/test', app.controller.home.all1); 64 | }); 65 | throw new Error('another exception'); 66 | } catch (err) { 67 | assert(err.message.includes('router-name must be string, but got')); 68 | } 69 | }); 70 | 71 | it('router-path must be string', () => { 72 | try { 73 | app.router.group({ name: 'home::', prefix: '/pre' }, router => { 74 | router.get('home::', /^test\/.*/, app.controller.home.all1); 75 | }); 76 | throw new Error('another exception'); 77 | } catch (err) { 78 | assert(err.message.includes('router-path must be string, but got')); 79 | } 80 | }); 81 | }); 82 | 83 | describe('case: all', () => { 84 | it('should GET /pre/test', () => { 85 | return app.httpRequest() 86 | .get('/pre/test') 87 | .expect('h-m1', 'h-m1-value') 88 | .expect('h-global', 'h-global-value') 89 | .expect('h-key', 'value') 90 | .expect(200); 91 | }); 92 | 93 | it('should POST /pre/test', () => { 94 | return app.httpRequest() 95 | .post('/pre/test') 96 | .expect('h-m1', 'h-m1-value') 97 | .expect('h-global', 'h-global-value') 98 | .expect('h-key', 'value') 99 | .expect(200); 100 | }); 101 | 102 | it('should PUT /pre/test', () => { 103 | return app.httpRequest() 104 | .put('/pre/test') 105 | .expect('h-m1', 'h-m1-value') 106 | .expect('h-global', 'h-global-value') 107 | .expect('h-key', 'value') 108 | .expect(200); 109 | }); 110 | 111 | it('should DELETE /pre/test', () => { 112 | return app.httpRequest() 113 | .delete('/pre/test') 114 | .expect('h-m1', 'h-m1-value') 115 | .expect('h-global', 'h-global-value') 116 | .expect('h-key', 'value') 117 | .expect(200); 118 | }); 119 | 120 | it('should GET /pre/test2', () => { 121 | return app.httpRequest() 122 | .get('/pre/test2') 123 | .expect('h-m1', 'h-m1-value') 124 | .expect('h-key', 'value') 125 | .expect('h-path', '/pre/test2?bar=foo') 126 | .expect(200); 127 | }); 128 | 129 | it('should POST /pre/test2', () => { 130 | return app.httpRequest() 131 | .post('/pre/test2') 132 | .expect('h-m1', 'h-m1-value') 133 | .expect('h-key', 'value') 134 | .expect('h-path', '/pre/test2?bar=foo') 135 | .expect(200); 136 | }); 137 | 138 | it('should PUT /pre/test2', () => { 139 | return app.httpRequest() 140 | .put('/pre/test2') 141 | .expect('h-m1', 'h-m1-value') 142 | .expect('h-key', 'value') 143 | .expect('h-path', '/pre/test2?bar=foo') 144 | .expect(200); 145 | }); 146 | 147 | it('should DELETE /pre/test2', () => { 148 | return app.httpRequest() 149 | .delete('/pre/test2') 150 | .expect('h-m1', 'h-m1-value') 151 | .expect('h-key', 'value') 152 | .expect('h-path', '/pre/test2?bar=foo') 153 | .expect(200); 154 | }); 155 | 156 | it('should GET /pre/get', () => { 157 | return app.httpRequest() 158 | .get('/pre/get') 159 | .expect('h-m1', 'h-m1-value') 160 | .expect('body: get') 161 | .expect(200); 162 | }); 163 | 164 | it('should GET /pre/get2', () => { 165 | return app.httpRequest() 166 | .get('/pre/get2') 167 | .expect('h-m1', 'h-m1-value') 168 | .expect('body: get') 169 | .expect(200); 170 | }); 171 | 172 | it('should GET /get3', () => { 173 | return app.httpRequest() 174 | .get('/get3') 175 | .expect('h-m2', 'h-m2-value') 176 | .expect('body: get') 177 | .expect(200); 178 | }); 179 | 180 | it('should POST /pre/post', () => { 181 | return app.httpRequest() 182 | .post('/pre/post') 183 | .expect('h-m1', 'h-m1-value') 184 | .expect('body: post') 185 | .expect(200); 186 | }); 187 | 188 | it('should PUT /pre/put', () => { 189 | return app.httpRequest() 190 | .put('/pre/put') 191 | .expect('h-m1', 'h-m1-value') 192 | .expect('body: put') 193 | .expect(200); 194 | }); 195 | 196 | it('should DELETE /pre/delete', () => { 197 | return app.httpRequest() 198 | .delete('/pre/delete') 199 | .expect('h-m1', 'h-m1-value') 200 | .expect('body: delete') 201 | .expect(200); 202 | }); 203 | 204 | it('should DEL /pre/del', () => { 205 | return app.httpRequest() 206 | .del('/pre/del') 207 | .expect('h-m1', 'h-m1-value') 208 | .expect('body: del') 209 | .expect(200); 210 | }); 211 | 212 | it('should OPTIONS /pre/options', () => { 213 | return app.httpRequest() 214 | .options('/pre/options') 215 | .expect('h-m1', 'h-m1-value') 216 | .expect('body: options') 217 | .expect(200); 218 | }); 219 | 220 | it('should PATCH /pre/patch', () => { 221 | return app.httpRequest() 222 | .patch('/pre/patch') 223 | .expect('h-m1', 'h-m1-value') 224 | .expect('body: patch') 225 | .expect(200); 226 | }); 227 | 228 | it('should REDIRECT /pre/redirect', () => { 229 | return app.httpRequest() 230 | .get('/pre/redirect') 231 | .expect(301) 232 | .expect('location', '/'); 233 | }); 234 | 235 | it('should REDIRECT /pre/redirect2 to router-name', () => { 236 | return app.httpRequest() 237 | .get('/pre/redirect2') 238 | .expect(302) 239 | .expect('location', '/pre/test2'); 240 | }); 241 | }); 242 | 243 | describe('case: resource', () => { 244 | it('should GET /pre/api/posts', () => { 245 | return app.httpRequest() 246 | .get('/pre/api/posts') 247 | .expect('h-path', '/pre/api/posts?bar=foo') 248 | .expect('h-m1', 'h-m1-value') 249 | .expect('post index') 250 | .expect(200); 251 | }); 252 | 253 | it('should GET /pre/api/posts/new', () => { 254 | return app.httpRequest() 255 | .get('/pre/api/posts/new') 256 | .expect('h-path', '/pre/api/posts/new?bar=foo') 257 | .expect('h-m1', 'h-m1-value') 258 | .expect('post new') 259 | .expect(200); 260 | }); 261 | 262 | it('should GET /pre/api/posts/1', () => { 263 | return app.httpRequest() 264 | .get('/pre/api/posts/1') 265 | .expect('h-path', '/pre/api/posts/:id?bar=foo') 266 | .expect('h-m1', 'h-m1-value') 267 | .expect('post show 1') 268 | .expect(200); 269 | }); 270 | 271 | it('should GET /pre/api/posts/1/edit', () => { 272 | return app.httpRequest() 273 | .get('/pre/api/posts/1/edit') 274 | .expect('h-path', '/pre/api/posts/:id/edit?bar=foo') 275 | .expect('h-m1', 'h-m1-value') 276 | .expect('post edit 1') 277 | .expect(200); 278 | }); 279 | 280 | it('should POST /pre/api/posts', () => { 281 | return app.httpRequest() 282 | .post('/pre/api/posts') 283 | .expect('h-m1', 'h-m1-value') 284 | .expect('post create') 285 | .expect(200); 286 | }); 287 | 288 | it('should PUT /pre/api/posts/1', () => { 289 | return app.httpRequest() 290 | .put('/pre/api/posts/1') 291 | .expect('h-m1', 'h-m1-value') 292 | .expect('post update 1') 293 | .expect(200); 294 | }); 295 | 296 | it('should DELETE /pre/api/posts/1', () => { 297 | return app.httpRequest() 298 | .delete('/pre/api/posts/1') 299 | .expect('h-m1', 'h-m1-value') 300 | .expect('post destroy 1') 301 | .expect(200); 302 | }); 303 | }); 304 | 305 | describe('case: name', () => { 306 | it('should GET /test_n1', () => { 307 | return app.httpRequest() 308 | .get('/test_n1') 309 | .expect('h-path', '/test_n1?bar=foo') 310 | .expect('h-key', 'value') 311 | .expect(200); 312 | }); 313 | 314 | it('should GET /test_n1', () => { 315 | return app.httpRequest() 316 | .get('/test_n1') 317 | .expect('h-path', '/test_n1?bar=foo') 318 | .expect('h-key', 'value') 319 | .expect(200); 320 | }); 321 | 322 | it('should POST /test_m2', () => { 323 | return app.httpRequest() 324 | .post('/test_n2/123') 325 | .expect('h-path', '/test_n2/:id?bar=foo') 326 | .expect('h-key', 'value') 327 | .expect('h-qid', '123') 328 | .expect(200); 329 | }); 330 | }); 331 | 332 | describe('case: prefix', () => { 333 | it('should GET /pre/test_p1', () => { 334 | return app.httpRequest() 335 | .get('/pre/test_p1') 336 | .expect('h-key', 'value') 337 | .expect(200); 338 | }); 339 | 340 | it('should POST /pre/test_m2', () => { 341 | return app.httpRequest() 342 | .post('/pre/test_p2/123') 343 | .expect('h-key', 'value') 344 | .expect('h-qid', '123') 345 | .expect(200); 346 | }); 347 | }); 348 | 349 | describe('case: middlename', () => { 350 | it('should GET /test_m1', () => { 351 | return app.httpRequest() 352 | .get('/test_m1') 353 | .expect('h-m1', 'h-m1-value') 354 | .expect('h-m2', 'h-m2-value') 355 | .expect('h-key', 'value') 356 | .expect(200); 357 | }); 358 | 359 | it('should POST /test_m2', () => { 360 | return app.httpRequest() 361 | .post('/test_m2/123') 362 | .expect('h-m1', 'h-m1-value') 363 | .expect('h-m2', 'h-m2-value') 364 | .expect('h-key', 'value') 365 | .expect('h-qid', '123') 366 | .expect(200); 367 | }); 368 | 369 | it('should GET /test_m3', () => { 370 | return app.httpRequest() 371 | .get('/test_m3') 372 | .expect('h-m1', 'h-m1-value') 373 | .expect('h-m2', 'h-m2-value') 374 | .expect('h-key', 'value') 375 | .expect(200); 376 | }); 377 | 378 | it('should POST /test_m4', () => { 379 | return app.httpRequest() 380 | .post('/test_m4/123') 381 | .expect('h-m1', 'h-m1-value') 382 | .expect('h-key', 'value') 383 | .expect('h-qid', '123') 384 | .expect(200); 385 | }); 386 | }); 387 | 388 | describe('case: group', () => { 389 | it('should GET /pre1/test_g1', () => { 390 | return app.httpRequest() 391 | .get('/pre1/test_g1') 392 | .expect('h-m1', 'h-m1-value') 393 | .expect('h-m2', 'h-m2-value') 394 | .expect('h-key', 'value') 395 | .expect('h-path', '/pre1/test_g1?bar=foo') 396 | .expect(200); 397 | }); 398 | 399 | it('should POST /pre1/test_g2', () => { 400 | return app.httpRequest() 401 | .post('/pre1/test_g2/123') 402 | .expect('h-m1', 'h-m1-value') 403 | .expect('h-key', 'value') 404 | .expect('h-qid', '123') 405 | .expect(200); 406 | }); 407 | 408 | it('should GET /pre1/pre2/test_g3', () => { 409 | return app.httpRequest() 410 | .get('/pre1/pre2/test_g3') 411 | .expect('h-m1', 'h-m1-value') 412 | .expect('h-m2', 'h-m2-value') 413 | .expect('h-key', 'value') 414 | .expect(200); 415 | }); 416 | 417 | it('should GET /pre1/test_g2_1', () => { 418 | return app.httpRequest() 419 | .get('/pre1/test_g2_1') 420 | .expect('h-m1', 'h-m1-value') 421 | .expect('h-key', 'value') 422 | .expect(200); 423 | }); 424 | 425 | it('should POST /pre1/pre2/test_g4', () => { 426 | return app.httpRequest() 427 | .post('/pre1/pre2/test_g4/123') 428 | .expect('h-m1', 'h-m1-value') 429 | .expect('h-m2', 'h-m2-value') 430 | .expect('h-key', 'value') 431 | .expect('h-qid', '123') 432 | .expect(200); 433 | }); 434 | 435 | it('should GET /pre1/pre2/test_g5', () => { 436 | return app.httpRequest() 437 | .get('/pre1/pre2/test_g5') 438 | .expect('h-m1', 'h-m1-value') 439 | .expect('h-m2', 'h-m2-value') 440 | .expect('h-key', 'value') 441 | .expect(200); 442 | }); 443 | 444 | it('should GET /pre1/pre2/test_g5_1', () => { 445 | return app.httpRequest() 446 | .get('/pre1/pre2/test_g5_1') 447 | .expect('h-m1', 'h-m1-value') 448 | .expect('h-m2', 'h-m2-value') 449 | .expect('h-key', 'value') 450 | .expect(200); 451 | }); 452 | 453 | it('should POST /pre1/pre2/test_g6', () => { 454 | return app.httpRequest() 455 | .post('/pre1/pre2/test_g6/123') 456 | .expect('h-m1', 'h-m1-value') 457 | .expect('h-m2', 'h-m2-value') 458 | .expect('h-key', 'value') 459 | .expect('h-qid', '123') 460 | .expect('h-path', '/pre1/pre2/test_g6/:id?bar=foo') 461 | .expect(200); 462 | }); 463 | 464 | it('should POST /pre1/pre2/test_g7', () => { 465 | return app.httpRequest() 466 | .get('/pre1/pre2/test_g7') 467 | .expect('h-m1', 'h-m1-value') 468 | .expect('h-key', 'value') 469 | .expect(200); 470 | }); 471 | 472 | it('should POST /pre1/pre2/test_g8', () => { 473 | return app.httpRequest() 474 | .get('/pre1/pre2/test_g8') 475 | .expect('h-m1', 'h-m1-value') 476 | .expect('h-m2', 'h-m2-value') 477 | .expect('h-key', 'value') 478 | .expect(200); 479 | }); 480 | }); 481 | 482 | }); 483 | --------------------------------------------------------------------------------