dwww Home | Show directory contents | Find package

# Advanced creation

> Make calling REST APIs easier by creating niche-specific `got` instances.

### Merging instances

Got supports composing multiple instances together. This is very powerful. You can create a client that limits download speed and then compose it with an instance that signs a request. It's like plugins without any of the plugin mess. You just create instances and then compose them together.

To mix them use `instanceA.extend(instanceB, instanceC, ...)`, that's all.

## Examples

Some examples of what kind of instances you could compose together:

#### Denying redirects that lead to other sites than specified

```js
const controlRedirects = got.extend({
        handlers: [
                (options, next) => {
                        const promiseOrStream = next(options);
                        return promiseOrStream.on('redirect', response => {
                                const host = new URL(resp.url).host;
                                if (options.allowedHosts && !options.allowedHosts.includes(host)) {
                                        promiseOrStream.cancel(`Redirection to ${host} is not allowed`);
                                }
                        });
                }
        ]
});
```

#### Limiting download & upload size

It can be useful when your machine has limited amount of memory.

```js
const limitDownloadUpload = got.extend({
        handlers: [
                (options, next) => {
                        let promiseOrStream = next(options);
                        if (typeof options.downloadLimit === 'number') {
                                promiseOrStream.on('downloadProgress', progress => {
                                        if (progress.transferred > options.downloadLimit && progress.percent !== 1) {
                                                promiseOrStream.cancel(`Exceeded the download limit of ${options.downloadLimit} bytes`);
                                        }
                                });
                        }

                        if (typeof options.uploadLimit === 'number') {
                                promiseOrStream.on('uploadProgress', progress => {
                                        if (progress.transferred > options.uploadLimit && progress.percent !== 1) {
                                                promiseOrStream.cancel(`Exceeded the upload limit of ${options.uploadLimit} bytes`);
                                        }
                                });
                        }

                        return promiseOrStream;
                }
        ]
});
```

#### No user agent

```js
const noUserAgent = got.extend({
        headers: {
                'user-agent': undefined
        }
});
```

#### Custom endpoint

```js
const httpbin = got.extend({
        prefixUrl: 'https://httpbin.org/'
});
```

#### Signing requests

```js
const crypto = require('crypto');

const getMessageSignature = (data, secret) => crypto.createHmac('sha256', secret).update(data).digest('hex').toUpperCase();
const signRequest = got.extend({
        hooks: {
                beforeRequest: [
                        options => {
                                options.headers['sign'] = getMessageSignature(options.body || '', process.env.SECRET);
                        }
                ]
        }
});
```

#### Putting it all together

If these instances are different modules and you don't want to rewrite them, use `got.extend(...instances)`.

**Note**: The `noUserAgent` instance must be placed at the end of chain as the instances are merged in order. Other instances do have the `user-agent` header.

```js
const merged = got.extend(controlRedirects, limitDownloadUpload, httpbin, signRequest, noUserAgent);

(async () => {
        // There's no 'user-agent' header :)
        await merged('/');
        /* HTTP Request =>
         * GET / HTTP/1.1
         * accept-encoding: gzip, deflate, br
         * sign: F9E66E179B6747AE54108F82F8ADE8B3C25D76FD30AFDE6C395822C530196169
         * Host: httpbin.org
         * Connection: close
         */

        const MEGABYTE = 1048576;
        await merged('https://ipv4.download.thinkbroadband.com/5MB.zip', {downloadLimit: MEGABYTE, prefixUrl: ''});
        // CancelError: Exceeded the download limit of 1048576 bytes

        await merged('https://jigsaw.w3.org/HTTP/300/301.html', {allowedHosts: ['google.com'], prefixUrl: ''});
        // CancelError: Redirection to jigsaw.w3.org is not allowed
})();
```

Generated by dwww version 1.15 on Thu May 23 02:19:56 CEST 2024.