elbywan / wretch

A tiny wrapper built around fetch with an intuitive syntax. :candy:
MIT License
4.79k stars 96 forks source link

Wretch error on 403 Forbidden #115

Closed friso-k closed 2 years ago

friso-k commented 3 years ago

Wretch seems to not be able to catch an 403 error when the error type is set to json. I'm not sure if this is the case for all empty response bodies.

elbywan commented 3 years ago

Hi @akumaf,

An empty body is not a valid json, so setting the error type to json will not work indeed.

If you have an API which is not consistently returning json errors, then you could eventually use a middleware to force a valid json response - or keep the text error type and parse the error yourself.

Such a middleware would be something like this:

const wretch = require("wretch")
const fetch = require("node-fetch@2.6.2")
const express = require("express")
const app = express()
const port = 3000

app.get('/', function (req, res) {
  res.json({hello: 'world'})
})

app.get('/403', function(req, res) {
  res.status(403).send('')
})

const middleware = next => (url, opts) => {
  return next(url, opts).then(response => {
    if(response.headers.get('Content-Length') === '0') {
        return { ...response, json: () => Promise.resolve({}) }
    }
    return response
  })
}

app.listen(port, () => {
  const http = wretch("http://localhost:3000").polyfills({ fetch }).errorType("json")
  http.get().json(console.log)
  // Invalid json - empty body
  http.url('/403').get().json(console.log).catch(error => console.error(`Caught ${error}`))
  // Will be caught
  http.middlewares([middleware]).url('/403').get().text(console.log).catch(error => console.error(`Caught ${error}`))
})
friso-k commented 2 years ago

thanks for getting back at me. The middleware strategy works best for me:)