UNPKG

4.7 kBJavaScriptView Raw
1var chai = require('chai')
2 , request = require('supertest')
3 , sinon = require('sinon')
4 , redis = require('redis').createClient()
5 , v = require('valentine')
6 , subject = require('../')
7
8chai.use(require('sinon-chai'))
9
10describe('rate-limiter', function () {
11 var express, app, limiter
12
13 beforeEach(function () {
14 express = require('express')
15 app = express()
16 limiter = subject(app, redis)
17 })
18
19 afterEach(function (done) {
20 redis.flushdb(done)
21 })
22
23 it('should work', function (done) {
24 var map = [10, 9, 8, 7, 6, 5, 4, 3, 2]
25 var clock = sinon.useFakeTimers()
26
27 limiter({
28 path: '/route',
29 method: 'get',
30 lookup: ['connection.remoteAddress'],
31 total: 10,
32 expire: 1000 * 60 * 60
33 })
34
35 app.get('/route', function (req, res) {
36 res.send(200, 'hello')
37 })
38
39 var out = (map).map(function (item) {
40 return function (f) {
41 process.nextTick(function () {
42 request(app)
43 .get('/route')
44 .expect('X-RateLimit-Limit', 10)
45 .expect('X-RateLimit-Remaining', item - 1)
46 .expect('X-RateLimit-Reset', 3600)
47 .expect(200, function (e) {f(e)})
48 })
49 }
50 })
51 out.push(function (f) {
52 request(app)
53 .get('/route')
54 .expect('X-RateLimit-Limit', 10)
55 .expect('X-RateLimit-Remaining', 0)
56 .expect('X-RateLimit-Reset', 3600)
57 .expect('Retry-After', /\d+/)
58 .expect(429, function (e) {f(e)})
59 })
60 out.push(function (f) {
61 // expire the time
62 clock.tick(1000 * 60 * 60 + 1)
63 request(app)
64 .get('/route')
65 .expect('X-RateLimit-Limit', 10)
66 .expect('X-RateLimit-Remaining', 9)
67 .expect('X-RateLimit-Reset', 7201)
68 .expect(200, function (e) {
69 clock.restore()
70 f(e)
71 })
72 })
73 v.waterfall(out, done)
74 })
75
76 context('options', function() {
77 it('should process options.skipHeaders', function (done) {
78 limiter({
79 path: '/route',
80 method: 'get',
81 lookup: ['connection.remoteAddress'],
82 total: 0,
83 expire: 1000 * 60 * 60,
84 skipHeaders: true
85 })
86
87 app.get('/route', function (req, res) {
88 res.send(200, 'hello')
89 })
90
91 request(app)
92 .get('/route')
93 .expect(function(res) {
94 if ('X-RateLimit-Limit' in res.headers) return 'X-RateLimit-Limit Header not to be set'
95 })
96 .expect(function(res) {
97 if ('X-RateLimit-Remaining' in res.headers) return 'X-RateLimit-Remaining Header not to be set'
98 })
99 .expect(function(res) {
100 if ('Retry-After' in res.headers) return 'Retry-After not to be set'
101 })
102 .expect(429, done)
103 })
104
105 it('should process ignoreErrors', function (done) {
106 limiter({
107 path: '/route',
108 method: 'get',
109 lookup: ['connection.remoteAddress'],
110 total: 10,
111 expire: 1000 * 60 * 60,
112 ignoreErrors: true
113 })
114
115 app.get('/route', function (req, res) {
116 res.send(200, 'hello')
117 })
118
119 var stub = sinon.stub(redis, 'get', function(key, callback) {
120 callback({err: true})
121 })
122
123 request(app)
124 .get('/route')
125 .expect(200, function (e) {
126 done(e)
127 stub.restore()
128 })
129 })
130 })
131
132 context('direct middleware', function () {
133
134 it('is able to mount without `path` and `method`', function (done) {
135 var clock = sinon.useFakeTimers()
136 var middleware = limiter({
137 lookup: 'connection.remoteAddress',
138 total: 3,
139 expire: 1000 * 60 * 60
140 })
141 app.get('/direct', middleware, function (req, res, next) {
142 res.send(200, 'is direct')
143 })
144 v.waterfall(
145 function (f) {
146 process.nextTick(function () {
147 request(app)
148 .get('/direct')
149 .expect('X-RateLimit-Limit', 3)
150 .expect('X-RateLimit-Remaining', 2)
151 .expect(200, function (e) {f(e)})
152 })
153 },
154 function (f) {
155 process.nextTick(function () {
156 request(app)
157 .get('/direct')
158 .expect('X-RateLimit-Limit', 3)
159 .expect('X-RateLimit-Remaining', 1)
160 .expect(200, function (e) {f(e)})
161 })
162 },
163 function (f) {
164 process.nextTick(function () {
165 request(app)
166 .get('/direct')
167 .expect('X-RateLimit-Limit', 3)
168 .expect('X-RateLimit-Remaining', 0)
169 .expect('Retry-After', /\d+/)
170 .expect(429, function (e) { f(null) })
171 })
172 },
173 function (e) {
174 done(e)
175 }
176 )
177 })
178 })
179})