Skip to content

Latest commit

 

History

History

hifetch

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

hifetch

< Back to Project WebCube

NPM Version

Nodei

A minimal higher-level wrapper around Fetch API

Built on top of isomorphic-fetch

Get started

npm install hifetch

Hifetch is optimized for JSON API.

You can fetch, process and consume JSON response with minimal custom options.

import hifetch from 'hifetch';

// GET http://www.mydomain.com/users/1/?mobile=true
// + Response 200 (application/json; charset=utf-8)
//   + Headers
//     X-API-Version: 1.0
//   + Body
//     {
//       "status": 0,
//       "username": "xxx"
//     }
hifetch({
  url: 'http://www.mydomain.com/users/1/',
  query: {
    mobile: true,
  },
  jwtToken: '...', // Authorization header with the Bearer authentication
  headers: { // Custom request headers
    'X-Requested-With': 'XMLHttpRequest',
  },
  timeout: 10000,
}).send().then(result => {
  // result:
  // {
  //   "status": 0,
  //   "username": "xxx"
  // }
}).catch(errorResult => {
  // errorResult:
  // {
  //   "status": 5,
  //   "message": "[TIMEOUT ERROR] limit: 10000"
  // }
  // or
  // {
  //   "status": 1,
  //   "message": "[INTERNAL JS ERROR] error message that generated by Hifetch own code"
  //   "error": Error,
  // }
});

By default, Hifetch supports JSON response in Goolge JSON Style

// GET http://www.mydomain.com/users/wrong-id/
// + Response 400 (application/json; charset=utf-8)
//   + Body
//    {
//      "error": {
//        "code": 400,
//        "message": "User Not Found", // human readable message
//        "errors": [{
//          "reason": "ResourceNotFoundException", // Unique Identifier
//          "message": "User Not Found", // human readable message
//        }]
//      }
//    }
hifetch({
  url: 'http://www.mydomain.com/users/wrong-id/',
  disableStatusValidator: true,
}).send().then(result => {
  // ...
}).catch(errorResult => {
  // errorResult:
  // {
  //   "status": 3,
  //   "message": `[REMOTE ERROR] reason: ResourceNotFoundException, code: 400, message: User Not Found`,
  //   "originMessage": "User Not Found",
  //   "reason": "ResourceNotFoundException",
  //   "errors": [{ ... }],
  // }
});

// GET http://www.mydomain.com/users/1/
// + Response 200 (application/json; charset=utf-8)
//   + Body
//    {
//      "data": {
//        "otherDataA": ...
//        "otherDataB": ...
//      },
//    }
hifetch({
  url: 'http://www.mydomain.com/users/1/',
}).send().then(result => {
  // result:
  // {
  //   "otherDataA": ...
  //   "otherDataB": ...
  // }
});

Hifetch also supports JSON response with unix-style exit status

A zero exit status indicates succeeded. A nonzero exit status indicates failure (Hifetch only supports negative number)

You can use this style by responseStyle option

// GET http://www.mydomain.com/users/wrong-id/
// + Response 200 (application/json; charset=utf-8)
//   + Body
//     {
//       "status": -1, // Unique Identifier
//       "message": "User Not Found" // human readable message
//       "otherData": ...
//     }
hifetch({
  url: 'http://www.mydomain.com/users/wrong-id/',
  responseStyle: 'unix',
}).send().then(result => {
  // ...
}).catch(errorResult => {
  // errorResult:
  // {
  //   "status": -1,
  //   "message": "User Not Found"
  //   "otherData": ...
  // }
});

// GET http://www.mydomain.com/users/1/
// + Response 200 (application/json; charset=utf-8)
//   + Body
//     {
//       "status": 0,
//       "otherDataA": ...
//       "otherDataB": ...
//     }
hifetch({
  url: 'http://www.mydomain.com/users/1/',
  query: {
    mobile: false,
  },
  responseStyle: 'unix',
}).send().then(result => {
  // result:
  // {
  //   "status": 0,
  //   "otherDataA": ...
  //   "otherDataB": ...
  // }
});

