Ignition icon indicating copy to clipboard operation
Ignition copied to clipboard

Write a request utility

Open kirrg001 opened this issue 8 years ago • 3 comments

We would like to write a request utility, which covers all the pain points we experienced in the past. So by that we have a centralised utility for external requests available.

Each Ghost and other internal projects have multiple custom implementations to send a request to an external resource. It happened a couple of times now, that we fall into the same traps over and over again, because we start with fresh custom implementations again and again and forget about covering the pain points 😬

These pain points were:

  • socket timeout handling
  • follow redirects handling
  • retries logic

kirrg001 avatar Jun 15 '17 13:06 kirrg001

I really like this idea, and was wondering if you had any idea how you wanted to do it. Did you want to build our own lightweight wrapper around http and https, or are you thinking about depending on a 3rd party?

I removed request from Ghost because it is a huge dependency and we were barely using it. However, I appreciate this leaves us open to having to work around all of these special cases and that it might be better to have a 3rd party do heavy-lifting for us again.


With this in mind, I have been researching 3rd party modules to see if any of them might be useful for my current project, where I need to regularly talk to 3rd party JSON APIs. I stumbled across npm compare, and put together this comparison of axios, got, needle, request & superagent.

IMO our requirements are probably something like:

  • very lightweight
  • uses promises, preferably via Bluebird
  • can handle JSON responses
  • can do http or https
  • handles timeouts cleanly
  • option to follow redirects
  • has retries logic

For clarity, using bluebird promises is important because when handling responses across APIs it is very very useful to use Bluebird's catch predicates, which ES6 promises don't yet have. However, It is relatively trivial for us to choose a library that does or doesn't use Promises and then wrap it in Bluebird here in Ghost-Ignition ready for all the dependent projects to use.

With all this in mind, I poked around the various repos and I have to say that got, which I hadn't heard of, jumped out at me.

It's 3 years old, it's well maintained and it seems to be heavily used. It also has clear options documented in the readme for timeouts, retries, redirects and JSON mode. The library itself is just 12kb but it does depend on 13 other modules.

The module itself is also Promise based, but uses native promises. However, whilst investigating I stumbled across this issue which suggests setting global.Promise = require('bluebird'); in order to resolve this. I hadn't realised it was that simple! Seems like this would be a smart thing to do in Ghost's overrides, so that every library automatically gets our preferred Promise library.

All the other options are either too big (request), under maintained (needle) or don't have the features we want (axios, superagent). IMO got would be the best option if we did want to use a 3rd party instead of rolling our own.

Still, the proof is in the pudding, so I'm going to test it out in my project for a bit. If it's as good as it looks, perhaps I can then abstract out what I build into Ignition?

ErisDS avatar Jun 23 '17 17:06 ErisDS

Wow such a nice and detailed reply, thanks 👍

With all this in mind, I poked around the various repos and I have to say that got, which I hadn't heard of, jumped out at me.

me2, never ever heard of it 😀 Cool that you have spotted it.

global.Promise = require('bluebird');

I've read about it quickly and it looks like it's officially supported, see and see.

Seems like this would be a smart thing to do in Ghost's overrides

Hmmmmm if Ignition creates a wrapper around got and we would like to use multiple catch predicates by default to handle all what we need, then Ignition would need to override the native Promise? This is just a thought i am leaving here for you.

Still, the proof is in the pudding, so I'm going to test it out in my project for a bit. If it's as good as it looks, perhaps I can then abstract out what I build into Ignition?

cool 👍

kirrg001 avatar Jun 23 '17 18:06 kirrg001

Ghost has it's own "got" request handler, which we could move to Ignition.

kirrg001 avatar May 09 '19 21:05 kirrg001