Skip to content

Commit

Permalink
Merge pull request #89 from jesusvilla/feat-response-send
Browse files Browse the repository at this point in the history
feat(response): add more types in send method
  • Loading branch information
jkyberneees authored May 26, 2020
2 parents 6571852 + e6167a8 commit ef894ad
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 57 deletions.
94 changes: 68 additions & 26 deletions libs/response-extensions.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,83 @@
'use strict'

const { forEach } = require('../utils/object')

const CONTENT_TYPE_HEADER = 'content-type'
const CONTENT_TYPE = {
JSON: 'application/json; charset=utf-8',
PLAIN: 'text/plain; charset=utf-8',
OCTET: 'application/octet-stream'
}
const NOOP = () => {}

const setHeader = (res, value) => {
if (!res.hasHeader(CONTENT_TYPE_HEADER)) {
res.setHeader(CONTENT_TYPE_HEADER, value)
}
}

const stringify = (obj) => {
// ToDo: fast json stringify
return JSON.stringify(obj)
}

const sendJSON = (res, obj, cb) => {
res.end(stringify(obj), cb)
}

const sendError = (res, error, cb) => {
const errorCode = error.status || error.code || error.statusCode
res.statusCode = typeof errorCode === 'number' ? parseInt(errorCode) : 500
res.setHeader(CONTENT_TYPE_HEADER, CONTENT_TYPE.JSON)
sendJSON(res, {
code: res.statusCode,
message: error.message,
data: error.data
}, cb)
}

/**
* The friendly 'res.send' method
* No comments needed ;)
*/
module.exports.send = (options, req, res) => (data = 200, code = 200, headers = null, cb = () => {}) => {
if (headers !== null) {
Object.keys(headers).forEach((key) => {
res.setHeader(key.toLowerCase(), headers[key])
})
}
module.exports.send = (options, req, res) => {
return (data = 200, code = 200, headers = null, cb = NOOP) => {
if (headers !== null) {
forEach(headers, (value, key) => {
res.setHeader(key.toLowerCase(), value)
})
}

if (typeof data === 'number') {
code = parseInt(data, 10)
data = res.body
} else if (data instanceof Error) {
const errorCode = data.status || data.code || data.statusCode
code = typeof errorCode === 'number' ? parseInt(errorCode) : 500
data = {
code,
message: data.message,
data: data.data
if (data instanceof Error) {
sendError(res, data, cb)
return
}
res.setHeader(CONTENT_TYPE_HEADER, 'application/json')
}

if (typeof data === 'object' && data instanceof Buffer === false) {
if (!res.hasHeader(CONTENT_TYPE_HEADER)) {
res.setHeader(CONTENT_TYPE_HEADER, 'application/json')
if (typeof data === 'number') {
code = parseInt(data, 10)
data = res.body
}
data = JSON.stringify(data)
}

res.statusCode = code
res.statusCode = code

if (data != null) {
if (typeof data === 'string') {
setHeader(res, CONTENT_TYPE.PLAIN)
} else if (data instanceof Buffer) {
setHeader(res, CONTENT_TYPE.OCTET)
} else if (typeof data.pipe === 'function') {
setHeader(res, CONTENT_TYPE.OCTET)
data.pipe(res)
data.on('end', cb)
return
} else if (typeof data === 'object') {
setHeader(res, CONTENT_TYPE.JSON)
sendJSON(res, data, cb)
return
}
}

// finally end request
res.end(data, cb)
// finally end request
res.end(data, cb)
}
}
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"devDependencies": {
"@hapi/hapi": "^19.1.1",
"chai": "^4.2.0",
"connect-query": "^1.0.0",
"express": "^4.17.1",
"express-jwt": "^5.3.3",
"fastify": "^2.14.1",
Expand Down
30 changes: 0 additions & 30 deletions specs/buffer.test.js

This file was deleted.

96 changes: 96 additions & 0 deletions specs/send.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use strict'

/* global describe, it */
const request = require('supertest')
const { createReadStream, readFileSync } = require('fs')
const path = require('path')

describe('All Responses', () => {
let server
const service = require('../index')()

service.get('/string', (req, res) => {
res.send('Hello World!')
})

service.get('/buffer', (req, res) => {
res.send(Buffer.from('Hello World!'))
})

service.get('/buffer-string', (req, res) => {
res.setHeader('content-type', 'text/plan; charset=utf-8')
res.send(Buffer.from('Hello World!'))
})

service.get('/json', (req, res) => {
res.send({ id: 'restana' })
})

service.get('/stream', (req, res) => {
res.setHeader('content-type', 'text/html; charset=utf-8')
res.send(createReadStream(path.resolve(__dirname, '../demos/static/src/index.html'), { encoding: 'utf8' }))
})

service.get('/error', (req, res) => {
const err = new Error('Test')
err.code = 501
res.send(err)
})

it('should start service', async () => {
server = await service.start(~~process.env.PORT)
})

it('should GET 200 and string content on /string', async () => {
await request(server)
.get('/string')
.expect(200)
.expect('Hello World!')
})

it('should GET 200 and buffer content on /buffer', async () => {
await request(server)
.get('/buffer')
.expect(200)
.expect('content-type', 'application/octet-stream')
.expect(Buffer.from('Hello World!'))
})

it('should GET 200 and string content on /buffer-string', async () => {
await request(server)
.get('/buffer-string')
.expect(200)
.expect('Hello World!')
})

it('should GET 200 and json content on /json', async () => {
await request(server)
.get('/json')
.expect(200)
.expect('content-type', 'application/json; charset=utf-8')
.expect({ id: 'restana' })
})

it('should GET 200 and buffer content on /stream', async () => {
await request(server)
.get('/stream')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(readFileSync(path.resolve(__dirname, '../demos/static/src/index.html'), 'utf8'))
})

it('should GET 501 and json content on /error', async () => {
await request(server)
.get('/error')
.expect(501)
.expect('content-type', 'application/json; charset=utf-8')
.expect({
code: 501,
message: 'Test'
})
})

it('should successfully terminate the service', async () => {
await service.close()
})
})
7 changes: 7 additions & 0 deletions utils/object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports.forEach = (obj, cb) => {
const keys = Object.keys(obj)
const length = keys.length
for (let i = 0; i < length; i++) {
cb(obj[keys[i]], keys[i])
}
}

0 comments on commit ef894ad

Please sign in to comment.