Socket
Socket
Sign inDemoInstall

get-it

Package Overview
Dependencies
Maintainers
1
Versions
159
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

get-it - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

lib/bundle-all.js

31

package.json
{
"name": "get-it",
"version": "0.0.2",
"version": "0.0.3",
"description": "Generic HTTP request library for node and browsers",

@@ -16,4 +16,13 @@ "main": "lib/index.js",

"scripts": {
"bundle": "npm run bundle:build && npm run bundle:build:all && npm run bundle:minify && npm run bundle:minify:all && npm run bundle:size",
"bundle:analyze": "npm run compile && NODE_ENV=production DEBUG='' browserify --full-paths -t envify -g uglifyify lib/index.js | discify --open",
"bundle:analyze:all": "npm run compile && NODE_ENV=production DEBUG='' browserify --full-paths -t envify -g uglifyify lib/bundle-all.js | discify --open",
"bundle:build": "npm run compile && NODE_ENV=production DEBUG='' browserify -t envify -g uglifyify lib/index.js -o umd/get-it.js --standalone=getIt",
"bundle:build:all": "npm run compile && NODE_ENV=production DEBUG='' browserify -t envify -g uglifyify lib/bundle-all.js -o umd/get-it-all.js --standalone=getIt",
"bundle:minify": "uglifyjs -c -m -- umd/get-it.js > umd/get-it.min.js",
"bundle:minify:all": "uglifyjs -c -m -- umd/get-it-all.js > umd/get-it-all.min.js",
"bundle:size": "node -r babel-register src/scripts/print-bundle-size",
"ci": "npm run coverage && npm run karma && npm run lint",
"clean": "rimraf lib .nyc_output coverage npm-debug.log yarn-debug.log",
"clean": "rimraf lib .nyc_output coverage npm-debug.log yarn-debug.log umd/*.js",
"compile": "babel --source-maps --copy-files -d lib/ src/",
"coverage": "nyc --reporter=html --reporter=lcov --reporter=text _mocha",

@@ -34,4 +43,2 @@ "karma": "karma start",

"@rexxars/timed-out": "^3.0.1",
"any-observable": "^0.2.0",
"any-promise": "^1.3.0",
"create-error-class": "^3.0.2",

@@ -54,13 +61,18 @@ "debug": "^2.3.3",

"devDependencies": {
"@sanity/observable": "^1.1.0",
"babel-cli": "^6.18.0",
"babel-loader": "^6.2.8",
"babel-preset-es2015": "^6.18.0",
"babel-preset-es2015-node4": "^2.1.0",
"babel-register": "^6.18.0",
"boxen": "^0.8.1",
"browserify": "^13.1.1",
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"chai-subset": "^1.3.0",
"chalk": "^1.1.3",
"disc": "^1.3.2",
"envify": "^4.0.0",
"es6-promise": "^4.0.5",
"eslint": "^3.11.1",
"eslint-config-sanity": "^2.0.1",
"gzip-size": "^3.0.0",
"karma": "^1.3.0",

@@ -77,6 +89,9 @@ "karma-chrome-launcher": "^2.0.0",

"nyc": "^10.0.0",
"pinkie-promise": "^2.0.1",
"pretty-bytes": "^4.0.2",
"rimraf": "^2.5.4",
"webpack": "^1.13.3"
"uglify-js": "^2.7.5",
"uglifyify": "^3.0.4",
"webpack": "^1.14.0",
"zen-observable": "^0.3.0"
}
}
# get-it
## Wanted features
Generic HTTP request library for node and browsers (IE9 and newer)
* [ ] Developer-friendly assertions that are stripped in production to reduce bundle size and performance
* [ ] Authentication (basic)
* [ ] Stream response middleware?
* [x] Progress upload/download events as middleware (available on observable/eventemitter)
* [x] All HTTP methods supported (obviously)
* [x] Configurable number of retries + "should retry" handler
* [x] Follow redirects (optional) up to limit
* [x] Gzip unwrapping support in node (browser automatically handles this)
* [x] Middleware-ish (like MJ's request lib)
* [x] Node and browser support (XHR), with small browser bundle footprint
* [x] Observable/promise/callback/eventemitter support as middleware (low-level by default)
* [x] Parsing of JSON request/response payloads as middleware
* [x] Send file/buffer/stuff as body, should just work
* [x] Timeouts with errors that are catchable (connect/response as separate in node)
## Motivation
We wanted an HTTP request library that worked transparently in Node.js and browsers with a small browser bundle footprint.
To be able to use the same library in a range of different applications with varying requirements, but still keep the bundle size down, we took inspiration from [http-client](https://github.com/mjackson/http-client) which cleverly composes functionality into the client.
## Features
Using a middleware approach, `get-it` has the following feature set:
* Promise, observable and low-level event-emitter patterns
* Automatic retrying with customizable number of attempts and filtering functionality
* Cancellation of requests
* Configurable connect/socket timeouts
* Automatic parsing of JSON responses
* Automatic stringifying of JSON request bodies
* Automatic gzip unwrapping in Node
* Automatically prepend base URL
* Automatically follow redirects (configurable number of retries)
* Upload/download progress events
* Treat HTTP status codes >=400 as errors
* Debug requests with environment variables/localStorage setting
## Usage
How `get-it` behaves depends on which middleware you've loaded, but common to all approaches is the setup process.
```js
// Require the core get-it package, which is used to generate a requester
const getIt = require('get-it')
// And require whatever middleware you want to use
const base = require('get-it/lib/middleware/base')
const jsonResponse = require('get-it/lib/middleware/jsonResponse')
const promise = require('get-it/lib/middleware/promise')
// Now compose the middleware you want to use
const request = getIt([
base('https://api.your.service/v1'),
jsonResponse()
])
// You can also register middleware using `.use(middleware)`
request.use(promise())
// Now you're ready to use the requester:
request({url: '/projects'})
.then(projects => console.log(projects))
.catch(err => console.error(err))
```
In most larger projects, you'd probably make a `httpClient.js` or similar, where you would instantiate the requester and export it for other modules to reuse.
## Options
* `rawBody` - Set to `true` to return the raw value of the response body, instead of a string. *Important note*: The returned body will be different in Node and browser environments. In Node, it will return a `Buffer`, while in browsers it will return an `ArrayBuffer`.
* `url` - URL to the resource you want to reach.
* `method` - HTTP method to use for request. Default: `GET`, unless a body is provided, in which case the default is `POST`.
* `headers` - Object of HTTP headers to send. Note that cross-origin requests in IE9 will not be able to set these headers.
* `body` - The request body. If the `jsonRequest` middleware is used, it will serialize to a JSON string before sending. Otherwise, it tries to send whatever is passed to it using the underlying adapter. Supported types:
* *Browser*: `string`, `ArrayBufferView`, `Blob`, `Document`, `FormData` (deprecated: `ArrayBuffer`)
* *Node*: `string`, `buffer`, `ReadStream`
* `bodySize` - Size of body, in bytes. Only used in Node when passing a `ReadStream` as body, in order for progress events to emit status on upload progress.
* `timeout` - Timeout in millisecond for the request. Takes an object with `connect` and `socket` properties.
* `maxRedirects` - Maximum number of redirects to follow before giving up. Note that this is only used in Node, as browsers have built-in redirect handling which cannot be adjusted. Default: `5`
* `rawBody` - Set to `true` to return the raw value of the response body, instead of a string. The type returned differs based on the underlying adapter:
* *Browser*: `ArrayBuffer`
* *Node*: `Buffer`
## Middleware
## Return values
Each middleware is an object of hook => action bindings. They are called in the order they are added to the request instance using `request.use()`. For instance, if you want to always set a certain header on outgoing responses, you could do:
By default, `get-it` will return an object of single-channel event emitters. This is done in order to provide a low-level API surface that others can build upon, which is what the `promise` and `observable` middlewares do. Unless you really know what you're doing, you'll probably want to use those middlewares.
## Response objects
`get-it` does not expose the low-level primitives such as the `XMLHttpRequest` or `http.IncomingMessage` instances. Instead, it provides a response object with the following properties:
```js
{
// string (ArrayBuffer or Buffer if `rawBody` is set to `true`)
body: 'Response body'
url: 'http://foo.bar/baz',
method: 'GET',
statusCode: 200,
statusMessage: 'OK',
headers: {
'Date': 'Fri, 09 Dec 2016 14:55:32 GMT',
'Cache-Control': 'public, max-age=120'
}
}
```
const isAwesome = {
processOptions: options => Object.assign({
headers: Object.assign({}, options.headers, {
'X-Is-Awesome': 'Absolutely'
})
})
}
request.use(isAwesome)
## Promise API
```js
const getIt = require('get-it')
const request = getIt([require('get-it/lib/middleware/promise')])
request({url: 'http://foo.bar'})
.then(res => console.log(res.body))
.catch(err => console.error(err))
```
The available hooks, their arguments and expected return values are as following:
If you are targetting older browsers that do not have a global Promise implementation, you must register one globally using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise):
### processOptions
```js
require('es6-promise/auto')
Called once a new request is instantiated. Can be used to alter options before they are validated and turned into an actual HTTP request. This hook is used by the `base` middleware, which prefixes the passed URL if it is not an absolute URI already.
const promise = require('get-it/lib/middleware/promise')
const request = getIt([promise])
```
Arguments:
### Cancelling promise-based requests
1. `options` - Object of request options passed to the request. Should be cloned if modifications are to be performed, to prevent unexpected side-effects.
With the Promise API, you can cancel requests using a _cancel token_. This API is based on the [Cancelable Promises proposal](https://github.com/tc39/proposal-cancelable-promises), which is currently at Stage 1.
Should return: Plain object of options to pass on to the rest of the middlewares.
You can create a cancel token using the `CancelToken.source` factory as shown below:
### parseResponse
```js
const promise = require('get-it/lib/middleware/promise')
const request = getIt([promise])
Called once a response has been received and the response body is ready.
const source = promise.CancelToken.source()
@todo document
request.get({
url: 'http://foo.bar/baz',
cancelToken: source.token
}).catch(err => {
if (promise.isCancel(err)) {
console.log('Request canceled', err.message)
} else {
// handle error
}
})
## Prior work
// Cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user')
```
## Observable API
The observable API requires you to pass an Observable-implementation that you want to use. Optionally, you can register it under the global `Observable`, but this is not recommended.
```js
const getIt = require('get-it')
const observable = require('get-it/lib/middleware/observable')
const request = getIt()
request.use(observable({
implementation: require('zen-observable')}
))
const observer = request({url: 'http://foo.bar/baz'})
.filter(ev => ev.type === 'response')
.subscribe({
next: res => console.log(res.body),
error: err => console.error(err)
})
// If you want to cancel the request, simply unsubscribe:
observer.unsubscribe()
```
It's important to note that the observable middleware does not only emit `response` objects, but also `progress` events. You should always filter to specify what you're interested in receiving. Every emitted value has a `type` property.
## Upcoming features
* Developer-friendly assertions that are stripped in production to reduce bundle size and performance
* Authentication (basic)
* Stream response middleware?
## Prior art
This module was inspired by the great work of others:

@@ -61,0 +178,0 @@

@@ -1,5 +0,5 @@

import pubsub from 'nano-pubsub'
import middlewareReducer from './util/middlewareReducer'
import processOptions from './middleware/defaultOptionsProcessor'
import httpRequest from './request' // node-request in node, browser-request in browsers
const pubsub = require('nano-pubsub')
const middlewareReducer = require('./util/middlewareReducer')
const processOptions = require('./middleware/defaultOptionsProcessor')
const httpRequest = require('./request') // node-request in node, browser-request in browsers

@@ -6,0 +6,0 @@ const channelNames = ['request', 'response', 'progress', 'error', 'abort']

const Cancel = require('./Cancel')
const Promise = require('any-promise')

@@ -4,0 +3,0 @@ function CancelToken(executor) {

@@ -1,2 +0,2 @@

import createErrorClass from 'create-error-class'
const createErrorClass = require('create-error-class')

@@ -8,3 +8,3 @@ const HttpError = createErrorClass('HttpError', function (res) {

module.exports = {
module.exports = () => ({
onResponse: res => {

@@ -18,2 +18,2 @@ const isHttpError = res.statusCode >= 400

}
}
})
const objectAssign = require('object-assign')
module.exports = {
module.exports = () => ({
processOptions: options => {

@@ -16,2 +16,2 @@ if (typeof options.body === 'undefined') {

}
}
})
const objectAssign = require('object-assign')
module.exports = {
module.exports = () => ({
onResponse: response => {

@@ -14,5 +14,5 @@ const contentType = response.headers['content-type']

processOptions: options => objectAssign({}, options, {
headers: objectAssign({}, options.headers, {Accept: 'application/json'})
headers: objectAssign({Accept: 'application/json'}, options.headers)
})
}
})

@@ -19,0 +19,0 @@ function tryParse(body) {

@@ -1,16 +0,23 @@

import Observable from 'any-observable'
import objectAssign from 'object-assign'
const global = require('global')
const objectAssign = require('object-assign')
module.exports = {
onReturn: (channels, context) => new Observable(observer => {
channels.error.subscribe(err => observer.error(err))
channels.progress.subscribe(event => observer.next(objectAssign({type: 'progress'}, event)))
channels.response.subscribe(response => {
observer.next({type: 'response', response})
observer.complete()
module.exports = (opts = {}) => {
const Observable = opts.implementation || global.Observable
if (!Observable) {
throw new Error('`Observable` is not available in global scope, and no implementation was passed')
}
return {
onReturn: (channels, context) => new Observable(observer => {
channels.error.subscribe(err => observer.error(err))
channels.progress.subscribe(event => observer.next(objectAssign({type: 'progress'}, event)))
channels.response.subscribe(response => {
observer.next(objectAssign({type: 'response'}, response))
observer.complete()
})
channels.request.publish(context)
return () => channels.abort.publish()
})
channels.request.publish(context)
return () => channels.abort.publish()
})
}
}

@@ -1,2 +0,2 @@

module.exports = {
module.exports = () => ({
onRequest: evt => {

@@ -31,2 +31,2 @@ if (evt.adapter !== 'xhr') {

}
}
})

@@ -13,3 +13,3 @@ const progressStream = require('progress-stream')

module.exports = {
module.exports = () => ({
onHeaders: (response, evt) => {

@@ -41,2 +41,2 @@ const progress = progressStream({time: 16})

}
}
})

@@ -1,2 +0,2 @@

const Promise = require('any-promise')
const global = require('global')
const Cancel = require('./cancel/Cancel')

@@ -6,5 +6,6 @@ const CancelToken = require('./cancel/CancelToken')

const promise = (opts = {}) => {
const promise = () => {
const Promise = global.Promise
if (!Promise) {
throw new Error('`Promise` is not available in global scope, and no implementation was given')
throw new Error('`Promise` is not available in global scope, and no implementation was passed')
}

@@ -11,0 +12,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