DrDirk
DrDirk

Reputation: 1997

Serverless Api Gateway Proxy Lambda with Axios to serve binary files (PDF)?

I am using serverless and axios to "passthrough" a PDF generated by the stampery api, which needs credentials I do not want to save client-side.

In principle I get the PDF as an arraybuffer from axios, transform the arraybuffer to an buffer, which I then use to create a base64 string, needed by API Gateway binary treatment, which can be "activated" by including the isBase64Encoded: true property in the callback response object.

The following code yields an empty PDF:

const axios = require('axios');

const stamperyClientId = 'xxx';
const stamperySecret = 'xxx';

const stampery = axios.create({
  baseURL: 'https://api-prod.stampery.com',
  auth: {
    username: stamperyClientId,
    password: stamperySecret
  }
});

module.exports.hello = (event, context, callback) => {
  const response = {
    statusCode: 200,
    headers: {
      'Content-Type' : 'application/pdf',
      'Content-Disposition': 'inline; filename="certificate.pdf"'
    },
    isBase64Encoded: true
  };

  stampery.get(`/stamps/5b2a612680e0190004bcccc8.pdf`, {
    responseType: 'arrayBuffer',
  })
    .then(res => {
      const buffer = Buffer.from(res.data)
      const base64Str = buffer.toString('base64')
      response.body = base64Str
      callback(null, response);
    })
};

The PDF is retrieved by: `curl https://xxx.execute-api.eu-west-1.amazonaws.com/dev/certificate -o my.pdf -H "Accept: application/pdf"

I tested the setup with fileReadSync, which turned out fine:

module.exports.hello = (event, context, callback) => {
  const content = fs.readFileSync("data/sample.pdf");

  const response = {
    statusCode: 200,
    headers: {
      "Content-Type": "application/pdf",
      "Content-Disposition": "inline; filename=\"sample.pdf\""
    },
    body: content.toString("base64"),
    isBase64Encoded: true
  };

  return callback(null, response);
};

What am I missing? Is this the right way to transform an axios arraybufferinto a base64 string?

P.S. My serverless.yml is given by:

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: certificate.pdf
          method: get
    package:
      include:
        - data/sample.pdf

resources:
  Resources:
    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        Name: dev-stamper
        BinaryMediaTypes:
          - "application/pdf" # or whichever ones you need

where I already thought of the necessary binary media types.

Upvotes: 1

Views: 1194

Answers (1)

DrDirk
DrDirk

Reputation: 1997

Ok... the error was a simple typo. I wrote arraybuffer in camel case arrayBuffer, so Axios returned a string instead of an arraybuffer.

Change this line:

 stampery.get(`/stamps/5b2a612680e0190004bcccc8.pdf`, {
    responseType: 'arrayBuffer',
  })

to

 stampery.get(`/stamps/5b2a612680e0190004bcccc8.pdf`, {
    responseType: 'arraybuffer',
  })

and everything works as a charm...

Upvotes: 2

Related Questions