Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

I'm not clear if fetch.js is using gzip compression by default, or if I need to manually compress and add headers. Any help would be appreciated.

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;
        });
      }
    });
});
like image 403
shackleton Avatar asked Aug 29 '17 15:08

shackleton


2 Answers

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;
          });
        }
      });
  });
});
like image 199
Motin Avatar answered Sep 19 '22 09:09

Motin


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});
like image 44
Chris Adams Avatar answered Sep 22 '22 09:09

Chris Adams