This commit is contained in:
darenhsu
2022-07-17 13:16:16 +08:00
parent 84759556ff
commit befd344ab0
28070 changed files with 4008428 additions and 1 deletions
+142
View File
@@ -0,0 +1,142 @@
<a name="5.0.1"></a>
## [5.0.1](https://github.com/poppinss/node-res/compare/v5.0.0...v5.0.1) (2018-08-22)
<a name="5.0.0"></a>
# [5.0.0](https://github.com/poppinss/node-res/compare/v4.1.4...v5.0.0) (2018-08-21)
### Code Refactoring
* remove download and attachment methods ([cdccb34](https://github.com/poppinss/node-res/commit/cdccb34))
### Features
* **stream:** add method to stream to response ([31d2180](https://github.com/poppinss/node-res/commit/31d2180))
### BREAKING CHANGES
* downlaod and attachment methods are removed, one can use `send` package from npm
for this
<a name="4.1.4"></a>
## [4.1.4](https://github.com/poppinss/node-res/compare/v4.1.3...v4.1.4) (2018-01-19)
### Bug Fixes
* **header:** do not cast headers to array forcefully ([2e032dd](https://github.com/poppinss/node-res/commit/2e032dd))
<a name="4.1.3"></a>
## [4.1.3](https://github.com/poppinss/node-res/compare/v4.1.2...v4.1.3) (2018-01-19)
<a name="4.1.2"></a>
## [4.1.2](https://github.com/poppinss/node-res/compare/v4.1.1...v4.1.2) (2018-01-18)
<a name="4.1.1"></a>
## [4.1.1](https://github.com/poppinss/node-res/compare/v4.1.0...v4.1.1) (2018-01-17)
### Features
* **response:** add `prepare` & `prepareJsonp` methods ([a765dd9](https://github.com/poppinss/node-res/commit/a765dd9))
<a name="4.1.0"></a>
# [4.1.0](https://github.com/poppinss/node-res/compare/v4.0.4...v4.1.0) (2018-01-16)
<a name="4.0.4"></a>
## [4.0.4](https://github.com/poppinss/node-res/compare/v4.0.2...v4.0.4) (2017-10-29)
### Bug Fixes
* **ReDos:** Regular Expression Denial of Service ([#4](https://github.com/poppinss/node-res/issues/4)) ([9c17076](https://github.com/poppinss/node-res/commit/9c17076))
* **response:** move write statement out of setImmediate ([b62071d](https://github.com/poppinss/node-res/commit/b62071d))
<a name="4.0.3"></a>
## [4.0.3](https://github.com/poppinss/node-res/compare/v4.0.2...v4.0.3) (2017-10-26)
<a name="4.0.2"></a>
## [4.0.2](https://github.com/poppinss/node-res/compare/v4.0.0...v4.0.2) (2017-10-02)
### Bug Fixes
* **response:** response.send handle `undefined` body ([e4897d8](https://github.com/poppinss/node-res/commit/e4897d8)), closes [#2](https://github.com/poppinss/node-res/issues/2)
* **response:** response.send options allow user to override ([438298f](https://github.com/poppinss/node-res/commit/438298f))
<a name="4.0.1"></a>
## [4.0.1](https://github.com/poppinss/node-res/compare/v4.0.0...v4.0.1) (2017-10-02)
### Features
* **response:** allow option to ignore etag ([989abe8](https://github.com/poppinss/node-res/commit/989abe8))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/poppinss/node-res/compare/v3.0.2...v4.0.0) (2017-06-16)
<a name="3.0.2"></a>
## [3.0.2](https://github.com/poppinss/node-res/compare/v3.0.1...v3.0.2) (2017-06-12)
<a name="3.0.1"></a>
## [3.0.1](https://github.com/poppinss/node-res/compare/v2.0.1...v3.0.1) (2016-11-08)
### Bug Fixes
* **response:** set charset with content type ([19d6b87](https://github.com/poppinss/node-res/commit/19d6b87)), closes [adonis-framework#329](https://github.com/adonis-framework/issues/329)
<a name="3.0.0"></a>
# [3.0.0](https://github.com/poppinss/node-res/compare/v2.0.1...v3.0.0) (2016-06-25)
### Bug Fixes
* **download:** use send module to download file([7134e51](https://github.com/poppinss/node-res/commit/7134e51))
<a name="2.0.2"></a>
## [2.0.2](https://github.com/poppinss/node-res/compare/v2.0.1...v2.0.2) (2016-01-19)
<a name="2.0.1"></a>
## 2.0.1 (2016-01-18)
### Features
* **package:** added commitizen for consistent commit messages ([bc0241c](https://github.com/poppinss/node-res/commit/bc0241c))
+484
View File
@@ -0,0 +1,484 @@
# Node Res
> A facade over Node.js HTTP `res` object with no side-effects.
[![NPM Version][npm-image]][npm-url]
[![Build Status][travis-image]][travis-url]
[![Appveyor][appveyor-image]][appveyor-url]
[![Coveralls][coveralls-image]][coveralls-url]
<a href="http://res.cloudinary.com/adonisjs/image/upload/q_100/v1502279403/poppinss_z8uk2j.png">
<img src="http://res.cloudinary.com/adonisjs/image/upload/q_100/v1502279403/poppinss_z8uk2j.png" width="300px" align="right" vspace="20px" />
</a>
`node-res` is a simple module to make HTTP response in Node.js. It offers helpers to make it easier to set `headers`, define response statuses and properly parse response type to set appropriate headers.
For example:
```js
// content-type: plain/text
nodeRes.send(req, res, 'Hello world')
// content-type: application/json
nodeRes.send(req, res, { greeting: 'hello world' })
// content-type: text/html
nodeRes.send(req, res, '<h2> Hello world </h2>')
```
## See also
1. [node-req](https://npmjs.org/package/node-req)
2. [node-cookie](https://npmjs.org/package/node-cookie)
## Basic Example
```javascript
const http = require('http')
const nodeRes = require('node-res')
http.createServer(function (req, res) {
// plain text
nodeRes.send(req, res, "Hello world")
// json
nodeRes.json(req, res, {time:"now"})
// jsonp
nodeRes.jsonp(req, res, {time:"now"}, "callback")
}).listen(3000)
```
## API
<a name="module_Response"></a>
## Response
A simple IO module to make consistent HTTP response, without
worrying about underlying details.
* [Response](#module_Response)
* [~getHeader(res, key)](#module_Response..getHeader) ⇒ <code>Array</code> \| <code>String</code>
* [~header(res, key, value)](#module_Response..header) ⇒ <code>void</code>
* [~append(res, key, value)](#module_Response..append) ⇒ <code>void</code>
* [~status(res, code)](#module_Response..status) ⇒ <code>void</code>
* [~safeHeader(res, key, value)](#module_Response..safeHeader) ⇒ <code>void</code>
* [~removeHeader(res, key)](#module_Response..removeHeader) ⇒ <code>void</code>
* [~write(res, body)](#module_Response..write) ⇒ <code>void</code>
* [~end(res, [payload])](#module_Response..end) ⇒ <code>void</code>
* [~send(req, res, body, [generateEtag])](#module_Response..send) ⇒ <code>void</code>
* [~etag(res, body)](#module_Response..etag) ⇒ <code>void</code>
* [~prepare(res, body)](#module_Response..prepare) ⇒ <code>String</code>
* [~prepareJsonp(res, body, callbackFn)](#module_Response..prepareJsonp) ⇒ <code>String</code>
* [~json(req, res, body, [generateEtag])](#module_Response..json) ⇒ <code>void</code>
* [~jsonp(req, res, body, [callbackFn], [generateEtag])](#module_Response..jsonp) ⇒ <code>void</code>
* [~location(res, url)](#module_Response..location) ⇒ <code>void</code>
* [~redirect(req, res, url, [status])](#module_Response..redirect) ⇒ <code>void</code>
* [~vary(res, field)](#module_Response..vary) ⇒ <code>void</code>
* [~type(req, res, [charset])](#module_Response..type) ⇒ <code>void</code>
* [~stream(res, body)](#module_Response..stream) ⇒ <code>Promise</code>
<a name="module_Response..getHeader"></a>
### Response~getHeader(res, key) ⇒ <code>Array</code> \| <code>String</code>
Returns the value of an existing header on
the response object
**Kind**: inner method of [<code>Response</code>](#module_Response)
**Returns**: <code>Array</code> \| <code>String</code> - Return type depends upon the header existing value
| Param | Type |
| --- | --- |
| res | <code>ServerResponse</code> |
| key | <code>String</code> |
**Example**
```js
nodeRes.getHeader(res, 'Content-type')
```
<a name="module_Response..header"></a>
### Response~header(res, key, value) ⇒ <code>void</code>
Sets header on the response object. This method will wipe off
existing values. To append to existing values, use `append`.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| key | <code>String</code> |
| value | <code>String</code> \| <code>Array</code> |
**Example**
```js
nodeRes.header(res, 'Content-type', 'application/json')
// or set an array of headers
nodeRes.header(res, 'Link', ['<http://localhost/>', '<http://localhost:3000/>'])
```
<a name="module_Response..append"></a>
### Response~append(res, key, value) ⇒ <code>void</code>
Appends value to the header existing values.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| key | <code>String</code> |
| value | <code>String</code> \| <code>Array</code> |
**Example**
```js
nodeRes.append(res, 'Content-type', 'application/json')
// or append an array of headers
nodeRes.append(res, 'Link', ['<http://localhost/>', '<http://localhost:3000/>'])
```
<a name="module_Response..status"></a>
### Response~status(res, code) ⇒ <code>void</code>
Set status on the HTTP res object
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| code | <code>Number</code> |
**Example**
```js
nodeRes.status(res, 200)
```
<a name="module_Response..safeHeader"></a>
### Response~safeHeader(res, key, value) ⇒ <code>void</code>
Sets the header on response object, only if it
does not exists.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| key | <code>String</code> |
| value | <code>String</code> \| <code>Array</code> |
**Example**
```js
nodeRes.safeHeader(res, 'Content-type', 'application/json')
```
<a name="module_Response..removeHeader"></a>
### Response~removeHeader(res, key) ⇒ <code>void</code>
Removes the header from response
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| key | <code>String</code> |
**Example**
```js
nodeRes.removeHeader(res, 'Content-type')
```
<a name="module_Response..write"></a>
### Response~write(res, body) ⇒ <code>void</code>
Write string or buffer to the response object.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| body | <code>String</code> \| <code>Buffer</code> |
**Example**
```js
nodeRes.write(res, 'Hello world')
```
<a name="module_Response..end"></a>
### Response~end(res, [payload]) ⇒ <code>void</code>
Explictly end HTTP response
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| [payload] | <code>String</code> \| <code>Buffer</code> |
**Example**
```js
nodeRes.end(res, 'Hello world')
```
<a name="module_Response..send"></a>
### Response~send(req, res, body, [generateEtag]) ⇒ <code>void</code>
Send body as the HTTP response and end it. Also
this method will set the appropriate `Content-type`
and `Content-length`.
If body is set to null, this method will end the response
as 204.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type | Default |
| --- | --- | --- |
| req | <code>http.ServerRequest</code> | |
| res | <code>http.ServerResponse</code> | |
| body | <code>String</code> \| <code>Buffer</code> \| <code>Object</code> \| <code>Stream</code> | |
| [generateEtag] | <code>Boolean</code> | <code>true</code> |
**Example**
```js
nodeRes.send(req, res, 'Hello world')
// or html
nodeRes.send(req, res, '<h2> Hello world </h2>')
// or JSON
nodeRes.send(req, res, { greeting: 'Hello world' })
// or Buffer
nodeRes.send(req, res, Buffer.from('Hello world', 'utf-8'))
// Ignore etag
nodeRes.send(req, res, 'Hello world', false)
```
<a name="module_Response..etag"></a>
### Response~etag(res, body) ⇒ <code>void</code>
Sets the Etag header for a given body chunk
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| body | <code>String</code> \| <code>Buffer</code> |
**Example**
```js
nodeRes.etag(res, 'Hello world')
```
<a name="module_Response..prepare"></a>
### Response~prepare(res, body) ⇒ <code>String</code>
Prepares the response body by encoding it properly. Also
sets appropriate headers based upon the body content type.
This method is used internally by `send`, so you should
never use it when calling `send`.
It is helpful when you want to get the final payload and end the
response at a later stage.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| body | <code>Mixed</code> |
**Example**
```js
const chunk = nodeRes.prepare(res, '<h2> Hello </h2>')
if (chunk) {
nodeRes.etag(res, chunk)
if (nodeReq.fresh(req, res)) {
chunk = null
nodeRes.status(304)
}
nodeRes.end(chunk)
}
```
<a name="module_Response..prepareJsonp"></a>
### Response~prepareJsonp(res, body, callbackFn) ⇒ <code>String</code>
Prepares response for JSONP
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| body | <code>Object</code> |
| callbackFn | <code>String</code> |
**Example**
```js
const chunk = nodeRes.prepareJsonp(res, '<h2> Hello </h2>', 'callback')
if (chunk) {
nodeRes.etag(res, chunk)
if (nodeReq.fresh(req, res)) {
chunk = null
nodeRes.status(304)
}
nodeRes.end(chunk)
}
```
<a name="module_Response..json"></a>
### Response~json(req, res, body, [generateEtag]) ⇒ <code>void</code>
Returns the HTTP response with `Content-type`
set to `application/json`.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type | Default |
| --- | --- | --- |
| req | <code>http.IncomingMessage</code> | |
| res | <code>http.ServerResponse</code> | |
| body | <code>Object</code> | |
| [generateEtag] | <code>Boolean</code> | <code>true</code> |
**Example**
```js
nodeRes.json(req, res, { name: 'virk' })
nodeRes.json(req, res, [ 'virk', 'joe' ])
```
<a name="module_Response..jsonp"></a>
### Response~jsonp(req, res, body, [callbackFn], [generateEtag]) ⇒ <code>void</code>
Make JSONP response with `Content-type` set to
`text/javascript`.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type | Default |
| --- | --- | --- |
| req | <code>http.IncomingMessage</code> | |
| res | <code>http.ServerResponse</code> | |
| body | <code>Object</code> | |
| [callbackFn] | <code>String</code> | <code>&#x27;callback&#x27;</code> |
| [generateEtag] | <code>Boolean</code> | <code>true</code> |
**Example**
```js
nodeRes.jsonp(req, res, { name: 'virk' }, 'callback')
```
<a name="module_Response..location"></a>
### Response~location(res, url) ⇒ <code>void</code>
Set `Location` header on the HTTP response.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| url | <code>String</code> |
<a name="module_Response..redirect"></a>
### Response~redirect(req, res, url, [status]) ⇒ <code>void</code>
Redirect the HTTP request to the given url.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type | Default |
| --- | --- | --- |
| req | <code>http.IncomingMessage</code> | |
| res | <code>http.ServerResponse</code> | |
| url | <code>String</code> | |
| [status] | <code>Number</code> | <code>302</code> |
**Example**
```js
nodeRes.redirect(req, res, '/')
```
<a name="module_Response..vary"></a>
### Response~vary(res, field) ⇒ <code>void</code>
Add vary header to the HTTP response.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>http.ServerResponse</code> |
| field | <code>String</code> |
<a name="module_Response..type"></a>
### Response~type(req, res, [charset]) ⇒ <code>void</code>
Set content type header by looking up the actual
type and setting charset to utf8.
### Note
When defining custom charset, you must set pass the complete
content type, otherwise `false` will be set as the
content-type header.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| req | <code>http.IncomingMessage</code> |
| res | <code>http.ServerResponse</code> |
| [charset] | <code>String</code> |
**Example**
```js
nodeRes.type(res, 'html')
nodeRes.type(res, 'json')
nodeRes.type(res, 'text/html', 'ascii')
```
<a name="module_Response..stream"></a>
### Response~stream(res, body) ⇒ <code>Promise</code>
Pipe stream to the response. Also this method will make sure
to destroy the stream, if request gets cancelled.
The promise resolve when response finishes and rejects, when
stream raises errors.
**Kind**: inner method of [<code>Response</code>](#module_Response)
| Param | Type |
| --- | --- |
| res | <code>Object</code> |
| body | <code>Stream</code> |
**Example**
```js
Response.stream(res, fs.createReadStream('foo.txt'))
// handle stream errors
Response
.stream(res, fs.createReadStream('foo.txt'))
.catch((error) => {
})
```
[appveyor-image]: https://img.shields.io/appveyor/ci/thetutlage/node-res/master.svg?style=flat-square
[appveyor-url]: https://ci.appveyor.com/project/thetutlage/node-res
[npm-image]: https://img.shields.io/npm/v/node-res.svg?style=flat-square
[npm-url]: https://npmjs.org/package/node-res
[travis-image]: https://img.shields.io/travis/poppinss/node-res/master.svg?style=flat-square
[travis-url]: https://travis-ci.org/poppinss/node-res
[coveralls-image]: https://img.shields.io/coveralls/poppinss/node-res/develop.svg?style=flat-square
[coveralls-url]: https://coveralls.io/github/poppinss/node-res
+647
View File
@@ -0,0 +1,647 @@
'use strict'
/*
* node-res
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const mime = require('mime-types')
const etag = require('etag')
const vary = require('vary')
const onFinished = require('on-finished')
const destroy = require('destroy')
const methods = require('./methods')
const returnContentAndType = function (body) {
/**
* Return the body and it's type when
* body is a string.
*/
if (typeof (body) === 'string') {
return {
body,
type: /^\s*</.test(body) ? 'text/html' : 'text/plain'
}
}
/**
* If body is a buffer, return the exact copy
* and type as bin.
*/
if (Buffer.isBuffer(body)) {
return { body, type: 'application/octet-stream' }
}
/**
* If body is a number or boolean. Convert it to
* a string and return the type as text.
*/
if (typeof (body) === 'number' || typeof (body) === 'boolean') {
return { body: String(body), type: 'text/plain' }
}
/**
* Otherwise check whether body is an object or not. If yes
* stringify it and otherwise return the exact copy.
*/
return typeof (body) === 'object'
? { body: JSON.stringify(body), type: 'application/json' }
: { body }
}
/**
* A simple IO module to make consistent HTTP response, without
* worrying about underlying details.
*
* @module Response
*/
const Response = exports = module.exports = {}
/**
* Copying all the descriptive methods to the response object.
*/
Response.descriptiveMethods = Object.keys(methods).map((method) => {
Response[method] = function (req, res, body) {
Response.status(res, methods[method])
Response.send(req, res, body)
}
return method
})
/**
* Returns the value of an existing header on
* the response object
*
* @method getHeader
*
* @param {ServerResponse} res
* @param {String} key
*
* @return {Array|String} Return type depends upon the header existing value
*
* @example
* ```js
* nodeRes.getHeader(res, 'Content-type')
* ```
*/
Response.getHeader = function (res, key) {
return res.getHeader(key)
}
/**
* Sets header on the response object. This method will wipe off
* existing values. To append to existing values, use `append`.
*
* @method header
*
* @param {http.ServerResponse} res
* @param {String} key
* @param {String|Array} value
*
* @return {void}
*
* @example
* ```js
* nodeRes.header(res, 'Content-type', 'application/json')
*
* // or set an array of headers
* nodeRes.header(res, 'Link', ['<http://localhost/>', '<http://localhost:3000/>'])
* ```
*/
Response.header = function (res, key, value) {
const values = Array.isArray(value) ? value.map(String) : value
res.setHeader(key, values)
}
/**
* Appends value to the header existing values.
*
* @method append
*
* @param {http.ServerResponse} res
* @param {String} key
* @param {String|Array} value
*
* @return {void}
*
* @example
* ```js
* nodeRes.append(res, 'Content-type', 'application/json')
*
* // or append an array of headers
* nodeRes.append(res, 'Link', ['<http://localhost/>', '<http://localhost:3000/>'])
* ```
*/
Response.append = function (res, key, value) {
const previousValue = Response.getHeader(res, key)
const headers = previousValue
? (Array.isArray(previousValue) ? previousValue.concat(value) : [previousValue].concat(value))
: value
Response.header(res, key, headers)
}
/**
* Set status on the HTTP res object
*
* @method status
*
* @param {http.ServerResponse} res
* @param {Number} code
*
* @return {void}
*
* @example
* ```js
* nodeRes.status(res, 200)
* ```
*/
Response.status = function (res, code) {
res.statusCode = code
}
/**
* Sets the header on response object, only if it
* does not exists.
*
* @method safeHeader
*
* @param {http.ServerResponse} res
* @param {String} key
* @param {String|Array} value
*
* @return {void}
*
* @example
* ```js
* nodeRes.safeHeader(res, 'Content-type', 'application/json')
* ```
*/
Response.safeHeader = function (res, key, value) {
if (!res.getHeader(key)) {
Response.header(res, key, value)
}
}
/**
* Removes the header from response
*
* @method removeHeader
*
* @param {http.ServerResponse} res
* @param {String} key
*
* @return {void}
*
* @example
* ```js
* nodeRes.removeHeader(res, 'Content-type')
* ```
*/
Response.removeHeader = function (res, key) {
res.removeHeader(key)
}
/**
* Write string or buffer to the response object.
*
* @method write
*
* @param {http.ServerResponse} res
* @param {String|Buffer} body
*
* @return {void}
*
* @example
* ```js
* nodeRes.write(res, 'Hello world')
* ```
*/
Response.write = function (res, body) {
res.write(body)
}
/**
* Explictly end HTTP response
*
* @method end
*
* @param {http.ServerResponse} res
* @param {String|Buffer} [payload]
*
* @return {void}
*
* @example
* ```js
* nodeRes.end(res, 'Hello world')
* ```
*/
Response.end = function (res, payload) {
res.end(payload)
}
/**
* Send body as the HTTP response and end it. Also
* this method will set the appropriate `Content-type`
* and `Content-length`.
*
* If body is set to null, this method will end the response
* as 204.
*
* @method send
*
* @param {http.ServerRequest} req
* @param {http.ServerResponse} res
* @param {String|Buffer|Object|Stream} body
* @param {Boolean} [generateEtag = true]
*
* @return {void}
*
* @example
* ```js
* nodeRes.send(req, res, 'Hello world')
*
* // or html
* nodeRes.send(req, res, '<h2> Hello world </h2>')
*
* // or JSON
* nodeRes.send(req, res, { greeting: 'Hello world' })
*
* // or Buffer
* nodeRes.send(req, res, Buffer.from('Hello world', 'utf-8'))
*
* // Ignore etag
* nodeRes.send(req, res, 'Hello world', false)
* ```
*/
Response.send = function (req, res, body = null, generateEtag = true) {
/**
* Handle streams
*/
if (body && typeof (body.pipe) === 'function') {
Response
.stream(res, body)
.catch((error) => {
Response.status(res, error.code === 'ENOENT' ? 404 : 500)
Response.send(req, res, error.message, generateEtag)
})
return
}
const chunk = Response.prepare(res, body)
if (chunk === null || req.method === 'HEAD') {
Response.end(res)
return
}
/**
* Generate etag when instructured for
*/
if (generateEtag) {
Response.etag(res, chunk)
}
Response.end(res, chunk)
}
/**
* Sets the Etag header for a given body chunk
*
* @method etag
*
* @param {http.ServerResponse} res
* @param {String|Buffer} body
*
* @return {void}
*
* @example
* ```js
* nodeRes.etag(res, 'Hello world')
* ```
*/
Response.etag = function (res, body) {
Response.header(res, 'ETag', etag(body))
}
/**
* Prepares the response body by encoding it properly. Also
* sets appropriate headers based upon the body content type.
*
* This method is used internally by `send`, so you should
* never use it when calling `send`.
*
* It is helpful when you want to get the final payload and end the
* response at a later stage.
*
* @method prepare
*
* @param {http.ServerResponse} res
* @param {Mixed} body
*
* @return {String}
*
* @example
* ```js
* const chunk = nodeRes.prepare(res, '<h2> Hello </h2>')
*
* if (chunk) {
* nodeRes.etag(res, chunk)
*
* if (nodeReq.fresh(req, res)) {
* chunk = null
* nodeRes.status(304)
* }
*
* nodeRes.end(chunk)
* }
* ```
*/
Response.prepare = function (res, body) {
if (body === null) {
Response.status(res, 204)
Response.removeHeader(res, 'Content-Type')
Response.removeHeader(res, 'Content-Length')
Response.removeHeader(res, 'Transfer-Encoding')
return null
}
let { body: chunk, type } = returnContentAndType(body)
/**
* Remove unwanted headers when statuscode is 204 or 304
*/
if (res.statusCode === 204 || res.statusCode === 304) {
Response.removeHeader(res, 'Content-Type')
Response.removeHeader(res, 'Content-Length')
Response.removeHeader(res, 'Transfer-Encoding')
return chunk
}
const headers = typeof res.getHeaders === 'function' ? res.getHeaders() : (res._headers || {})
/**
* Setting content type. Ideally we can use `Response.type`, which
* sets the right charset too. But we will be doing extra
* processing for no reasons.
*/
if (type && !headers['content-type']) {
Response.header(res, 'Content-Type', `${type}; charset=utf-8`)
}
/**
* setting up content length as response header
*/
if (chunk && !headers['content-length']) {
Response.header(res, 'Content-Length', Buffer.byteLength(chunk))
}
return chunk
}
/**
* Prepares response for JSONP
*
* @method prepareJsonp
*
* @param {http.ServerResponse} res
* @param {Object} body
* @param {String} callbackFn
*
* @return {String}
*
* @example
* ```js
* const chunk = nodeRes.prepareJsonp(res, '<h2> Hello </h2>', 'callback')
*
* if (chunk) {
* nodeRes.etag(res, chunk)
*
* if (nodeReq.fresh(req, res)) {
* chunk = null
* nodeRes.status(304)
* }
*
* nodeRes.end(chunk)
* }
* ```
*/
Response.prepareJsonp = function (res, body, callbackFn) {
Response.header(res, 'X-Content-Type-Options', 'nosniff')
Response.safeHeader(res, 'Content-Type', 'text/javascript; charset=utf-8')
const parsedBody = JSON
.stringify(body)
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029')
/**
* setting up callbackFn on response body , typeof will make
* sure not to throw error of client if callbackFn is not
* a function
*/
return '/**/ typeof ' + callbackFn + " === 'function' && " + callbackFn + '(' + parsedBody + ');'
}
/**
* Returns the HTTP response with `Content-type`
* set to `application/json`.
*
* @method json
*
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @param {Object} body
* @param {Boolean} [generateEtag = true]
*
* @return {void}
*
* @example
* ```js
* nodeRes.json(req, res, { name: 'virk' })
* nodeRes.json(req, res, [ 'virk', 'joe' ])
* ```
*/
Response.json = function (req, res, body, generateEtag) {
Response.safeHeader(res, 'Content-Type', 'application/json; charset=utf-8')
Response.send(req, res, body, generateEtag)
}
/**
* Make JSONP response with `Content-type` set to
* `text/javascript`.
*
* @method jsonp
*
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @param {Object} body
* @param {String} [callbackFn = 'callback']
* @param {Boolean} [generateEtag = true]
*
* @return {void}
*
* @example
* ```js
* nodeRes.jsonp(req, res, { name: 'virk' }, 'callback')
* ```
*/
Response.jsonp = function (req, res, body, callbackFn = 'callback', generateEtag) {
Response.send(req, res, Response.prepareJsonp(res, body, callbackFn), generateEtag)
}
/**
* Set `Location` header on the HTTP response.
*
* @method location
*
* @param {http.ServerResponse} res
* @param {String} url
*
* @return {void}
*/
Response.location = function (res, url) {
Response.header(res, 'Location', url)
}
/**
* Redirect the HTTP request to the given url.
*
* @method redirect
*
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @param {String} url
* @param {Number} [status = 302]
*
* @return {void}
*
* @example
* ```js
* nodeRes.redirect(req, res, '/')
* ```
*/
Response.redirect = function (req, res, url, status = 302) {
const body = ''
Response.status(res, status)
Response.location(res, url)
Response.send(req, res, body)
}
/**
* Add vary header to the HTTP response.
*
* @method vary
*
* @param {http.ServerResponse} res
* @param {String} field
*
* @return {void}
*/
Response.vary = function (res, field) {
vary(res, field)
}
/**
* Set content type header by looking up the actual
* type and setting charset to utf8.
*
* ### Note
* When defining custom charset, you must set pass the complete
* content type, otherwise `false` will be set as the
* content-type header.
*
* @method type
*
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @param {String} [charset]
* @return {void}
*
* @example
* ```js
* nodeRes.type(res, 'html')
*
* nodeRes.type(res, 'json')
*
* nodeRes.type(res, 'text/html', 'ascii')
* ```
*/
Response.type = function (res, type, charset) {
type = charset ? `${type}; charset=${charset}` : type
Response.safeHeader(res, 'Content-Type', mime.contentType(type))
}
/**
* Pipe stream to the response. Also this method will make sure
* to destroy the stream, if request gets cancelled.
*
* The promise resolve when response finishes and rejects, when
* stream raises errors.
*
* @method stream
*
* @param {Object} res
* @param {Stream} body
*
* @returns {Promise}
*
* @example
* ```js
* Response.stream(res, fs.createReadStream('foo.txt'))
*
* // handle stream errors
* Response
* .stream(res, fs.createReadStream('foo.txt'))
* .catch((error) => {
* })
* ```
*/
Response.stream = function (res, body) {
return new Promise((resolve, reject) => {
if (typeof (body.pipe) !== 'function') {
reject(new Error('Body is not a valid stream'))
return
}
let finished = false
/**
* Error in stream
*/
body.on('error', (error) => {
if (finished) {
return
}
finished = true
destroy(body)
reject(error)
})
/**
* Consumed stream
*/
body.on('end', resolve)
/**
* Written response
*/
onFinished(res, function () {
finished = true
destroy(body)
})
/**
* Pipe to res
*/
body.pipe(res)
})
}
+55
View File
@@ -0,0 +1,55 @@
'use strict'
/*
* node-res
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
module.exports = {
continue: 100,
switchingProtocols: 101,
ok: 200,
created: 201,
accepted: 202,
nonAuthoritativeInformation: 203,
noContent: 204,
resetContent: 205,
partialContent: 206,
multipleChoices: 300,
movedPermanently: 301,
found: 302,
seeOther: 303,
notModified: 304,
useProxy: 305,
temporaryRedirect: 307,
badRequest: 400,
unauthorized: 401,
paymentRequired: 402,
forbidden: 403,
notFound: 404,
methodNotAllowed: 405,
notAcceptable: 406,
proxyAuthenticationRequired: 407,
requestTimeout: 408,
conflict: 409,
gone: 410,
lengthRequired: 411,
preconditionFailed: 412,
requestEntityTooLarge: 413,
requestUriTooLong: 414,
unsupportedMediaType: 415,
requestedRangeNotSatisfiable: 416,
expectationFailed: 417,
unprocessableEntity: 422,
tooManyRequests: 429,
internalServerError: 500,
notImplemented: 501,
badGateway: 502,
serviceUnavailable: 503,
gatewayTimeout: 504,
httpVersionNotSupported: 505
}
+101
View File
@@ -0,0 +1,101 @@
{
"_args": [
[
"node-res@5.0.1",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
]
],
"_from": "node-res@5.0.1",
"_id": "node-res@5.0.1",
"_inBundle": false,
"_integrity": "sha512-YOleO9c7MAqoHC+Ccu2vzvV1fL6Ku49gShq3PIMKWHRgrMSih3XcwL05NbLBi6oU2J471gTBfdpVVxwT6Pfhxg==",
"_location": "/node-res",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "node-res@5.0.1",
"name": "node-res",
"escapedName": "node-res",
"rawSpec": "5.0.1",
"saveSpec": null,
"fetchSpec": "5.0.1"
},
"_requiredBy": [
"/@nuxt/loading-screen"
],
"_resolved": "https://registry.npmjs.org/node-res/-/node-res-5.0.1.tgz",
"_spec": "5.0.1",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"author": {
"name": "amanvirk"
},
"bugs": {
"url": "https://github.com/poppinss/node-res/issues"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"dependencies": {
"destroy": "^1.0.4",
"etag": "^1.8.1",
"mime-types": "^2.1.19",
"on-finished": "^2.3.0",
"vary": "^1.1.2"
},
"description": "Nodejs http response builder",
"devDependencies": {
"co-functional": "^0.2.1",
"coveralls": "^3.0.2",
"cz-conventional-changelog": "^2.1.0",
"japa": "^1.0.6",
"japa-cli": "^1.0.1",
"nyc": "^12.0.2",
"semver": "^5.5.1",
"standard": "^11.0.1",
"supertest": "^3.1.0"
},
"directories": {
"test": "test"
},
"files": [
"index.js",
"methods.js"
],
"homepage": "https://github.com/poppinss/node-res#readme",
"keywords": [
"node-res",
"http",
"response",
"http-res",
"response",
"builder",
"res",
"builder"
],
"license": "MIT",
"main": "index.js",
"name": "node-res",
"nyc": {
"include": [
"index.js",
"methods.js"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/poppinss/node-res.git"
},
"scripts": {
"coverage": "nyc report --reporter=text-lcov | coveralls",
"lint": "standard",
"posttest": "npm run coverage",
"pretest": "npm run lint",
"test": "nyc npm run test:local",
"test:local": "FORCE_COLOR=true node bin/index.js --local",
"test:win": "set FORCE_COLOR=true && node bin/index.js --win"
},
"version": "5.0.1"
}