8000 close #78 by adding wildcard route support · jthomerson/lambda-api@e130b99 · GitHub
[go: up one dir, main page]

Skip to content

Commit e130b99

Browse files
committed
close jeremydaly#78 by adding wildcard route support
1 parent 9b29529 commit e130b99

File tree

2 files changed

+109
-2
lines changed

2 files changed

+109
-2
lines changed

lib/request.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,25 +145,34 @@ class REQUEST {
145145
let routes = this.app._routes
146146

147147
// Init wildcard
148-
let wildcard = {}
148+
let wc = []
149149

150150
// Loop the routes and see if this matches
151151
for (let i=0; i<path.length; i++) {
152152

153153
// Capture wildcard routes
154-
if (routes['*']) { wildcard = routes['*'] }
154+
if (routes['*']) { wc.push(routes['*']) }
155155

156156
// Traverse routes
157157
if (routes[path[i]]) {
158158
routes = routes[path[i]]
159159
} else if (routes['__VAR__']) {
160160
routes = routes['__VAR__']
161+
} else if (
162+
wc[wc.length-1]
163+
&& wc[wc.length-1]['__'+this.method]
164+
&& (this.method !== 'OPTIONS' || this.validWildcard(wc,this.method))
165+
) {
166+
routes = wc[wc.length-1]
161167
} else {
162168
this.app._errorStatus = 404
163169
throw new RouteError('Route not found','/'+path.join('/'))
164170
}
165171
} // end for loop
166172

173+
// Grab the deepest wildcard path
174+
let wildcard = wc.pop()
175+
167176
// Select ROUTE if exist for method, default ANY, apply wildcards, alias HEAD requests
168177
let route = routes['__'+this.method] ? routes['__'+this.method] :
169178
(routes['__ANY'] ? routes['__ANY'] :
@@ -207,6 +216,11 @@ class REQUEST {
207216
this._logs.push(this.app._logger.log(...args))
208217
}
209218

219+
// Recusive wildcard function
220+
validWildcard(wc) {
221+
return Object.keys(wc[wc.length-1]).length > 1
222+
|| (wc.length > 1 && this.validWildcard(wc.slice(0,-1)))
223+
}
210224

211225
} // end REQUEST class
212226

test/routes.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const expect = require('chai').expect // Assertion library
66
const api = require('../index')({ version: 'v1.0', logger: false })
77
const api2 = require('../index')({ version: 'v1.0', logger: false })
88
const api3 = require('../index')({ version: 'v1.0', logger: false })
9+
const api4 = require('../index')({ version: 'v1.0', logger: false })
910

1011
let event = {
1112
httpMethod: 'get',
@@ -222,6 +223,32 @@ api3.METHOD([1,'DELETE'],'/multimethod/badtype', (req,res) => {
222223
res.status(200).json({ method: req.method, path: '/multimethod/badtype' })
223224
})
224225

226+
227+
api4.get('/*', (req,res) => {
228+
res.status(200).header('wildcard',true).json({ method: req.method, path: req.path })
229+
})
230+
231+
api4.get('/test/*', (req,res) => {
232+
res.status(200).header('wildcard',true).json({ method: req.method, path: req.path, nested: "true" })
233+
})
234+
235+
api4.options('/test/*', (req,res) => {
236+
res.status(200).header('wildcard',true).json({ method: req.method, path: req.path, nested: "true" })
237+
})
238+
239+
api4.options('/test/test/*', (req,res) => {
240+
res.status(200).header('wildcard',true).json({ method: req.method, path: req.path, nested: "true" })
241+
})
242+
243+
api4.post('/*', (req,res) => {
244+
res.status(200).header('wildcard',true).json({ method: req.method, path: req.path })
245+
})
246+
247+
api4.post('/test/*', (req,res) => {
248+
res.status(200).header('wildcard',true).json({ method: req.method, path: req.path, nested: "true" })
249+
})
250+
251+
225252
/******************************************************************************/
226253
/*** BEGIN TESTS ***/
227254
/******************************************************************************/
@@ -320,6 +347,28 @@ describe('Route Tests:', function() {
320347
expect(result).to.deep.equal({ headers: { 'content-type': 'application/json' }, statusCode: 404, body: '{"error":"Route not found"}', isBase64Encoded: false })
321348
}) // end it
322349

350+
it('Wildcard: /*', async function() {
351+
let _event = Object.assign({},event,{ path: '/foo/bar' })
352+
let result = await new Promise(r => api4.run(_event,{},(e,res) => { r(res) }))
353+
expect(result).to.deep.equal({
354+
headers: { 'content-type': 'application/json', 'wildcard': true },
355+
statusCode: 200,
356+
body: '{"method":"GET","path":"/foo/bar"}',
357+
isBase64Encoded: false
358+
})
359+
}) // end it
360+
361+
it('Wildcard: /test/*', async function() {
362+
let _event = Object.assign({},event,{ path: '/test/foo/bar' })
363+
let result = await new Promise(r => api4.run(_event,{},(e,res) => { r(res) }))
364+
expect(result).to.deep.equal({
365+
headers: { 'content-type': 'application/json', 'wildcard': true },
366+
statusCode: 200,
367+
body: '{"method":"GET","path":"/test/foo/bar","nested":"true"}',
368+
isBase64Encoded: false
369+
})
370+
}) // end it
371+
323372
}) // end GET tests
324373