You can disable this feature by disableResponseStyle option

HTTP status code validation

hifetch({
  url: 'http://www.mydomain.com/nonexistent-url/',
  // the following code is the default value of `validateStatus`, so it should be omitted
  validateStatus(status) {
    return status >= 200 && status < 300;
  },
}).send().then(result => {
  // ...
}).catch(errorResult => {
  // errorResult:
  // {
  //   "status": 2,
  //   "message": "[FETCH ERROR] 404 Not Found"
  //   "httpStatus": 404,
  //   "httpStatusText": "Not Found",
  // }
});

Error response caused by user-defined hook function (validateStatus, parser, handler, success, error)

hifetch({
  url: 'http://www.mydomain.com/users/1/',
  handler() {
    throw new Error();
  },
}).send().then(result => {
  // ...
}).catch(errorResult => {
  // errorResult:
  // {
  //   "status": 4,
  //   "message": "[CUSTOM JS ERROR] error message that caused by user-defined hook function"
  //   "error": Error,
  // }
});

By default, Hifetch directly uses response body as the result.

When the response body is JSON object format, you can merge some response headers into the result.

// GET http://www.mydomain.com/users/1/
// + Response 200 (application/json; charset=utf-8)
//   + Headers
//     X-API-Version: 1.0
//   + Body
//     {
//       "status": 0,
//       "username": "xxx"
//     }
hifetch({
  url: 'http://www.mydomain.com/users/1/',
  mergeHeaders: {
    version: 'X-API-Version',
  },
}).send().then(res => {
  // result:
  // {
  //   "status": 0,
  //   "username": "xxx"
  //   "version": "1.0",
  // }
});

When enableMeta is true, the result is a meta object.

// GET http://www.mydomain.com/users/1/
// + Response 200 (application/json; charset=utf-8)
//   + Headers
//     X-API-Version: 1.0
//   + Body
//     {
//       "status": 0,
//       "username": "xxx"
//     }
hifetch({
  url: 'http://www.mydomain.com/users/1/',
  mergeHeaders: {
    version: 'X-API-Version',
  },
  enableMeta: true,
  // enableResponseObject: true,
}).send().then(res => {
  // result:
  // {
  //   "status": 0,
  //   "httpStatus": 200,
  //   "httpStatusText": "",
  //   "url": "http://www.mydomain.com/users/1/",
  //   "headers": {
  //     "x-api-version": "1.0",
  //     "content-type": "application/json; charset=utf-8",
  //   },
  //   "data": {
  //     "status": 0,
  //     "username": "xxx"
  //   },
  //   "response": ResponseObject, // if `enableResponseObject` is true
  // }
});

hifetch({
  url: 'http://www.mydomain.com/users/1/',
  mergeHeaders: {
    version: 'X-API-Version',
  },
  filterHeaders: {
    'content-type': true,
  },
  enableMeta: true,
}).send().then(res => {
  // result:
  // {
  //   "status": 0,
  //   "httpStatus": 200,
  //   "httpStatusText": "",
  //   "url": "http://www.mydomain.com/users/1/",
  //   "headers": {
  //     "content-type": "application/json; charset=utf-8",
  //   },
  //   "data": {
  //     "status": 0,
  //     "username": "xxx"
  //   },
  // }
});

Use custom responseType and parser to fetch HTML string:

