thenables / requisition

ES7 async/await ready http client
MIT License
57 stars 3 forks source link

Discussion: implement validateStatus like axios? #19

Open drawveloper opened 8 years ago

drawveloper commented 8 years ago

Hi! Have you thought about implementing something like validateStatus from axios?

https://github.com/mzabriskie/axios#request-config

  // `validateStatus` defines whether to resolve or reject the promise for a given
  // HTTP response status code. If `validateStatus` returns `true` (or is set to `null`
  // or `undefined`), the promise will be resolved; otherwise, the promise will be
  // rejected.
  validateStatus: function (status) {
    return status >= 200 && status < 300; // default
  },

I could maybe draft a PR if you think this fits the bill.

jonathanong commented 8 years ago

i would prefer a property like .ok

drawveloper commented 8 years ago

Sorry, I don't follow precisely what you mean. Where would that property be?

Also, what do you feel about custom Error objects for rejecting the promise?

I'm currently using this hack on top of requisition:

export function successful (status) {
  return status >= 200 && status < 300
}

export function StatusCodeError (statusCode, statusMessage, response) {
  this.name = 'StatusCodeError'
  this.status = this.statusCode = statusCode
  this.message = statusMessage
  this.res = this.response = response

  if (Error.captureStackTrace) {
    Error.captureStackTrace(this)
  }
}
StatusCodeError.prototype = Object.create(Error.prototype)
StatusCodeError.prototype.constructor = StatusCodeError

Request.prototype._then = Request.prototype.then

Request.prototype.then = function (resolve, reject) {
  return this._then(res => {
    if (successful(res.statusCode)) {
      return resolve(res)
    }
    const error = new StatusCodeError(res.statusCode, res.statusMessage, res)
    if (res.is('json')) {
      return res.json().then(body => {
        error.error = body
        throw error
      })
    }
    throw error
  }, reject)
}
haoxins commented 8 years ago

Sorry, I don't follow precisely what you mean. Where would that property be?

I think it's just

  const status = res.statusCode;
  this.status =
  this.statusCode = status;
  this.ok = status >= 200 && status < 300;

or

memo(Response.prototype, 'ok', function () {
  return this.status >= 200 && this.status < 300;
})

Also, what do you feel about custom Error objects for rejecting the promise?

this module deps http-errors, I think it's easy to implement such a api.

drawveloper commented 8 years ago

Ah, sorry, I don't think the point came across precisely: the idea of the validateStatus is that the user defines what's the criteria for the promise to be rejected. Most promise-based clients right now seem to prefer the idiom that a status code outside of the 2xx range represents an "error", or a rejection of the promise.

haoxins commented 8 years ago

Oh, sorry!

It's looks like ?

const createError = require('http-errors')
const statuses = require('statuses')

...

Response.prototype.checkStatus = function () {
  const status = this.status
  const ok = status >= 200 && status < 300
  if (!ok) {
    throw createError(status, statuses[status])
  }

  ...
}
drawveloper commented 8 years ago

Yes! But the point of having a user-configured function is that it allows the users of the lib to determine whether they want their promise to fail or not.