325374

@@ -486,6 +535,28 @@ describe('Route Tests:', function() {
486535
expect(result).to.deep.equal({ headers: { 'content-type': 'application/json' }, statusCode: 404, body: '{"error":"Route not found"}', isBase64Encoded: false })
487536
}) // end it
488537

538+
it('Wildcard: /*', async function() {
539+
let _event = Object.assign({},event,{ path: '/foo/bar', httpMethod: 'post' })
540+
let result = await new Promise(r => api4.run(_event,{},(e,res) => { r(res) }))
541+
expect(result).to.deep.equal({
542+
headers: { 'content-type': 'application/json', 'wildcard': true },
543+
statusCode: 200,
544+
body: '{"method":"POST","path":"/foo/bar"}',
545+
isBase64Encoded: false
546+
})
547+
}) // end it
548+
549+
it('Wildcard: /test/*', async function() {
550+
let _event = Object.assign({},event,{ path: '/test/foo/bar', httpMethod: 'post' })
551+
let result = await new Promise(r => api4.run(_event,{},(e,res) => { r(res) }))
552+
expect(result).to.deep.equal({
553+
headers: { 'content-type': 'application/json', 'wildcard': true },
554+
statusCode: 200,
555+
body: '{"method":"POST","path":"/test/foo/bar","nested":"true"}',
556+
isBase64Encoded: false
557+
})
558+
}) // end it
559+
489560
}) // end POST tests
490561

491562

@@ -702,6 +773,28 @@ describe('Route Tests:', function() {
702773
expect(result).to.deep.equal({ headers: { 'content-type': 'application/json' }, statusCode: 404, body: '{"error":"Route not found"}', isBase64Encoded: false })
703774
}) // end it
704775

776+
it('Wildcard: /test/*', async function() {
777+
let _event = Object.assign({},event,{ path: '/test/foo/bar', httpMethod: 'options' })
778+
let result = await new Promise(r => api4.run(_event,{},(e,res) => { r(res) }))
779+
expect(result).to.deep.equal({
780+
headers: { 'content-type': 'application/json', 'wildcard': true },
781+
statusCode: 200,
782+
body: '{"method":"OPTIONS","path":"/test/foo/bar","nested":"true"}',
783+
isBase64Encoded: false
784+
})
785+
}) // end it
786+
787+
it('Wildcard: /test/test/* (higher level matching)', async function() {
788+
let _event = Object.assign({},event,{ path: '/test/test/foo/bar', httpMethod: 'options' })
789+
let result = await new Promise(r => api4.run(_event,{},(e,res) => { r(res) }))
790+
expect(result).to.deep.equal({
791+
headers: { 'content-type': 'application/json', 'wildcard': true },
792+
statusCode: 200,
793+
body: '{"method":"OPTIONS","path":"/test/test/foo/bar","nested":"true"}',
794+
isBase64Encoded: false
795+
})
796+
}) // end it
797+
705798
}) // end OPTIONS tests
706799

707800

0 commit comments

Comments
 (0)
0