shackleton
shackleton

Reputation: 793

Enabling gzip compression with fetch.js

I'm using fetch.js (https://github.com/github/fetch) to send a relatively large json object to the backend. The json is large in that it include an SVG image string.

Does fetch.js use gzip compression by default, or do I need to manually compress and add headers?

return new Promise((resolve, reject) => {
  fetch(api_base + "/api/save-photo", {
    method: 'POST',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  })
    .then((response) => {
      if (response.status === 404) {
        throw new Error('404 (Not Found)');
      } else {
        return response.json().then((json) => {
          console.log('save poster response: ', json);
          return json;
        });
      }
    });
});

Upvotes: 17

Views: 24909

Answers (2)

Motin
Motin

Reputation: 5053

Use https://github.com/nodeca/pako (a faster port of zlib).

Add the following import:

import { gzip } from 'pako';

Then, change:

body: JSON.stringify(payload)

To:

body: await gzip(JSON.stringify(payload))

And add the header:

'Content-Encoding': 'gzip',

Or, if you don't use the await/async syntax, your example code becomes:

return new Promise((resolve, reject) => {
  gzip(JSON.stringify(payload)).then((gzippedBody) => {
    fetch(api_base + "/api/save-photo", {
      method: 'POST',
      mode: 'cors',
      headers: {
        'Content-Encoding': 'gzip',
        'Content-Type': 'application/json'
      },
      body: gzippedBody
    })
      .then((response) => {
        if (response.status === 404) {
          throw new Error('404 (Not Found)');
        } else {
          return response.json().then((json) => {
            console.log('save poster response: ', json);
            return json;
          });
        }
      });
  });
});

Upvotes: 10

Chris Adams
Chris Adams

Reputation: 1454

I'm assuming that with your line of

body: JSON.stringify(payload)

that payload isn't compressed.

I also wanted to be able to zip/compress a payload body and I also need an async approach to fit with the rest of my code. The bit I was struggling with was finding a way to use zlib without callbacks.

To achieve this, I did the following....

In a separate help library, I import zib...

import zlib from 'zlib'

I created the following functions....

async function asyncCompressBody(body) {

    const compressedData = await compressBody(body);
    console.log("Data Compressed");

    return compressedData;

}

function compressBody(body) {

    return new Promise( function( resolve, reject ) {

        zlib.deflate(body, (err, buffer) => {
            if(err){
                console.log("Error Zipping");
                reject(err);
            }

            console.log("Zipped");

            resolve(buffer);
        });
    });

}

The compressBody function is a promise around zlib.deflate. The function asyncCompressBody is an async function that allows the calling function to await.

In the calling function, I use it as...

let compressedBody = await asyncCompressBody(jsonContent);

let headers = new Headers();
headers.append("Content-Type","application/json");
headers.append("Content-Encoding","zlib");

const response = await fetch(url,
    {method: 'POST',
    headers:headers,
    body:compressedBody});

Upvotes: 3

Related Questions