0.1.3 • Published 2 years ago

grb v0.1.3

Weekly downloads
4
License
MIT
Repository
-
Last release
2 years ago

gr(a)b

Yet another HTTP library, and an attempt to bring the simplicity of got 9.x back.

Once great, I believe got turned unwieldy for the simple usecases it was meant to make easier than ever.

$ npm install grb

Learn by example

const grab = require('grb');
// import grab from 'grb'; works too

// Basic GET
const response = await grab('https://google.com');
console.log('HTML', response.body);
// response.headers is a Map with case-insensitive get methods
// .getAll returns an array with all values of a given header
console.log('Headers', response.headers.getAll('Set-Cookie'));

// Query parameters and explicit method
// If you use the `query` field, query params in the url will be ignored
const response = await grab('https://www.google.com/search', {
    method: 'GET',
    query: {
        q: 'example'
    }
});

// Parse JSON and extract body
const { body } = await grab('https://jsonplaceholder.typicode.com/todos/1', {
    json: true
});
console.log('JSON', body);

// Basic POST
await grab.post('https://example.com', {
    body: 'any payload! But there are better ways for forms and json payloads'
});

// If body is an object, it will be parsed as JSON and the Content-Type header will be set to application/json
await grab.post('https://example.com', {
    body: {
        hello: 'there',
        'obi-wan': 'kenobi'
    }
});

// Form payloads can also be used, just use the form field for the payload
const { body: message } = await grab.post('https://discordapp.com/api/v6/channels/505815497598828570/messages', {
    form: {
        content: 'forms are versatile',
        file: fs.createReadStream('kitten.png')
    },
    headers: {
        authorization: 'Discord token'
    },
    json: true
});

console.log(message);

// You could also just pass a FormData instance to body!

// Cookies
// You could extract this to a file, like http.js, and require it directly from other files
// They will all share a single CookieJar
// This pattern is common when creating adapter classes, but with .defaults, a complete class is often overkill
const { CookieJar } = require('tough-cookie');
const instance = grab.defaults({
    jar: new CookieJar()
});

await instance('https://google.com');
console.log('Cookies', instance.jar.toJSON());

Voila! Now you should be armed to use this library to your heart's content. Everything else you should be able to figure out through IntelliSense; it's all TypeScript. Go on and make something awesome.

FAQ

Why yet another HTTP library?

  1. Personal challenge. I wanted to make one, and so I did
  2. Have a simple library that makes the most common interactions easy. This rules out fluid interfaces; nobody wants to remember to .send() requests manually
  3. While not a primary objective, keep the bundle size small and competitive. install size (about one third of got, but 10 times bigger than phin or centra because they don't include form-data integration)
  4. Have a simple and easy to remember API, that won't change over time. No need to re-learn everything, and the less keystrokes, the better. This means that nearly everything is done with a single function call. This also means that it doesn't ship with stream support or a callback interface; it's all done with promises.
  5. Don't make awkward API decisions, like fetch, with their chained Response.json() method looking weird with async/await, or got's .json() method that can be called on a Promise object directly. Sure, you can get used to them, but you shouldn't have to.
  6. I found the grb name was available by chance, and it honestly sounded great for a got successor and an http library. You want something off the internet? Just grb it.

Callbacks?

No.

Streams?

Someday. Perhaps around the same time I add progress indicators. Are those often used? Do people really download and upload big files through node often, and show some indicator to the user? I don't know

Caching?

Not yet, most Node programs often just want the freshest data there is, but perhaps if we were available for client-side code.

Cancelation?

Yikes, I should add that eventually, response.abort() is fairly easy to implement, although impaling the returned Promise object with a cancel method sounds icky to me... We'll see.

0.1.0

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.3

2 years ago

0.0.28

4 years ago

0.0.26

4 years ago

0.0.25

4 years ago

0.0.22

4 years ago

0.0.23

4 years ago

0.0.24

4 years ago

0.0.21

4 years ago

0.0.20

4 years ago

0.0.18

4 years ago

0.0.19

4 years ago

0.0.17

4 years ago

0.0.16

4 years ago

0.0.15

4 years ago

0.0.14

4 years ago

0.0.12

4 years ago

0.0.13

4 years ago

0.0.11

4 years ago

0.0.10

4 years ago

0.0.9

4 years ago

0.0.8

4 years ago

0.0.3

4 years ago

0.0.5

4 years ago

0.0.4

4 years ago

0.0.7

4 years ago

0.0.6

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago