Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bandwidth-throttle-stream

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bandwidth-throttle-stream - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

CHANGELOG.md

26

package.json
{
"name": "bandwidth-throttle-stream",
"version": "0.1.1",
"description": "A Node.js transform stream for throttling bandwidth",
"version": "0.2.0",
"description": "A Node.js and Deno transform stream for throttling bandwidth",
"author": "KunkaLabs Limited",
"private": false,
"license": "Apache-2.0",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"main": "./dist/node/index.js",
"types": "./dist/node/index.d.ts",
"module": "./dist/deno/mod.js",
"files": [
"dist"
"dist/node",
"dist/deno"
],

@@ -18,6 +20,9 @@ "repository": {

"scripts": {
"test": "TS_NODE_PROJECT=./tsconfig.json mocha \"**/*.test.ts\" --config ./config/mocha/.mocharc.json",
"test": "TS_NODE_PROJECT=./config/typescript/tsconfig.base.json mocha \"**/*.test.ts\" --config ./config/mocha/.mocharc.json",
"test:watch": "npm run test -- --watch",
"test:cover": "nyc npm run test",
"build": "rm -rf dist && tsc -p ./config/typescript/tsconfig.build.json",
"clean:dist": "rm -rf dist",
"build:node": "ttsc -p ./config/typescript/tsconfig.build.node.json",
"build:deno": "ttsc -p ./config/typescript/tsconfig.build.deno.json",
"build": "npm run clean:dist npm run build:node && npm run build:deno",
"lint": "tslint --project tsconfig.json -c ./config/tslint/tslint.json \"./src/**/*.ts\""

@@ -49,3 +54,4 @@ },

"@types/node": "12.6.8",
"@types/sinon": "7.0.13",
"@types/sinon": "9.0.4",
"@zerollup/ts-transform-paths": "^1.7.17",
"chai": "4.2.0",

@@ -57,9 +63,11 @@ "husky": "3.0.2",

"prettier": "1.19.1",
"sinon": "7.4.2",
"sinon": "9.0.2",
"ts-node": "8.3.0",
"tsc-watch": "2.4.0",
"tsconfig-paths": "^3.9.0",
"tslint": "5.20.1",
"tslint-eslint-rules": "5.4.0",
"ttypescript": "^1.5.10",
"typescript": "3.7.4"
}
}

