5.0.1 • Published 5 years ago

node-res v5.0.1

Weekly downloads
313,336
License
MIT
Repository
github
Last release
5 years ago

npm.io

Node res is a facade to be used by any framework to send HTTP response from a given request. The res object of Node.js is very low level and not enjoyable to work with.

Table of contents

Features

  • Support for JSON, JSONP response types.
  • Automatically generates etag to enable caching.
  • Serializes response body and set appropriate headers for it.
  • Elegantly closes readable stream when piping a stream to the response.
  • Files download.
  • Helper methods.
  • Typings support
  • Extendable from outside
  • Thoroughly tested.

Getting started

Install the package from npm as follows:

npm i node-res

# yarn
yarn add node-res

and then use it by importing it as follows:

const { Response } = require('node-res')
const http = require('http')

const options = {
  etag: true,
  jsonpCallbackName: 'callback'
}

http.createServer(function (req, res) {
  const response = new Response(req, res, options)
  response.status(201).json({ ok: true })
})

Raw Node.js API

http.createServer(function (req, res) {
  const body = JSON.stringify({ ok: true })

  res.statusCode = 201
  res.setHeader('content-type', 'application/json')
  res.setHeader('content-length', Buffer.byteLength(body))
  res.write(body)
  res.end()
})

As you can see, sending JSON response from the raw res object requires little bit of extra work and the purpose of this module is to abstract those low level API's to a consistent set of high level API's.

Explicit Mode

This mode is used by AdonisJs Framework

The response/res object in Node.js and in many popular frameworks like Express, Fastify will write the response body as soon as you will call res.send method.

This is okay, if your HTTP request stack is simple and doesn't have many abstraction layers. However, if you heavily make use of middleware and want to modify the response body inside a middleware, it's impossible to do that.

Whereas, this module comes with a switch (explicitEnd), using that you can tell it to not write the response unless response.finish is called explicitly.

http.createServer(function (req, res) {
  const response = new Response(req, res, {})
  
  response.explicitEnd = true
  
  // response is saved in memory
  response.send({ ok: true })
  
  response.hasLazyBody // true
  response.lazyBody // { writer, args: [] }
  
  // now writing
  response.finish()
})

This is how explicitEnd=true works in nutshell

  1. Any calls to methods send, json, jsonp will be buffered and stored inside memory.
  2. No headers will be set.
  3. Consecutive calls to previous methods will override the existing memory reference with the new one.
  4. The response is only written to the TCP socket when response.finish is called.
  5. Consecutive calls to response.finish results in a noop.

Typescript support

The module is written in Typescript, so expect intellisense to work out of the box. Also an interface is exported, which you can extend if extending the original Response class.

import { IResponse: BaseIResponse } from 'node-res/build/src/IResponse'

export interface IResponse extends BaseIResponse {
  myCustomMethod (): string
}

and then use it as follows

import { IResponse } from './my/interfaces'

http.createServer(function (req, res) {
  const response: IResponse = new Response(req, res, {})
  response.myCustomMethod() // intellisense works
})

Extending via Macros

The module extends macroable, which allows extending classes from outside in. You can use the following methods to extend the prototype of the Response class.

import { Response } from 'node-res'

// Added as a method
Response.macro('status', function () {
  return this.response.statusCode
})

// Added as property
Response.getter('status', function () {
  return this.response.statusCode
})

// Added as singleton property
Response.getter('status', function () {
  return this.response.statusCode
}, true)

Later, using the request instance, you can use getters and macros.

http.createServer(function (req, res) {
  const response = new Response(req, res, {})

  response.status // getter
  response.status() // macro
})

Difference from other frameworks

You don't need this module, if you are using Express or Koa, since their res object is already decorated with handful of convenient getters.

In case you are building a framework or using a framework like micro, then this module can save lots of time.

API

The API docs are generated using TypeDoc and can be found here.