serverless-apigw-binary icon indicating copy to clipboard operation
serverless-apigw-binary copied to clipboard

Updates API Gateway but PNG images are still base64 encoded.

Open richburdon opened this issue 6 years ago • 10 comments

The plugin successfully updates the API Gateway's binary support types, but when I try to serve PNG files from aws-serverless-express I'm still getting base64 encoded data returned from:

  app.use('/static', express.static(ENV.STATIC_DIR));

If I explicitly add an accept header with image/png then the correct image data is returned, but I can't do that from an <img/> tag.

Any suggestions? (seems like a popular issue):

https://forum.serverless.com/t/returning-binary-data-jpg-from-lambda-via-api-gateway/796 https://forum.serverless.com/t/force-return-of-binary-response-ignoring-accept-header/1299 https://github.com/maciejtreder/serverless-apigw-binary/issues/33 https://github.com/awslabs/aws-serverless-express/issues/39 https://github.com/awslabs/aws-serverless-express/issues/99 https://github.com/awslabs/aws-serverless-express/issues/104

richburdon avatar Nov 02 '17 15:11 richburdon

Yeah I'd love to know as well. This sounds like an issue with the API Gateway though, right? I think it doesn't understand that given a generic Accept: */* header, it should decode the base64.

What I really don't get is that, if I return isBase64Encoded: true in the callback, the API gateway should just take it and decode it. It's never okay not to...

Doesn't work:

  • Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  • Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/png;q=0.8
  • Accept: */*

Works:

  • Accept: image/png
  • Accept: image/png;q=0.8

jleclanche avatar Dec 17 '17 15:12 jleclanche

Note that the following works around it if you always return binary:

custom:
  apigwBinary:
    types:
      - "*/*"

jleclanche avatar Dec 17 '17 15:12 jleclanche

You got to be kidding. I spend so much time on this. URG...

To provide some value: It will work if you change the endpoint to end with e.g. ".png".

simlu avatar Feb 04 '18 01:02 simlu

What I really don't get is that, if I return isBase64Encoded: true in the callback, the API gateway should just take it and decode it. It's never okay not to...

Agreed.

Note that the following works around it if you always return binary:

custom:
  apigwBinary:
    types:
      - "*/*"

I experienced the same problem here. @jleclanche's suggestion was the only fix that was reliable and reasonable.

If it's effectively necessary to specify */* as the accepted type to get this plugin to work for most file types, why not have the plugin just default the types to ['*/*'] (thereby avoiding the need to add a custom block to configure it)?

Let me know if a PR would be welcome to make */* the default type. I'm happy to submit one.

rmm5t avatar Mar 04 '18 15:03 rmm5t

Let me know if a PR would be welcome to make */* the default type. I'm happy to submit one.

@rmm5t I would advise against doing that. I just implemented this plugin in an already working service with other unrelated endpoints. Everything stopped working and I couldn't figure out why. Turns out that by using types:'*/*' i was now base64 encoding all my other payloads. I reverted back and things went back to normal.

I guess that's where @jleclanche's " if you always return binary" comes from

jesusgollonet avatar Nov 08 '18 14:11 jesusgollonet

@jesusgollonet Can't you change your endpoint name to end with the image extension you're serving?

simlu avatar Nov 08 '18 14:11 simlu

yeah, that's what i'm doing now. my comment was that making '*/*' the default would lead to confusion when integrating this into projects

jesusgollonet avatar Nov 08 '18 14:11 jesusgollonet

fwiw, in case someone runs into the same... (hope it's ok to post here) As far as I can tell, using */* is the only workable solution if you want to serve images to be embedded in img tags, even using a path that ends in .png

The closest thing I got to avoid having to split my image service into a different one was adding the image extension and using image/* as a mime type. That works very well.. in chrome. Firefox and safari are actually sending */* for img requests.

So until API Gateway starts honoring isBase64Encoded : true regardless of the Accept header, integrating binary responses into a bigger service should be avoided or at least taken with good care (I've had to split the image service into a new one)

jesusgollonet avatar Nov 08 '18 16:11 jesusgollonet

In my case / did not work. Browser was calling with image/webp,image/apng,image/*,*/*;q=0.8 accept header. I suppose */* did not match the header value. Changing to image/* worked for me.

Townsheriff avatar Jan 27 '20 14:01 Townsheriff

This does not work. I cannot post json to any other functions with this plugin? Does anyone have a solutions for this.

jonathanalberghini avatar Jul 27 '20 15:07 jonathanalberghini