@@ -5,6 +5,7 @@ ![CI](https://github.com/patrickkunka/bandwidth-throttle-stream/workflows/CI/badge.svg) [![Coverage Status](https://coveralls.io/repos/github/patrickkunka/bandwidth-throttle-stream/badge.svg?branch=master)](https://coveralls.io/github/patrickkunka/bandwidth-throttle-stream?branch=master)

A Node.js [transform stream](https://nodejs.org/api/stream.html) for throttling bandwidth which distributes available bandwidth evenly between all requests in a "group", accurately simulating the effect of network conditions on simultaneous overlapping requests.
A [Node.js](https://nodejs.org/en/) and [Deno](https://deno.land/) transform stream for throttling bandwidth which distributes available bandwidth evenly between all requests in a "group", accurately simulating the effect of network conditions on simultaneous overlapping requests.
#### Features
- Idiomatic pipeable Node.js transform stream API
- Idiomatic pipeable [Transform](https://nodejs.org/api/stream.html) API for use in Node.js
- Idiomatic pipeable [TransformStream](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) API for use in Deno
- Distributes the desired bandwidth evenly over each second

@@ -15,3 +16,4 @@ - Distributes the desired bandwidth evenly between all active requests

#### Contents
- [Installation](#installation)
- [Node.js Installation](#nodejs-installation)
- [Deno Installation](#deno-installation)
- [Usage](#usage)

@@ -23,6 +25,5 @@ - [Creating a Group](#creating-a-group)

- [Dynamic Configuration](#dynamic-configuration)
- [Aborting Requests](#aborting-requests)
- [Destroying Requests](#destroying-requests)
- [Aborted Requests](#aborted-requests)
## Installation
## Node.js Installation

@@ -41,2 +42,10 @@ Firstly, install the package using your package manager of choice.

## Deno Installation
In Deno, all libraries are imported from URLs as ES modules. Versioned releases of `bandwidth-throttle-stream` are available from TBC:
```js
import {createBandwidthThrottleGroup} from 'https://path/to/cdn/bandwidth-throttle-stream@0.2.0/mod.ts'
```
## Usage

@@ -46,7 +55,5 @@

We must firstly create a "bandwidth throttle group" which will be configured with a specific throughput in bytes (B) per second.
Using the imported `createBandwidthThrottleGroup` factory function, we must firstly create a "bandwidth throttle group" which will be configured with a specific throughput in bytes (B) per second.
```js
import {createBandwidthThrottleGroup} from 'bandwidth-throttle-stream';
// Create a group with a configured available bandwidth in bytes (B) per second.

@@ -65,11 +72,12 @@

The most simple integration would be to insert the throttle (via `.pipe`) between a readable stream (e.g file system readout, server-side HTTP response), and the response stream of the incoming client request to be throttled.
The most simple integration would be to insert the throttle (via `.pipe`, or `.pipeThrough`) between a readable stream (e.g file system readout, server-side HTTP response), and the response stream of the incoming client request to be throttled.
##### Node.js example: Piping between readable and writable streams
```js
// Attach a throttle to a group (e.g. in response to an incoming request)
const throttle = bandwidthThrottleGroup.createBandwidthThrottle();
const throttle = bandwidthThrottleGroup.createBandwidthThrottle(contentLength);
// Throttle the response by piping a readable stream to a writable
// stream via the throttle
// Throttle the response by piping a `stream.Readable` to a `stream.Writable`
// via the throttle

@@ -82,2 +90,31 @@ someReadableStream

#### Deno example: Piping between a readable stream and a reader:
```ts
// Attach a throttle to a group (e.g. in response to an incoming request)
const throttle = bandwidthThrottleGroup.createBandwidthThrottle(contentLength);
// Throttle the response by piping a `ReadableStream` to a `ReadableStreamDefaultReader`:
someReadableStream
.pipeThrough(throttle)
.getReader()
```
Note that a number value for `contentLength` (in "bytes") must be passed when creating an individual throttle. This should be the total size of data for the request being passed through the throttle, and is used to allocate memory upfront in a single `Uint8Array` typed array, thus preventing expensive GC calls as backpressure builds up. When throttling HTTP requests, `contentLength` can be obtained from the `'content-length'` header, once the headers of the request have arrived:
#### Node.js (Express) example: Obtaining `content-length` from `req` headers:
```js
const contentLength = parseInt(req.get('content-length'))
```
#### Deno example: Obtaining `content-length` from `fetch` headers:
```ts
const { body, headers } = await fetch(destination);
const contentLength = parseInt(headers.get("content-length"));
```
#### Handling Output

@@ -89,4 +126,5 @@

##### Node.js example: Hooking into the `end` event of a writable stream
```js
someReadableStream
request
.pipe(throttle)

@@ -99,7 +137,23 @@ .on('data', chunk => response.write(chunk)

response.end();
// Destroy the throttle to release it from the group
throttle.destroy();
});
```
##### Deno example: responding to a request with a reader and a status code
```ts
import {readerToDenoReader} from 'TBC';
...
await request.respond({
status: 200
body: readerToDenoReader(reader, contentLength),
});
// request sent successfully
```
Note that in the Deno example, a reader may be passed directly to `request.respond()` allowing real-time streaming of the throttled output. However, the Deno [`std`](https://deno.land/std/http/server.ts) server expects a `Deno.Reader` as a `body` (rather than the standard `ReadableStreamDefaultReader`), meaning that conversion is needed between the two.
The `readerToDenoReader` util is exposed for this purpose, and must be provided with both a reference to `ReadableStreamDefaultReader` (`reader`), and the `contentLength` of the request.
## Configuration Options

@@ -112,3 +166,3 @@

bytesPerSecond: 500000 // 500KB/s,
resolutionHz: 20 // aim to write output 20x per second
ticksPerSecond: 20 // aim to write output 20x per second
});

@@ -163,8 +217,10 @@ ```

## Aborting Requests
## Aborted Requests
When a client aborts a requests, its important that we also abort the throttle, ensuring the group can re-balance available bandwidth correctly.
When a client aborts a requests, its important that we also abort the throttle, ensuring the group can re-balance available bandwidth correctly, and backpressure buffer memory is released.
##### Node.js example: Handling aborted requests
```js
const throttle = bandwidthThrottleGroup.createBandwidthThrottle();
const throttle = bandwidthThrottleGroup.createBandwidthThrottle(contentLength);

@@ -177,25 +233,26 @@ request.on('aborted', () => {

someReadableStream
request
.pipe(throttle)
.on('data', chunk => response.write(chunk)
.on('end', () => {
// Set the response status of the HTTP request to 200
response.status(200);
// End the request
response.end();
// Destroy the throttle to release it from the group
throttle.destroy();
});
.pipe(response);
```
## Destroying Requests
##### Deno example: Handling aborted requests
To prevent memory leaks, individual throttles should be destroyed once all data for a request has been processed, and the request as ended.
```ts
const throttle = bandwidthThrottleGroup.createBandwidthThrottle(contentLength);
This ensures the throttle instance is fully released from its parent group.
request
.pipeThrough(throttle)
.getReader()
Each throttle instance exposes a `.destroy()` method for this purpose:
try {
await request.respond({
status: 200
body: readerToDenoReader(reader, contentLength),
});
} catch(err) {
// request aborted or failed
```js
throttle.destroy();
throttle.abort();
}
```
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