hifetch({
  url: 'http://www.mydomain.com/profile/1/',
  responseType: 'html', // or 'text/html',
  parser(response) { // you muse provide a custom parser for Fetch API's response
    return response.text();
  },

Post JSON with urlencoded body

hifetch({
  url: 'http://www.mydomain.com/users/1/actions/createByUrlencoded',
  method: 'post',
  query: {
    mobile: true,
  },
  data: { // request body
    name: 'yy',
  },

Post JSON with JSON-encoded body

hifetch({
  url: 'http://www.mydomain.com/users/1/actions/createByJSON',
  method: 'post',
  query: {
    mobile: true,
  },
  data: { // request body
    name: 'yy',
  },
  dataType: 'json', // or 'application/json',

Post form-data body

const formData = new FormData();
formData.append('name', 'yy');

hifetch({
  url: 'http://www.mydomain.com/users/1/actions/createByFormData',
  method: 'post',
  query: {
    mobile: true,
  },
  data: formData, // request body

or

hifetch({
  url: 'http://www.mydomain.com/users/1/actions/createByFormData',
  method: 'post',
  query: {
    mobile: true,
  },
  data: { // request body
    name: 'yy',
  },
  dataType: 'form', // or 'multipart/form-data',

Post form-data body with files

hifetch({
  url: 'http://www.mydomain.com/users/1/actions/createByFormData',
  method: 'post',
  query: {
    mobile: true,
  },
  data: { // request body
    name: 'yy',
    avatar: imageFile,
  },

or

const formData = new FormData();
formData.append('name', 'yy');
formData.append('photos', imageFile1);
formData.append('photos', imageFile2);

hifetch({
  url: 'http://www.mydomain.com/users/1/actions/createByFormData',
  method: 'post',
  query: {
    mobile: true,
  },
  data: formData, // request body

Custom validator and processor for response data

hifetch({
  //...
  handler: (res, headers) => {
    if (res.xx) {
      throw new Error(res.xx);
    }
    return Object.assign(headers, data);
  },

Options

Request

  • url
    • Required
  • method
    • Default: 'get'
  • query
    • Type: plain object
  • dataType
    • Default: 'application/x-www-form-urlencoded'
    • Custom 'Content-Type' header
  • data
    • Type: plain object, FormData object or String
    • When using FormData, dataType can be omitted (always be 'multipart/form-data')
  • FormData
  • headers
    • Other custom request headers
  • jwtToken
    • Add JWT header

Response

  • responseType
    • Default: 'application/json'
    • Custom 'Accept' header
  • responseStyle
    • Type: 'google' | 'unix'
    • Default: 'google'
    • Automatically processing the JSON response based on special style guide
  • mergeHeaders
    • Type: plain object
    • Default: null
    • Merge some response headers into the JSON object reponse
    • Example: { poweredBy: 'X-Powered-By' }
  • filterHeaders
    • Type: plain object
    • Default: null
    • Pick some response headers.
    • Example: { 'X-Powered-By': true } or { 'x-powered-by': true }
  • timeout
    • Millisecond
  • enableCookies
    • Type: Boolean
    • Default: false
    • Automatically send cookies
  • disableCORS
    • Type: Boolean
    • Default: false
  • disableStatusValidator
    • Type: Boolean
    • Default: false
    • Skip the validateStatus hook
  • disableResponseStyle
    • Type: Boolean
    • Default: false
    • Disable the automatic processing (like 'REMOTE ERROR') triggered by the special format of JSON response
  • enableMeta
    • Type: Boolean
    • Default: false
    • Embed response body into a meta object
  • enableResponseObject
    • Type: Boolean
    • Default: false
    • Like enableMeta, plus the response object

Hooks

  • validateStatus
    • Default: status >= 200 && status < 300
    • Custom validator for acceptable HTTP response status code
  • parser
    • Default: response => response.json()
  • handler
    • Custom validator and processor for response data
  • success
    • Default: res => res
  • error
    • Default: res => Promise.reject(res)

Actions

  • send()
    • Return: Promise
    • Automatically nterrupt latest outstanding request each time it's called
  • cancel()
    • Interrupt latest outstanding request, nothing happen
  • error()
    • Interrupt latest outstanding request, trigger error callback

See actions.spec.js for more detail.

Development

npm run lint
npm run test