You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
479 lines
9.4 KiB
479 lines
9.4 KiB
4 years ago
|
'use strict'
|
||
|
|
||
|
const t = require('tap')
|
||
|
const test = t.test
|
||
|
const Fastify = require('..')
|
||
|
const sget = require('simple-get').concat
|
||
|
const http = require('http')
|
||
|
const split = require('split2')
|
||
|
|
||
|
test('Should register a versioned route', t => {
|
||
|
t.plan(11)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.2.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.x'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.2.x'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.2.0'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.2.1'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('Should register the same route with different versions', t => {
|
||
|
t.plan(8)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.2.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send('1.2.0')
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.3.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send('1.3.0')
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.x'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
t.strictEqual(res.payload, '1.3.0')
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.2.x'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
t.strictEqual(res.payload, '1.2.0')
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '2.x'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('The versioned route should take precedence', t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ winter: 'is coming' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.2.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.x'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('Versioned route but not version header should return a 404', t => {
|
||
|
t.plan(2)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.2.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('Should register a versioned route', t => {
|
||
|
t.plan(6)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.2.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.listen(0, err => {
|
||
|
t.error(err)
|
||
|
fastify.server.unref()
|
||
|
|
||
|
sget({
|
||
|
method: 'GET',
|
||
|
url: 'http://localhost:' + fastify.server.address().port,
|
||
|
headers: {
|
||
|
'Accept-Version': '1.x'
|
||
|
}
|
||
|
}, (err, response, body) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(response.statusCode, 200)
|
||
|
t.deepEqual(JSON.parse(body), { hello: 'world' })
|
||
|
})
|
||
|
|
||
|
sget({
|
||
|
method: 'GET',
|
||
|
url: 'http://localhost:' + fastify.server.address().port,
|
||
|
headers: {
|
||
|
'Accept-Version': '2.x'
|
||
|
}
|
||
|
}, (err, response, body) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(response.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('Shorthand route declaration', t => {
|
||
|
t.plan(5)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.get('/', { version: '1.2.0' }, (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.x'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.2.1'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('The not found handler should not use the Accept-Version header', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.2.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.setNotFoundHandler(function (req, reply) {
|
||
|
t.notOk(req.headers['accept-version'])
|
||
|
reply.code(404).send('not found handler')
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': '2.x'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.deepEqual(res.payload, 'not found handler')
|
||
|
t.strictEqual(res.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('Bad accept version (inject)', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.2.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': 'a.b.c'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 404)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
'Accept-Version': 12
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('Bas accept version (server)', t => {
|
||
|
t.plan(5)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: '1.2.0',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.listen(0, err => {
|
||
|
t.error(err)
|
||
|
fastify.server.unref()
|
||
|
|
||
|
sget({
|
||
|
method: 'GET',
|
||
|
url: 'http://localhost:' + fastify.server.address().port,
|
||
|
headers: {
|
||
|
'Accept-Version': 'a.b.c'
|
||
|
}
|
||
|
}, (err, response, body) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(response.statusCode, 404)
|
||
|
})
|
||
|
|
||
|
sget({
|
||
|
method: 'GET',
|
||
|
url: 'http://localhost:' + fastify.server.address().port,
|
||
|
headers: {
|
||
|
'Accept-Version': 12
|
||
|
}
|
||
|
}, (err, response, body) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(response.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('test log stream', t => {
|
||
|
t.plan(3)
|
||
|
const stream = split(JSON.parse)
|
||
|
const fastify = Fastify({
|
||
|
logger: {
|
||
|
stream: stream,
|
||
|
level: 'info'
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.get('/', { version: '1.2.0' }, function (req, reply) {
|
||
|
reply.send(new Error('kaboom'))
|
||
|
})
|
||
|
|
||
|
fastify.listen(0, err => {
|
||
|
t.error(err)
|
||
|
fastify.server.unref()
|
||
|
|
||
|
http.get({
|
||
|
hostname: 'localhost',
|
||
|
port: fastify.server.address().port,
|
||
|
path: '/',
|
||
|
method: 'GET',
|
||
|
headers: {
|
||
|
'Accept-Version': '1.x'
|
||
|
}
|
||
|
})
|
||
|
|
||
|
stream.once('data', listenAtLogLine => {
|
||
|
stream.once('data', line => {
|
||
|
t.equal(line.req.version, '1.x')
|
||
|
stream.once('data', line => {
|
||
|
t.equal(line.req.version, '1.x')
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('Should register a versioned route with custome versioning strategy', t => {
|
||
|
t.plan(8)
|
||
|
|
||
|
const versioning = {
|
||
|
storage: function () {
|
||
|
let versions = {}
|
||
|
return {
|
||
|
get: (version) => { return versions[version] || null },
|
||
|
set: (version, store) => { versions[version] = store },
|
||
|
del: (version) => { delete versions[version] },
|
||
|
empty: () => { versions = {} }
|
||
|
}
|
||
|
},
|
||
|
deriveVersion: (req, ctx) => {
|
||
|
return req.headers.accept
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const fastify = Fastify({ versioning })
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: 'application/vnd.example.api+json;version=2',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'from route v2' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.route({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
version: 'application/vnd.example.api+json;version=3',
|
||
|
handler: (req, reply) => {
|
||
|
reply.send({ hello: 'from route v3' })
|
||
|
}
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
Accept: 'application/vnd.example.api+json;version=2'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.deepEqual(JSON.parse(res.payload), { hello: 'from route v2' })
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
Accept: 'application/vnd.example.api+json;version=3'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.deepEqual(JSON.parse(res.payload), { hello: 'from route v3' })
|
||
|
t.strictEqual(res.statusCode, 200)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/',
|
||
|
headers: {
|
||
|
Accept: 'application/vnd.example.api+json;version=4'
|
||
|
}
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.strictEqual(res.statusCode, 404)
|
||
|
})
|
||
|
})
|