Git Product home page Git Product logo

s3-resizer's Introduction

What is it?

It's AWS Lambda, which is a compute service that lets you run code without provisioning or managing servers.

Read more about AWS Lambda.

Demo

https://sagidm.github.io/smartuploader/examples/4.s3-resizer.html

What this lambda provides

Let's say we have some shared image in S3, for example:
https://example.com/images/pretty_photo.jpg

to resize on fly this image to, say, 150x150, we can make a request like this:
https://example.com/images/150x150/pretty_photo.jpg

So, if there's not image in this path, it's redirected to lambda and, after a moment, lambda creates the suitable image and then redirects back. We'll obviously have a new image next time.


Instead of WxH there're some extra available magic paths:
.../AUTOx150/...
.../150xAUTO/...
or
.../150x150_max/...
.../150x150_min/...

Note that s3-resizer does not enlarge an image if the original image width or height are less than the requested dimensions. You can read about withoutEnlargement method.

Setting up

To resize images we need a storage, which is S3 (but could be CloudFront), and Lambda function. Then we should set up all the permissions and redirection rules.

  • Create a Bucket

    • Click on the blue button Create bucket
    • Enter the name and click on Create
  • Create a Lambda

    • Create a function -> Author from scratch
    • Enter a name (e.g. s3-resizer)
    • Select the latest version of Node.js according to Releases (you can change it later)
    • You need a role that has permission to put objects to your storage (aka policy). If you click on Create function, a default role will be created. You can edit it later or you can create and set up a role right now. To do that,
      • then Create role -> Lambda -> Next: Permissions -> Create policy, a new tab should open
      • on that tab, you can use Visual Editor or add this JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::__BUCKET_NAME__/*"
    }
  ]
}

Pay attention to __BUCKET_NAME__

      • Name your policy, for example: "access_to_putObject_policy" and click on Create policy; you can close the tab
      • On the previous tab, update the policy list clicking on the button with reload image or reloading the page.
      • Select your policy clicking on the checkbox
      • Click on Next: tags -> Next: Review, name your role, for example, "access_to_putObject_role"
      • Click on Create role; you can close the tab.
    • Now you are again on the lambda creating page.
    • Select Use an existing role and choose your role in the list, update the list if necessary.
    • After clicking on Create function, the lambda should be created.
  • Add a trigger, which will listen to http requests

    • YOUR_LAMBDA -> Add trigger -> API Gateway
    • You can select api that has prefix -API or Create a new API
    • In Security, select Open, then click Add
    • Now if you click on API Gateway, you should see API endpoint, something like
      https://some-id.execute-api.eu-central-1.amazonaws.com/your-stage/your-lambdas-name
  • Set up Static website hosting

    • Having an API endpoint, go to your bucket created at the beginning and add permissions
      • YOUR_BUCKET -> Permissions -> Block public access -> Edit, uncheck Block all public access, Save -> Confirm
      • YOUR_BUCKET -> Permissions -> Bucket policy and paste
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::__BUCKET_NAME__/*"
        }
    ]
}

Pay attention to __BUCKET_NAME__. By the way, you are able to give an access not only to the whole bucket but also to a specific directory providing its path instead of *.

    • Go to Properties (next to Permissions) -> Static website hosting -> Select "Use this bucket to host a website"
    • In Index document paste any file, it'd be logical to name it "index.html"
    • Paste this Redirection rules
[
  {
    "Condition": {
      "HttpErrorCodeReturnedEquals": "404"
    },
    "Redirect": {
      "Protocol": "https",
      "HostName": "__DOMAIN__",
      "ReplaceKeyPrefixWith": "__PATH_TO_LAMBDA__?path=",
      "HttpRedirectCode": "307"
    }
  }
]

Pay attention to __DOMAIN__ and __PATH_TO_LAMBDA__ (protocol is always https)
This is your API endpoint. For example, if the url is https://some-id.execute-api.us-east-1.amazonaws.com/your-stage/your-lambdas-name, the correct xml nodes shall look like

<HostName>some-id.execute-api.us-east-1.amazonaws.com</HostName>
<ReplaceKeyPrefixWith>your-stage/your-lambdas-name?path=</ReplaceKeyPrefixWith>
    • At this state, before clicking on Save, copy your Endpoint. Do not mix it up. This is an endpoint of your Static website hosting, and it is http, not https.
  • Add s3-resizer.zip and make lambda work

    • Go to your lambda and select Lambda layer (presumably, the API Gateway layer was selected instead)
    • Function code -> Code entry type -> Upload a .zip file upload a zip file
    • In Runtime, select the latest version of Node.js that you found on Releases
    • [You can now click on Save to save your time because it takes a while to upload a zip file]
    • Set up the following Environment variables (format: key=value)
      BUCKET=your bucket's name
      URL=Endpoint you copied before (from Static website hosting)
      WHITELIST=your list (space-separated) of allowed size options (e.g. AUTOx150 300x200 100x100_max). This parameter is optional, if not provided, the lambda will process everything
    • In Basic settings
      • Allocate 768mb memory
      • Timeout could be 5 seconds

It's mooore than enough. But you shouldn't care of limits because images cache, which means the lambda is called only for the first time. For example, large png 29mb image converts to 150x150 in 1.8s with 1024mb memory allocated, 2.3 with 768, 3.5 with 512mb, and ~7s with 256 on Node.js 12.13. (I guess these such different results is because of GC). For normal images, results are nearly the same (400-700 mls).

    • Save it. You are done!

  • Test your lambda (optional)
    • Upload an image to your bucket and copy the full path to it. Check whether the image shows in your browser entering "ENDPOINT/FULL_PATH"

Attention. Endpoint is your Static website hosting (http). If you added the image to the root of your bucket, than FULL_PATH should be just a name of the image.

    • Go to lambda, click on Test, and paste this json:
{
  "queryStringParameters": {"path": __YOUR_IMAGE_PATH_WITH_SIZE_PREFIX__}
}

__YOUR_IMAGE_PATH_WITH_SIZE_PREFIX__ - for example: 150x150/pretty_image.jpg

    • Go back to the bucket, a new directory 150x150 must be created

How to use HTTPS

The Amazon S3 website endpoints do not support HTTPS
https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
As a workaround, you have to use your own domain.
Please check out #7

s3-resizer's People

Contributors

adamivancza avatar kofon95 avatar matheusflausino avatar muhammadreda avatar nelsonamaya82 avatar sagidm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

s3-resizer's Issues

"Access Denied" in the brower

I can test successful in Lambda , but I test in my chrome brower and the system return "Access Denied". Could help me? Thanks !!

AccessDenied
Access Denied
E6BC853F822F087E

0W84WFaXXRCdQnZa1DWRSzQc0/LRijPbqjqSKf4tejzoXHmwF1nq9c42yWfXJa10i6CWmpBaO88=

"errorMessage": "Error: Cannot find module 'sharp'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",

{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'sharp'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
"trace": [
"Runtime.ImportModuleError: Error: Cannot find module 'sharp'",
"Require stack:",
"- /var/task/index.js",
"- /var/runtime/UserFunction.js",
"- /var/runtime/index.js",
" at _loadUserApp (/var/runtime/UserFunction.js:100:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
" at Object. (/var/runtime/index.js:43:30)",
" at Module._compile (internal/modules/cjs/loader.js:1015:30)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:1035:10)",
" at Module.load (internal/modules/cjs/loader.js:879:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:724:14)",
" at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)",
" at internal/main/run_main_module.js:17:47"
]
}

AccessDenied

Great library by the way, it works great in the root of the buckets ,

but when i created folder inside the backet and upload new image to this sub folder when i tried to resize it using the fill path
https://lockcommerce.s3.me-south-1.amazonaws.com/187hdk3783-34345/50x50/img.png
the sub folder name : 187hdk3783-34345 ( cause i want to create folder for each customer .

i received this error

AccessDenied Access Denied F59E7CC0FF72CEA3 5L5me6BP8S9Xk8qH9XeYBk1WvXobMz91MO/oCDVlXgad+5bgG7/CWWPy+C1dlk5IOpB4YctAWbY=

please help .

npm module error

ran through the install steps, ran into an issue when running my test:

{ "errorMessage": "The module '/var/task/node_modules/sharp/build/Release/sharp.node'\nwas compiled against a different Node.js version using\nNODE_MODULE_VERSION 48. This version of Node.js requires\nNODE_MODULE_VERSION 57. Please try re-compiling or re-installing\nthe module (for instance, using npm rebuildornpm install).", "errorType": "Error", "stackTrace": [ "NODE_MODULE_VERSION 48. This version of Node.js requires", "NODE_MODULE_VERSION 57. Please try re-compiling or re-installing", "the module (for instance, using npm rebuildornpm install).", "Object.Module._extensions..node (module.js:681:18)", "Module.load (module.js:565:32)", "tryModuleLoad (module.js:505:12)", "Function.Module._load (module.js:497:3)", "Module.require (module.js:596:17)", "require (internal/module.js:11:18)", "Object.<anonymous> (/var/task/node_modules/sharp/lib/constructor.js:10:15)", "Module._compile (module.js:652:30)", "Object.Module._extensions..js (module.js:663:10)", "Module.load (module.js:565:32)" ] }

Access Denied

Upon testing it. The lambda test shows this error.

image

AWS end support for Node.js 8.x

I received the following email from AWS - do you intend to rebuild using 10?


Hello,

We are contacting you as we have identified that your AWS Account currently has one or more Lambda functions using Node.js 8.10, which will reach its EOL at the end of 2019.

What’s happening?

The Node community has decided to end support for Node.js 8.x on December 31, 2019 [1]. From this date forward, Node.js 8.x will stop receiving bug fixes, security updates, and/or performance improvements. To ensure that your new and existing functions run on a supported and secure runtime, language runtimes that have reached their EOL are deprecated in AWS [2].

For Node.js 8.x, there will be 2 stages to the runtime deprecation process:

  1. Disable Function Create – Beginning January 6, 2020, customers will no longer be able to create functions using Node.js 8.10

  2. Disable Function Update – Beginning February 3, 2020, customers will no longer be able to update functions using Node.js 8.10

After this period, both function creation and updates will be disabled permanently. However, existing Node 8.x functions will still be available to process invocation events.

What do I need to do?

We encourage you to update all of your Node.js 8.10 functions to the newer available runtime version, Node.js 10.x[3]. You should test your functions for compatibility with the Node.js 10.x language version before applying changes to your production functions.

Whitelist sizes to resize

It would be quite annoying if someone was to create various sizes of different images.

Is there a way to white list only a few specific image sizes?

Missing module Sharp?

Forgive my lack of knowledge on AWS - i'm kind of a newbie but when i try to test the lambda the following gets returned - is there a missing module or do i need to do anything additional to your tutorial? Thank you! Any help is appreciated.

Response:
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'sharp'",
"trace": [
"Runtime.ImportModuleError: Error: Cannot find module 'sharp'",
" at _loadUserApp (/var/runtime/UserFunction.js:100:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
" at Object. (/var/runtime/index.js:45:30)",
" at Module._compile (internal/modules/cjs/loader.js:778:30)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)",
" at Module.load (internal/modules/cjs/loader.js:653:32)",
" at tryModuleLoad (internal/modules/cjs/loader.js:593:12)",
" at Function.Module._load (internal/modules/cjs/loader.js:585:3)",
" at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)",
" at startup (internal/bootstrap/node.js:283:19)"
]
}

Request ID:
"a9d515ef-c4a3-4b8b-ba30-f8d2c643bc0b"

Function Logs:
START RequestId: a9d515ef-c4a3-4b8b-ba30-f8d2c643bc0b Version: $LATEST
2020-03-31T13:40:02.304Z undefined ERROR Uncaught Exception {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'sharp'","stack":["Runtime.ImportModuleError: Error: Cannot find module 'sharp'"," at _loadUserApp (/var/runtime/UserFunction.js:100:13)"," at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)"," at Object. (/var/runtime/index.js:45:30)"," at Module._compile (internal/modules/cjs/loader.js:778:30)"," at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)"," at Module.load (internal/modules/cjs/loader.js:653:32)"," at tryModuleLoad (internal/modules/cjs/loader.js:593:12)"," at Function.Module._load (internal/modules/cjs/loader.js:585:3)"," at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)"," at startup (internal/bootstrap/node.js:283:19)"]}
END RequestId: a9d515ef-c4a3-4b8b-ba30-f8d2c643bc0b
REPORT RequestId: a9d515ef-c4a3-4b8b-ba30-f8d2c643bc0b Duration: 763.36 ms Billed Duration: 800 ms Memory Size: 768 MB Max Memory Used: 30 MB
Unknown application error occurred
Runtime.ImportModuleError

HTTPS problem

Hi!

I've got the resizing working, but Lambda is not working on HTTPS.
I can reach my original (public) S3 image on
https://[bucket].s3.eu-north-1.amazonaws.com/[image].jpg and
http://[bucket].s3.eu-north-1.amazonaws.com/[image].jpg

And resized via Lambda on HTTP
http://[bucket].s3-website.eu-north-1.amazonaws.com/300x300/[image].jpg
But on on HTTPS
https://[bucket].s3-website.eu-north-1.amazonaws.com/300x300/[image].jpg
That just times out.

Though, when I have used Lambda over HTTP I can reach via HTTPS directly through S3.

Any ideas?

AWS end support for Node.js 16

I received the following email from AWS - do you intend to rebuild using 16?

Hello,

We are contacting you as we have identified that your AWS Account currently has one or more Lambda functions using Node.js 12 runtime.

We are ending support for Node.js 12 in AWS Lambda. This follows Node.js 12 End-Of-Life (EOL) reached on April 30, 2022 [1].

As described in the Lambda runtime support policy [2], end of support for language runtimes in Lambda happens in two stages. Starting November 14, 2022, Lambda will no longer apply security patches and other updates to the Node.js 12 runtime used by Lambda functions, and functions using Node.js 12 will no longer be eligible for technical support. In addition, you will no longer be able to create new Lambda functions using the Node.js 12 runtime. Starting December 14, 2022, you will no longer be able to update existing functions using the Node.js 12 runtime.

We recommend that you upgrade your existing Node.js 12 functions to Node.js 16 before November 14, 2022.

index.handler is undefined or not exported

I followed readme file and I've done everything that @sagidM said in the readme file.

node version is: 12.x
Handler: index.handler
.zip file: s3-resizer-3.1.0.zip (download zip from your repo.)

Still, I'm getting below error when I run the test.

test json is

{
  "queryStringParameters": {
    "path": "150x150/engg.jpg"
  }
}

lambda_error

Cyclic redirect with CloudFront

Hello,

The Lambda function is working well, but I have cyclic redirect when trying to configure it with CloudFront.

I created a CloudFront distribution with default settings and used S3's static website endpoint as the origin. Also, I used the CloudFront domain name for the URL Lambda envonment variable.

Existing images are served well. But for new images I receive redirects loop between API gateway and CloudFront. What is interesting, new image generated and accessible with S3's endpoint. Can't get what is wrong.

Any ideas on how to fix it?
Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.