Socket
Socket
Sign inDemoInstall

servie-send

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

servie-send - npm Package Compare versions

Comparing version 0.0.1 to 1.0.0

38

dist/index.d.ts
/// <reference types="node" />
import { Request, Response } from 'servie';
import { Stream } from 'stream';
import { Request, Response, CreateHeaders } from 'servie';
import { CreateBody } from 'servie/dist/body/node';
export interface SendOptions {
statusCode?: number;
headers?: CreateHeaders;
contentType?: string;
contentLength?: number;
mtime?: Date;
replacer?: (key: string, value: any) => string;
space?: string | number;
type?: string;
status?: number;
etag?: string;
length?: number;
skipEtag?: boolean;
jsonSpaces?: string | number;
jsonReplacer?: (key: string, value: any) => string;
}
/**
* Send the payload as a HTTP response.
* Create an empty response.
*/
export declare function send(req: Request, payload: any, options?: SendOptions): Response;
export declare function sendEmpty(req: Request, options?: SendOptions): Response;
/**
* Send JSON response.
*/
export declare function sendJson(req: Request, payload: object | string | number, options?: SendOptions): Response;
export declare function sendJson(req: Request, payload: boolean | string | number | object, options?: SendOptions): Response;
/**
* Send the response as a stream.
*/
export declare function sendStream(req: Request, payload: Stream, options?: SendOptions): Response;
export declare function sendStream(req: Request, payload: CreateBody, options?: SendOptions): Response;
/**
* Send as text response (defaults to `text/plain`).
*/
export declare function sendText(req: Request, payload: string | Buffer, options?: SendOptions): Response;
export declare function sendText(req: Request, payload: CreateBody, options?: SendOptions): Response;
/**
* Send as html response (`text/html`).
*/
export declare function sendHtml(req: Request, payload: CreateBody, options?: SendOptions): Response;
/**
* Generate the response for Servie.
*/
export declare function send(req: Request, payload: CreateBody, options?: SendOptions): Response;
/**
* Create an ETag of the payload body.
*/
export declare function entityTag(body: string | Buffer): string;
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var crypto_1 = require("crypto");
var servie_1 = require("servie");
var crypto_1 = require("crypto");
var stream_1 = require("stream");
var node_1 = require("servie/dist/body/node");
var CACHE_CONTROL_NO_CACHE_REGEXP = /(?:^|,)\s*?no-cache\s*?(?:,|$)/;
var TOKEN_LIST_REGEXP = / *, */;
var ZERO_LENGTH_ENTITY_TAG = createEntityTag('');
/**
* Send the payload as a HTTP response.
* Create an empty response.
*/
function send(req, payload, options) {
if (payload === null || payload === undefined) {
return sendText(req, '', options);
}
if (payload instanceof stream_1.Stream) {
return sendStream(req, payload, options);
}
if (Buffer.isBuffer(payload)) {
return sendText(req, payload, options);
}
if (typeof payload === 'object') {
return sendJson(req, payload, options);
}
return sendText(req, String(payload), options);
function sendEmpty(req, options) {
if (options === void 0) { options = {}; }
return send(req, undefined, options);
}
exports.send = send;
exports.sendEmpty = sendEmpty;
/**

@@ -32,5 +30,5 @@ * Send JSON response.

if (options === void 0) { options = {}; }
return sendText(req, JSON.stringify(payload, options.replacer, options.space), {
type: options.type || 'application/json'
});
var contentType = options.contentType || 'application/json';
var data = JSON.stringify(payload, options.jsonReplacer, options.jsonSpaces);
return send(req, data, __assign({}, options, { contentType: contentType }));
}

@@ -43,22 +41,4 @@ exports.sendJson = sendJson;

if (options === void 0) { options = {}; }
var headers = {};
var status = options.status || 200;
var body = req.method === 'HEAD' ? undefined : payload;
if (fresh(req, options.etag, options.mtime)) {
status = 304;
body = undefined;
}
else {
headers['Content-Type'] = options.type || 'application/octet-stream';
if (options.length) {
headers['Content-Length'] = String(options.length);
}
}
if (options.etag) {
headers['ETag'] = options.etag;
}
if (options.mtime) {
headers['Last-Modified'] = options.mtime.toUTCString();
}
return new servie_1.Response({ status: status, headers: headers, body: body });
var contentType = options.contentType || 'application/octet-stream';
return send(req, payload, __assign({}, options, { contentType: contentType }));
}

@@ -71,33 +51,61 @@ exports.sendStream = sendStream;

if (options === void 0) { options = {}; }
var headers = {};
var length = typeof payload === 'string' ? Buffer.byteLength(payload) : payload.length;
var etag = options.etag || entityTag(length, payload);
var status = options.status || 200;
var body = req.method === 'HEAD' ? undefined : payload;
if (fresh(req, etag, options.mtime)) {
status = 304;
var contentType = options.contentType || 'text/plain';
return send(req, payload, __assign({}, options, { contentType: contentType }));
}
exports.sendText = sendText;
/**
* Send as html response (`text/html`).
*/
function sendHtml(req, payload, options) {
if (options === void 0) { options = {}; }
var contentType = options.contentType || 'text/html';
return send(req, payload, __assign({}, options, { contentType: contentType }));
}
exports.sendHtml = sendHtml;
/**
* Generate the response for Servie.
*/
function send(req, payload, options) {
if (options === void 0) { options = {}; }
var headers = servie_1.createHeaders(options.headers);
var statusCode = options.statusCode || 200;
var body = req.method === 'HEAD' ? undefined : node_1.createBody(payload);
if (fresh(req, options.etag, options.mtime)) {
statusCode = 304;
body = undefined;
}
else {
headers['Content-Type'] = options.type || 'text/plain';
headers['Content-Length'] = String(length);
if (options.contentType)
headers.set('Content-Type', options.contentType);
if (options.contentLength)
headers.set('Content-Length', String(options.contentLength));
}
headers['ETag'] = etag;
if (options.mtime) {
headers['Last-Modified'] = options.mtime.toUTCString();
if (options.mtime)
headers.set('Last-Modified', options.mtime.toUTCString());
if (options.etag) {
headers.set('ETag', options.etag);
}
return new servie_1.Response({ status: status, headers: headers, body: body });
else if (!options.skipEtag) {
if (typeof payload === 'string' || Buffer.isBuffer(payload)) {
headers.set('ETag', entityTag(payload));
}
}
return new servie_1.Response({ statusCode: statusCode, headers: headers, body: body });
}
exports.sendText = sendText;
exports.send = send;
/**
* Create an ETag of the payload body.
*/
function entityTag(len, body) {
if (len === 0) {
return "\"0-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU\"";
}
var hash = crypto_1.createHash('sha256').update(body).digest('base64').replace(/=+$/, '');
return "\"" + len.toString(36) + "-" + hash + "\"";
function entityTag(body) {
return body.length === 0 ? ZERO_LENGTH_ENTITY_TAG : createEntityTag(body);
}
exports.entityTag = entityTag;
/**
* Create an entity tag for cache identification.
*/
function createEntityTag(body) {
var hash = crypto_1.createHash('sha256').update(body).digest('base64');
return "\"" + hash + "\"";
}
/**
* Check if a request is fresh.

@@ -110,5 +118,4 @@ *

var modifiedSince = req.headers.get('if-modified-since');
if (!noneMatch && !modifiedSince) {
if (!noneMatch && !modifiedSince)
return false;
}
var cacheControl = req.headers.get('cache-control');

@@ -119,12 +126,12 @@ if (cacheControl && CACHE_CONTROL_NO_CACHE_REGEXP.test(cacheControl)) {

if (noneMatch && etag) {
var isStale = noneMatch.split(TOKEN_LIST_REGEXP).every(function (match) { return match !== etag; });
if (isStale) {
var isStale = noneMatch.split(TOKEN_LIST_REGEXP).every(function (match) {
return match !== etag;
});
if (isStale)
return false;
}
}
if (modifiedSince && lastModified) {
var isStale = lastModified.getTime() > Date.parse(modifiedSince);
if (isStale) {
if (isStale)
return false;
}
}

@@ -131,0 +138,0 @@ return true;

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -6,37 +42,103 @@ var index_1 = require("./index");

var stream_1 = require("stream");
var node_1 = require("servie/dist/body/node");
describe('servie-send', function () {
it('should send text', function () {
var req = new servie_1.Request({ url: '/' });
expect(index_1.send(req, 'hello world')).toMatchSnapshot();
});
it('should send an empty response', function () {
var req = new servie_1.Request({ url: '/' });
expect(index_1.send(req, null)).toMatchSnapshot();
});
it('should send json', function () {
var req = new servie_1.Request({ url: '/' });
expect(index_1.send(req, { hello: 'world' })).toMatchSnapshot();
});
it('should send stream', function () {
var req = new servie_1.Request({ url: '/' });
var chunk = 'hello world';
var stream = new stream_1.Readable({
read: function () {
this.push(chunk);
chunk = null;
it('should send text', function () { return __awaiter(_this, void 0, void 0, function () {
var req, res, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
req = new servie_1.Request({ url: '/' });
res = index_1.sendText(req, 'hello world');
expect(res.statusCode).toEqual(200);
expect(res.getHeaders()).toMatchSnapshot();
_a = expect;
return [4 /*yield*/, res.body.text()];
case 1:
_a.apply(void 0, [_b.sent()]).toEqual('hello world');
return [2 /*return*/];
}
});
expect(index_1.send(req, stream)).toMatchSnapshot();
});
it('should send 304 with matching etag', function () {
var req = new servie_1.Request({
url: '/',
headers: {
'If-None-Match': '"0-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU"'
},
body: ''
}); });
it('should send an empty response', function () { return __awaiter(_this, void 0, void 0, function () {
var req, res, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
req = new servie_1.Request({ url: '/' });
res = index_1.sendEmpty(req);
expect(res.statusCode).toEqual(200);
expect(res.getHeaders()).toMatchSnapshot();
_a = expect;
return [4 /*yield*/, res.body.text()];
case 1:
_a.apply(void 0, [_b.sent()]).toEqual('');
return [2 /*return*/];
}
});
expect(index_1.send(req, '')).toMatchSnapshot();
});
}); });
it('should send json', function () { return __awaiter(_this, void 0, void 0, function () {
var req, res, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
req = new servie_1.Request({ url: '/' });
res = index_1.sendJson(req, { hello: 'world' });
expect(res.statusCode).toEqual(200);
expect(res.getHeaders()).toMatchSnapshot();
_a = expect;
return [4 /*yield*/, res.body.text()];
case 1:
_a.apply(void 0, [_b.sent()]).toEqual('{"hello":"world"}');
return [2 /*return*/];
}
});
}); });
it('should send stream', function () { return __awaiter(_this, void 0, void 0, function () {
var req, chunk, stream, res, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
req = new servie_1.Request({ url: '/' });
chunk = 'hello world';
stream = new stream_1.Readable({
read: function () {
this.push(chunk);
chunk = null;
}
});
res = index_1.sendStream(req, stream);
expect(res.statusCode).toEqual(200);
expect(res.getHeaders()).toMatchSnapshot();
_a = expect;
return [4 /*yield*/, res.body.text()];
case 1:
_a.apply(void 0, [_b.sent()]).toEqual('hello world');
return [2 /*return*/];
}
});
}); });
it('should send 304 with matching etag', function () { return __awaiter(_this, void 0, void 0, function () {
var req, res, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
req = new servie_1.Request({
url: '/',
headers: servie_1.createHeaders({
'If-None-Match': index_1.entityTag('')
}),
body: node_1.createBody('')
});
res = index_1.sendText(req, '');
expect(res.statusCode).toEqual(304);
expect(res.getHeaders()).toMatchSnapshot();
_a = expect;
return [4 /*yield*/, res.body.text()];
case 1:
_a.apply(void 0, [_b.sent()]).toEqual('');
return [2 /*return*/];
}
});
}); });
});
//# sourceMappingURL=index.spec.js.map
{
"name": "servie-send",
"version": "0.0.1",
"version": "1.0.0",
"description": "Generate a HTTP response with client-side cache support",

@@ -11,3 +11,3 @@ "main": "dist/index.js",

"scripts": {
"lint": "tslint \"src/**/*.ts\" --project tsconfig.json --type-check",
"lint": "tslint \"src/**/*.ts\" --project tsconfig.json",
"build": "rm -rf dist/ && tsc",

@@ -41,21 +41,21 @@ "specs": "jest --coverage",

"devDependencies": {
"@types/jest": "^19.2.3",
"@types/node": "^7.0.18",
"jest": "^20.0.0",
"@types/jest": "^22.2.2",
"@types/node": "^8.0.0",
"jest": "^22.4.3",
"rimraf": "^2.5.4",
"servie": "^0.2.5",
"servie": "^2.1.3",
"throwback": "^2.0.0",
"ts-jest": "^20.0.2",
"tslint": "^5.0.0",
"tslint-config-standard": "^5.0.0",
"ts-jest": "^22.4.2",
"tslint": "^5.9.1",
"tslint-config-standard": "^7.0.0",
"typescript": "^2.2.1"
},
"peerDependencies": {
"servie": "^0.2.0"
"servie": "^2.1.0"
},
"jest": {
"transform": {
".(ts|tsx)": "ts-jest/preprocessor.js"
".(ts|tsx)": "ts-jest"
},
"testRegex": "src/.*\\.(?:test|spec)\\.(ts|tsx|js)$",
"testRegex": "src/.*\\.(?:test|spec)\\.(tsx?|jsx?)$",
"moduleFileExtensions": [

@@ -62,0 +62,0 @@ "ts",

@@ -7,5 +7,4 @@ # Servie Send

[![Test coverage](https://img.shields.io/coveralls/serviejs/servie-send.svg?style=flat)](https://coveralls.io/r/serviejs/servie-send?branch=master)
[![Greenkeeper badge](https://badges.greenkeeper.io/serviejs/servie-send.svg)](https://greenkeeper.io/)
> Create a HTTP response to send using Servie - a thin layer for creating a `Response` object with correct client-side cache headers.
> Create a HTTP response to send using Servie - a thin layer for creating a `Response` object with cache headers.

@@ -21,6 +20,10 @@ ## Installation

```ts
import { send } from 'servie-send'
import { sendText, sendHtml, sendJson, sendStream, sendEmpty } from 'servie-send'
function handle (req) {
return send(req, 'hello world!')
return sendText(req, 'hello world!')
return sendHtml(req, '<!doctype html>')
return sendJson(req, { json: true })
return sendStream(req, fs.createReadStream('example.txt'))
return sendEmpty(req) // Nothing in response.
}

@@ -27,0 +30,0 @@ ```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc