shihuojian commited on
Commit
adae8b1
·
1 Parent(s): de10cbd

update rate-limit

Browse files
ndcc/server/index.js CHANGED
@@ -599,7 +599,7 @@ module.exports = async (app) =>{
599
  }
600
  },
601
  {
602
- plugin:require('./plugins/rateLimit.js'), //upload
603
  options:{}
604
  },
605
  {
 
599
  }
600
  },
601
  {
602
+ plugin:require('./plugins/rateLimit/index.js'), //upload
603
  options:{}
604
  },
605
  {
ndcc/server/lib/index.js CHANGED
@@ -136,8 +136,12 @@ exports.plugin = {
136
  path: '/test',
137
  options:{
138
  plugins:{
139
- 'hapi-rate-limit': {
140
- enabled: false
 
 
 
 
141
  }
142
  }
143
  },
@@ -226,7 +230,7 @@ exports.plugin = {
226
  server.route({
227
  method: 'GET',
228
  path: '/_next/{p*}',
229
- options:{plugins: {'hapi-rate-limit': {enabled: false } }},
230
  handler: async ({raw},h)=>{
231
  await handler(raw.req,raw.res);
232
  if (raw.res.headersSent) { return h.close;}
@@ -238,7 +242,7 @@ exports.plugin = {
238
  server.route({
239
  method: 'GET',
240
  path: '/pwa/{p*}',
241
- options:{plugins: {'hapi-rate-limit': { enabled: false}}},
242
  handler: async ({ url}, h) => {
243
  try {
244
  let pathname = url.pathname;
@@ -257,7 +261,7 @@ exports.plugin = {
257
  server.route({
258
  method: 'GET',
259
  path: '/sw.js',
260
- options:{plugins: {'hapi-rate-limit': { enabled: false}}},
261
  handler: async ({ url}, h) => {
262
  try {
263
  let pathname = url.pathname;
@@ -615,10 +619,10 @@ exports.plugin = {
615
  auth: 'auth',
616
  plugins: {
617
  //限制用户每5s只能上传一次
618
- "hapi-rate-limit": {
619
  "userPathLimit":Number(uploadRequestsPerSecond.split('/')[0]),
620
  "userPathCache":{
621
- "segment":`hapi-rate-limit-user-upload-${server.info.port}`,
622
  "expiresIn":Number(uploadRequestsPerSecond.split('/')[1])
623
  }
624
  }
 
136
  path: '/test',
137
  options:{
138
  plugins:{
139
+ 'rate-limit': {
140
+ "userPathLimit":1,
141
+ "userPathCache":{
142
+ "segment":"ZhIWjVHdVLruss7eFn",
143
+ "expiresIn":1000
144
+ }
145
  }
146
  }
147
  },
 
230
  server.route({
231
  method: 'GET',
232
  path: '/_next/{p*}',
233
+ options:{plugins: {'rate-limit': {enabled: false } }},
234
  handler: async ({raw},h)=>{
235
  await handler(raw.req,raw.res);
236
  if (raw.res.headersSent) { return h.close;}
 
242
  server.route({
243
  method: 'GET',
244
  path: '/pwa/{p*}',
245
+ options:{plugins: {'rate-limit': { enabled: false}}},
246
  handler: async ({ url}, h) => {
247
  try {
248
  let pathname = url.pathname;
 
261
  server.route({
262
  method: 'GET',
263
  path: '/sw.js',
264
+ options:{plugins: {'rate-limit': { enabled: false}}},
265
  handler: async ({ url}, h) => {
266
  try {
267
  let pathname = url.pathname;
 
619
  auth: 'auth',
620
  plugins: {
621
  //限制用户每5s只能上传一次
622
+ "rate-limit": {
623
  "userPathLimit":Number(uploadRequestsPerSecond.split('/')[0]),
624
  "userPathCache":{
625
+ "segment":`rate-limit-user-upload-${server.info.port}`,
626
  "expiresIn":Number(uploadRequestsPerSecond.split('/')[1])
627
  }
628
  }
ndcc/server/plugins/{rateLimit.js → rateLimit/index.js} RENAMED
@@ -1,6 +1,6 @@
1
 
2
  'use strict';
3
- const {Error} = require('../lib/think');
4
  exports.plugin = {
5
  pkg: {
6
  "name": "rateLimit",
@@ -9,8 +9,7 @@ exports.plugin = {
9
  register: async function (server, options) {
10
  const {requestsPerSecond} = server.settings.app.systemConfig.Config
11
 
12
- //使用的hapi-rate-limit插件,再次封装而已 参考 https://www.npmjs.com/package/hapi-rate-limit
13
- const pkgName = "hapi-rate-limit"
14
  await server.ext('onPreAuth', function (request, h) {
15
  // if(request.route.path === "/api/{action*}"){
16
  // // console.log(requestsPerSecond,'============')
@@ -19,10 +18,10 @@ exports.plugin = {
19
  //无需单独写,后台路由配置直接覆盖即可,参考
20
  // "options":{
21
  // "plugins": {
22
- // "hapi-rate-limit": {
23
  // "userPathLimit":1,
24
  // "userPathCache":{
25
- // "segment":"ZhIWjVHdVLru7eFn", //填写路由id就行了
26
  // "expiresIn":1000 //过期时间
27
  // }
28
  // }
@@ -34,7 +33,7 @@ exports.plugin = {
34
  });
35
 
36
  await server.register({
37
- plugin:require('hapi-rate-limit'),
38
  options: {
39
  enabled:true,
40
  trustProxy:true,
@@ -42,7 +41,7 @@ exports.plugin = {
42
  userPathLimit:false, //每个用户每个时间段在给定路径上可以发出的请求总数
43
  userLimit:Number(requestsPerSecond.split('/')[0]), //用户每个时间段可以发出的总请求数
44
  userCache:{
45
- segment:`hapi-rate-limit-user-${server.info.port}`,
46
  expiresIn:Number(requestsPerSecond.split('/')[1])
47
  },
48
  }
 
1
 
2
  'use strict';
3
+ const {Error} = require('../../lib/think');
4
  exports.plugin = {
5
  pkg: {
6
  "name": "rateLimit",
 
9
  register: async function (server, options) {
10
  const {requestsPerSecond} = server.settings.app.systemConfig.Config
11
 
12
+ //使用的hapi-rate-limit插件,再次封装而已,pak name吸修改为rate-limit 参考 https://www.npmjs.com/package/rate-limit
 
13
  await server.ext('onPreAuth', function (request, h) {
14
  // if(request.route.path === "/api/{action*}"){
15
  // // console.log(requestsPerSecond,'============')
 
18
  //无需单独写,后台路由配置直接覆盖即可,参考
19
  // "options":{
20
  // "plugins": {
21
+ // "rate-limit": {
22
  // "userPathLimit":1,
23
  // "userPathCache":{
24
+ // "segment":"ZhIWjVHdVLru7eFn", //填写路由id就行了
25
  // "expiresIn":1000 //过期时间
26
  // }
27
  // }
 
33
  });
34
 
35
  await server.register({
36
+ plugin:require('./lib/index'),
37
  options: {
38
  enabled:true,
39
  trustProxy:true,
 
41
  userPathLimit:false, //每个用户每个时间段在给定路径上可以发出的请求总数
42
  userLimit:Number(requestsPerSecond.split('/')[0]), //用户每个时间段可以发出的总请求数
43
  userCache:{
44
+ segment:`ndcc-rate-limit-user-${server.info.port}`,
45
  expiresIn:Number(requestsPerSecond.split('/')[1])
46
  },
47
  }
ndcc/server/plugins/rateLimit/lib/index.js ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict'
2
+
3
+ const Joi = require('joi')
4
+ const Pkg = {
5
+ name:"rate-limit"
6
+ }
7
+
8
+ const internals = require('./internals')
9
+
10
+ const register = function (plugin, options) {
11
+ const pluginSettings = Joi.attempt(Object.assign({}, options), internals.schema)
12
+
13
+ // we call toString on the user attribute in getUser, so we have to do it here too.
14
+ pluginSettings.userWhitelist = pluginSettings.userWhitelist.map(user => user.toString())
15
+
16
+ const userCache = plugin.cache(pluginSettings.userCache)
17
+ const pathCache = plugin.cache(pluginSettings.pathCache)
18
+ const userPathCache = plugin.cache(pluginSettings.userPathCache)
19
+ const authCache = plugin.cache(pluginSettings.authCache)
20
+
21
+ // called regardless if authentication is performed, before authentication is performed
22
+ plugin.ext('onPreAuth', async (request, h) => {
23
+ const routeSettings = request.route.settings.plugins[internals.pluginName] || {}
24
+
25
+ delete routeSettings.userCache
26
+
27
+ if (routeSettings.userLimit !== false) {
28
+ delete routeSettings.userLimit
29
+ }
30
+
31
+ const settings = { ...pluginSettings, ...routeSettings }
32
+
33
+ request.plugins[internals.pluginName] = { settings }
34
+
35
+ if (settings.enabled === false) {
36
+ return h.continue
37
+ }
38
+
39
+ const remaining = await internals.authCheck(authCache, request)
40
+
41
+ if (remaining < 0) {
42
+ return settings.limitExceededResponse(request, h)
43
+ }
44
+
45
+ return h.continue
46
+ })
47
+
48
+ // called regardless if authentication is performed, but not if authentication fails
49
+ plugin.ext('onPostAuth', async (request, h) => {
50
+ const { settings } = request.plugins[internals.pluginName]
51
+
52
+ if (settings.enabled === false) {
53
+ return h.continue
54
+ }
55
+
56
+ const remaining = await Promise.all([
57
+ internals.userCheck(userCache, request),
58
+ internals.userPathCheck(userPathCache, request),
59
+ internals.pathCheck(pathCache, request)
60
+ ])
61
+
62
+ if (remaining.some(r => r < 0)) {
63
+ return settings.limitExceededResponse(request, h)
64
+ }
65
+
66
+ return h.continue
67
+ })
68
+
69
+ // always called, unless the request is aborted
70
+ plugin.ext('onPreResponse', async (request, h) => {
71
+ const requestPlugin = request.plugins[internals.pluginName]
72
+
73
+ if (!requestPlugin) {
74
+ // We never even made it to onPreAuth
75
+ return h.continue
76
+ }
77
+
78
+ const { response } = request
79
+
80
+ // Non 401s can include authToken in their data and if it's there it counts
81
+ if (response.isBoom) {
82
+ await internals.authFailure(authCache, request)
83
+ }
84
+
85
+ const { settings } = requestPlugin
86
+
87
+ if (settings.headers !== false) {
88
+ let headers = response.headers
89
+
90
+ if (response.isBoom) {
91
+ headers = response.output.headers
92
+ }
93
+
94
+ if (settings.pathLimit !== false) {
95
+ headers['X-RateLimit-PathLimit'] = requestPlugin.pathLimit
96
+ headers['X-RateLimit-PathRemaining'] = requestPlugin.pathRemaining
97
+ headers['X-RateLimit-PathReset'] = requestPlugin.pathReset
98
+ }
99
+
100
+ if (settings.userPathLimit !== false) {
101
+ headers['X-RateLimit-UserPathLimit'] = requestPlugin.userPathLimit
102
+ headers['X-RateLimit-UserPathRemaining'] = requestPlugin.userPathRemaining
103
+ headers['X-RateLimit-UserPathReset'] = requestPlugin.userPathReset
104
+ }
105
+
106
+ if (settings.userLimit !== false) {
107
+ headers['X-RateLimit-UserLimit'] = requestPlugin.userLimit
108
+ headers['X-RateLimit-UserRemaining'] = requestPlugin.userRemaining
109
+ headers['X-RateLimit-UserReset'] = requestPlugin.userReset
110
+ }
111
+ }
112
+
113
+ return h.continue
114
+ })
115
+ }
116
+
117
+ module.exports = {
118
+ register,
119
+ pkg: Pkg
120
+ }
ndcc/server/plugins/rateLimit/lib/internals.js ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const Crypto = require('crypto')
2
+ const Boom = require('@hapi/boom')
3
+ const Hoek = require('@hapi/hoek')
4
+ const Joi = require('joi')
5
+
6
+ const pluginName = 'rate-limit'
7
+
8
+ const schema = Joi.object({
9
+ enabled: Joi.boolean().default(true),
10
+ addressOnly: Joi.boolean().default(false),
11
+ headers: Joi.boolean().default(true),
12
+ ipWhitelist: Joi.array().default([]),
13
+ authCache: Joi.object({
14
+ getDecoratedValue: Joi.boolean().default(true),
15
+ cache: Joi.string().optional(),
16
+ segment: Joi.string().default(`${pluginName}-auth`),
17
+ expiresIn: Joi.number().default(1 * 60 * 1000) // 1 minute
18
+ }).default(),
19
+ authToken: Joi.string().default('authToken'),
20
+ authLimit: Joi.alternatives()
21
+ .try(Joi.boolean(), Joi.number())
22
+ .default(5),
23
+ pathCache: Joi.object({
24
+ getDecoratedValue: Joi.boolean().default(true),
25
+ cache: Joi.string().optional(),
26
+ segment: Joi.string().default(`${pluginName}-path`),
27
+ expiresIn: Joi.number().default(1 * 60 * 1000) // 1 minute
28
+ }).default(),
29
+ pathLimit: Joi.alternatives()
30
+ .try(Joi.boolean(), Joi.number())
31
+ .default(50),
32
+ ignorePathParams: Joi.boolean().default(false),
33
+ trustProxy: Joi.boolean().default(false),
34
+ getIpFromProxyHeader: Joi.func().default(null),
35
+ proxyHeaderName: Joi.string().default('x-forwarded-for'),
36
+ userAttribute: Joi.string().default('id'),
37
+ userCache: Joi.object({
38
+ getDecoratedValue: Joi.boolean().default(true),
39
+ cache: Joi.string().optional(),
40
+ segment: Joi.string().default(`${pluginName}-user`),
41
+ expiresIn: Joi.number().default(10 * 60 * 1000) // 10 minutes
42
+ }).default(),
43
+ userLimit: Joi.alternatives()
44
+ .try(Joi.boolean(), Joi.number())
45
+ .default(300),
46
+ userWhitelist: Joi.array().default([]),
47
+ userPathCache: Joi.object({
48
+ getDecoratedValue: Joi.boolean().default(true),
49
+ cache: Joi.string().optional(),
50
+ segment: Joi.string().default(`${pluginName}-userPath`),
51
+ expiresIn: Joi.number().default(1 * 60 * 1000) // 1 minute
52
+ }).default(),
53
+ userPathLimit: Joi.alternatives()
54
+ .try(Joi.boolean(), Joi.number())
55
+ .default(false),
56
+ limitExceededResponse: Joi.func().default(() => {
57
+ return limitExceededResponse
58
+ })
59
+ })
60
+
61
+ function getUser (request, settings) {
62
+ if (request.auth.isAuthenticated) {
63
+ const user = Hoek.reach(request.auth.credentials, settings.userAttribute)
64
+ if (user !== undefined) {
65
+ return user.toString()
66
+ }
67
+ }
68
+ }
69
+
70
+ function getIP (request, settings) {
71
+ let ip
72
+
73
+ if (settings.trustProxy && request.headers[settings.proxyHeaderName]) {
74
+ if (settings.getIpFromProxyHeader) {
75
+ ip = settings.getIpFromProxyHeader(request.headers[settings.proxyHeaderName])
76
+ } else {
77
+ const ips = request.headers[settings.proxyHeaderName].split(',')
78
+ ip = ips[0]
79
+ }
80
+ }
81
+
82
+ if (ip === undefined) {
83
+ ip = request.info.remoteAddress
84
+ }
85
+
86
+ return ip
87
+ }
88
+
89
+ async function authFailure (authCache, request) {
90
+ const requestPlugin = request.plugins[pluginName]
91
+ const settings = requestPlugin.settings
92
+ if (settings.authLimit === false) {
93
+ return
94
+ }
95
+
96
+ const ip = getIP(request, settings)
97
+
98
+ const { value, cached } = await authCache.get(ip)
99
+
100
+ let token
101
+
102
+ token = Hoek.reach(request, `auth.artifacts.${settings.authToken}`)
103
+
104
+ if (!token) {
105
+ token = Hoek.reach(request, `auth.error.data.${settings.authToken}`)
106
+ }
107
+
108
+ if (!token) {
109
+ return
110
+ }
111
+
112
+ const tokenHash = Crypto.createHash('sha1')
113
+ .update(token)
114
+ .digest('hex')
115
+ .slice(0, 6)
116
+
117
+ let tokens
118
+ let ttl = settings.userPathCache.expiresIn
119
+
120
+ /* $lab:coverage:off$ */
121
+ if (value === null || cached.isStale) {
122
+ /* $lab:coverage:on$ */
123
+ tokens = new Set([tokenHash])
124
+ } else {
125
+ ttl = cached.ttl
126
+ tokens = new Set([...value, tokenHash])
127
+ }
128
+
129
+ // Sets don't stringify so we cast to an array before storing in the cache
130
+ await authCache.set(ip, Array.from(tokens), ttl)
131
+ }
132
+
133
+ async function authCheck (authCache, request) {
134
+ const requestPlugin = request.plugins[pluginName]
135
+ const settings = requestPlugin.settings
136
+ if (settings.authLimit === false) {
137
+ requestPlugin.authLimit = false
138
+ return
139
+ }
140
+
141
+ const ip = getIP(request, settings)
142
+ const { value, cached } = await authCache.get(ip)
143
+
144
+ /* $lab:coverage:off$ */
145
+ if (value === null || cached.isStale) {
146
+ /* $lab:coverage:on$ */
147
+ return
148
+ }
149
+
150
+ const badIps = new Set(value)
151
+ const remaining = settings.authLimit - badIps.size
152
+
153
+ return remaining
154
+ }
155
+
156
+ async function pathCheck (pathCache, request) {
157
+ const requestPlugin = request.plugins[pluginName]
158
+ const settings = requestPlugin.settings
159
+ const path = settings.ignorePathParams ? request.route.path : request.path
160
+
161
+ if (settings.pathLimit === false) {
162
+ requestPlugin.pathLimit = false
163
+ return
164
+ }
165
+
166
+ const { value, cached } = await pathCache.get(path)
167
+ let count
168
+ let ttl = settings.pathCache.expiresIn
169
+
170
+ /* $lab:coverage:off$ */
171
+ if (value === null || cached.isStale) {
172
+ /* $lab:coverage:on$ */
173
+ count = 1
174
+ } else {
175
+ count = value + 1
176
+ ttl = cached.ttl
177
+ }
178
+
179
+ let remaining = settings.pathLimit - count
180
+ if (remaining < 0) {
181
+ remaining = -1
182
+ }
183
+
184
+ await pathCache.set(path, count, ttl)
185
+
186
+ requestPlugin.pathLimit = settings.pathLimit
187
+ requestPlugin.pathRemaining = remaining
188
+ requestPlugin.pathReset = Date.now() + ttl
189
+
190
+ return remaining
191
+ }
192
+
193
+ async function userCheck (userCache, request) {
194
+ const requestPlugin = request.plugins[pluginName]
195
+ const settings = requestPlugin.settings
196
+ const ip = getIP(request, settings)
197
+ let user = getUser(request, settings)
198
+ if (
199
+ settings.ipWhitelist.indexOf(ip) > -1 ||
200
+ (user && settings.userWhitelist.indexOf(user) > -1) ||
201
+ settings.userLimit === false
202
+ ) {
203
+ requestPlugin.userLimit = false
204
+ return
205
+ }
206
+
207
+ if (settings.addressOnly || user === undefined) {
208
+ user = ip
209
+ }
210
+
211
+ const { value, cached } = await userCache.get(user)
212
+
213
+ let count
214
+ let ttl = settings.userCache.expiresIn
215
+
216
+ /* $lab:coverage:off$ */
217
+ if (value === null || cached.isStale) {
218
+ /* $lab:coverage:on$ */
219
+ count = 1
220
+ } else {
221
+ count = value + 1
222
+ ttl = cached.ttl
223
+ }
224
+
225
+ let remaining = settings.userLimit - count
226
+ if (remaining < 0) {
227
+ remaining = -1
228
+ }
229
+
230
+ await userCache.set(user, count, ttl)
231
+
232
+ requestPlugin.userLimit = settings.userLimit
233
+ requestPlugin.userRemaining = remaining
234
+ requestPlugin.userReset = Date.now() + ttl
235
+
236
+ return remaining
237
+ }
238
+
239
+ async function userPathCheck (userPathCache, request) {
240
+ const requestPlugin = request.plugins[pluginName]
241
+ const settings = requestPlugin.settings
242
+ const ip = getIP(request, settings)
243
+ let user = getUser(request, settings)
244
+ const path = settings.ignorePathParams ? request.route.path : request.path
245
+
246
+ if (
247
+ settings.ipWhitelist.indexOf(ip) > -1 ||
248
+ (user && settings.userWhitelist.indexOf(user) > -1) ||
249
+ settings.userPathLimit === false
250
+ ) {
251
+ requestPlugin.userPathLimit = false
252
+ return
253
+ }
254
+
255
+ if (settings.addressOnly || user === undefined) {
256
+ user = ip
257
+ }
258
+
259
+ const userPath = `${user}:${path}`
260
+
261
+ const { value, cached } = await userPathCache.get(userPath)
262
+
263
+ let count
264
+ let ttl = settings.userPathCache.expiresIn
265
+
266
+ /* $lab:coverage:off$ */
267
+ if (value === null || cached.isStale) {
268
+ /* $lab:coverage:on$ */
269
+ count = 1
270
+ } else {
271
+ count = value + 1
272
+ ttl = cached.ttl
273
+ }
274
+
275
+ let remaining = settings.userPathLimit - count
276
+ if (remaining < 0) {
277
+ remaining = -1
278
+ }
279
+
280
+ await userPathCache.set(userPath, count, ttl)
281
+
282
+ requestPlugin.userPathLimit = settings.userPathLimit
283
+ requestPlugin.userPathRemaining = remaining
284
+ requestPlugin.userPathReset = Date.now() + ttl
285
+
286
+ return remaining
287
+ }
288
+
289
+ function limitExceededResponse () {
290
+ return Boom.tooManyRequests('Rate limit exceeded')
291
+ }
292
+
293
+ module.exports = {
294
+ authCheck,
295
+ authFailure,
296
+ getIP,
297
+ getUser,
298
+ limitExceededResponse,
299
+ pathCheck,
300
+ pluginName,
301
+ schema,
302
+ userCheck,
303
+ userPathCheck
304
+ }
ndcc/server/plugins/route.js CHANGED
@@ -97,7 +97,7 @@ exports.plugin = {
97
  collection === "plugins" ? server.match('POST', `/plugins/${_id}`) : server.match('GET', `/${_id}`); //添加时默认是这样
98
  if(!route){
99
  const options = collection === "api" ? {auth: 'auth'} :
100
- collection === 'plugins' ? { isInternal:true,payload: {parse: false, output: 'stream'},plugins: {'hapi-rate-limit': {enabled: false } }} :
101
  {}
102
 
103
  //添加插件需要注入到server.settings.app.plugins
@@ -242,7 +242,7 @@ exports.plugin = {
242
  server.route({
243
  method: ['POST'],
244
  path: `/plugins/${_id}`,
245
- options:{ isInternal:true,payload: {parse: false, output: 'stream'},plugins: {'hapi-rate-limit': {enabled: false } }},
246
  handler: pluginsHandler(_id)
247
  });
248
  })
 
97
  collection === "plugins" ? server.match('POST', `/plugins/${_id}`) : server.match('GET', `/${_id}`); //添加时默认是这样
98
  if(!route){
99
  const options = collection === "api" ? {auth: 'auth'} :
100
+ collection === 'plugins' ? { isInternal:true,payload: {parse: false, output: 'stream'},plugins: {'rate-limit': {enabled: false } }} :
101
  {}
102
 
103
  //添加插件需要注入到server.settings.app.plugins
 
242
  server.route({
243
  method: ['POST'],
244
  path: `/plugins/${_id}`,
245
+ options:{ isInternal:true,payload: {parse: false, output: 'stream'},plugins: {'rate-limit': {enabled: false } }},
246
  handler: pluginsHandler(_id)
247
  });
248
  })