Amazon CloudFront custom origin configuration - amazon-web-services

I'd like CloudFront to first search S3 for a file, defaulting to my custom server if the image is not found. Is this possible?

Unfortunately CloudFront does not have a flexible fallback mechanism.
Depending on your specific use case, you could use an alternate approach where you configure CloudFront to pass all traffic trough your custom server and configure the server to proxy the request to S3 by default and, if that fails, to serve a local copy of the file.
It's also possible that, instead of actually proxying the content from S3, you just configure your server to redirect to the S3 object if it exists, to reduce the traffic that goes trough your server.
Another approach, that could possibly apply if you have a CloudFront distribution dedicated to serving images, is to set your S3 bucket as the distribution's origin and configure a custom error page for 404 errors to serve a default image that's also hosted on S3. For this approach, see:
http://aws.typepad.com/aws/2013/09/custom-error-pages-and-responses-for-amazon-cloudfront.html

You could to try and set it up as a reverse proxy. I haven't tested it, but it falls back to your domain if the asset is missing. Who knows what the 'break' would be that you would need a fallback. But this would help in a number of cases, such as a new admin accidentally deleting your cloudfront bucket.

Related

AWS CloudFront and ELB: requests doesn't reach backend

Get into quite strange trouble. Have an Cloudfront distribution with two origins: S3 and ELB.
I've set behaviors for Default () and the Custom (/test-request).
On ELB side there is a rule to forward request from my domain to certain backend. Domain also added as an alias for cloudfront distribution.
But anytime I try to reach https://my.domain/test-request I've got... nothing. Looks like all request go to S3 content and never reach the backend I need.
I've already play with options on behavior side, read a lot of tutorials, but still no luck.
I'm not searching for clear answers, but at least I need direction of my research.
I'm assuming your Cloudfront distribution configuration is
/test-request to your ELB as first priority
Default (*) to your S3 as the catch-all
my.domain is mapped to your Cloudfront's CNAME correctly
When you try to access my.domain/test-request, Cloudfront will match your cache behavior and forwards to your ELB, together with the path /test-request.
Please note that it does NOT strip the /test-request path from your original request.
Your ELB then forwards the original request to your application server, using the path /test-request.
Therefore, it's likely that your application does not expose any resource or API under the path /test-request, and the request fails as a result.
Also, since you are in this topic, please note that by default, Cloudfront does not forward query parameters or browser cookie to your custom origin which is ELB in your case. If you want to capture them, you need to configure the cache behavior properly.
Refs:
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesPathPattern
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesQueryString

AWS unable to enforce https for S3 bucket

I have tried several tutorials on how to set up https via CloudFront, but nothing is working. I am hosting from an S3 bucket and the app works fine via the http protocol, but I need it to be https.
Does anyone have a very thorough tutorial on how to make this work?
Some tutorials explain how to go about setting up a certificate, some explain how to use CloudFront to handle its distribution and I even found a CloudFront tutorial that explains how not using a link from the CloudFront setup forces the wrong region to be created for a certificate, so I even tried that.
I have not found anything that explains exactly what needs to be done for this very common setup, so I am hoping that someone here has some helpful resources.
I think the main issue I had when setting up a CloudFront distribution for an S3 static webhosting bucket was in the Orign Domain Name.
When you create a new distribution, under Origin Settings, the Origin Domain Name field works as a drop-down menu and lists your buckets. Except that picking a bucket from that list doesn't work for static webhosting. You need to specifically put the endpoint for the bucket there, for example:
mywebhostingbucket.com.s3-website-sa-east-1.amazonaws.com
And for custom domains, you must set up the CNAMEs under Distribution Settings, Alternate Domain Names (CNAMEs), and then make sure you have your custom SSL certificate in the us-east-1 region.
Then you can configure the alias record set for the CloudFront distribution.
Here is a complete answer for setting up a site with https.
I had everything in this document completed:
https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html
And it worked to get the site live via http, but in order to add https, I needed to do the following:
I had requested a certificate for whatever.com, and tried several suggestions after that. But there were a couple of things missing.
To route traffic for the domain (whatever.com) to CloudFront distribution, you will need to clear the current value of the A record and fill in distribution domain name.
Several documents that I viewed said to point the whatever.com S3 bucket to the www.whatever.com S3 bucket, and use the second one to drive the site. Since CloudFront can serve multiple domain name, you may set CNAME of distribution with both, but you will need to set A record for both to distribution AND request an ACM certificate with both domain names (with and without the www). Also, I did ask this, so if you already have a certificate, you can't edit it to do this, which means you'll need to request a new one that has both whatever.com and www.whatever.com
After all of this, I still got "Access Denied" when I went to my site, so to fix this issue, I had to create a new origin in CloudFront with 'Origin Domain Name' set to the full address of the S3 bucket (without the http), and then set the Default (*) Behavior to the S3-Website-.....whatever.com bucket.
After all of this, my site was accessible via http AND https. I hope this helps anyone who experienced this challenge.

How to serve static web content from S3 backed by multiple buckets from different regions

I'm trying to serve static web content (HTML, CSS, and JS files) from S3 buckets. I know I can go to the bucket's properties tab and choose the item Use this bucket to host a website from the Static website hosting box. And I'm sure this step will still be part of the solution I'm looking for but it won't be all.
Here's what I'm trying to accomplish:
Deploying the same content to multiple regions and based on availability and/or latency, provide the service to the client.
As for the API Gateway, I know how to do this. I should create the same API Gateway (alongside underlying lambda functions) and Custom Domain Names in all the regions. And then creating the same domain on Route 53 (of type CNAME) and choose Latency as Routing Policy. One can also set up a Health Check for the Record Set so availability of the API Gateway and lambda functions are checked periodically.
Now I want to do the same for the S3 bucket and my static content. i.e. I want to deploy the same content to different regions and somehow make Route 53 to route the request to the closest available bucket. Previously, I was using CloudFront but it seems to me in this setup, I can only introduce one bucket.
Does anyone know how can I serve my static content from multiple buckets? If you are going to suggest CouldFront, please tell me how you plan to use multiple buckets.
You can generate a certificate, setup a CloudFront distribution to grab the content from your bucket and then point your domain to your distribution using Route53. You get free https and you can also add several S3 buckets as origins for your distribution.
From AWS Docs:
After you configure CloudFront to deliver your content, here's what happens when users request your objects:
1. A user accesses your website or application and requests one or more objects, such as an image file and an HTML file.
2. DNS routes the request to the CloudFront edge location that can best serve the request—typically the nearest CloudFront edge location in terms of latency—and routes the request to that edge location.
3. In the edge location, CloudFront checks its cache for the requested files. If the files are in the cache, CloudFront returns them to the user. If the files are not in the cache, it does the following:
3a. CloudFront compares the request with the specifications in your distribution and forwards the request for the files to the applicable origin server for the corresponding file type—for example, to your Amazon S3 bucket for image files and to your HTTP server for the HTML files.
3b. The origin servers send the files back to the CloudFront edge location.
3c. As soon as the first byte arrives from the origin, CloudFront begins to forward the files to the user. CloudFront also adds the files to the cache in the edge location for the next time someone requests those files.
P.D. Keep in mind this is for static content only!
This is possible with CloudFront using Lambda#Edge to change origin based on answer from Route 53.
Please refer this blog for a sample Lambda#Edge code to do this -
https://aws.amazon.com/blogs/apn/using-amazon-cloudfront-with-multi-region-amazon-s3-origins/

Calling cross domain requests from almost static site

I'm using vuejs and almost everything I do is on client-side, but for thing I need to call the server-side to check if URL exists or not.
I don't want to make these requests from browser, because that doesn't make sense to fetch different website from my scripts that will be more like calling any bad website without user knowing it in background, so I need to call cloud-function(gce) or aws lambda(since I don't want to host the site on server for it, since it has just one api call).
What would be the best way to accomplish it, I'm looking for something like website is www.webapp.com and cloud-function call on www.webapp.com/checkUrl
If you choose AWS platform, you can use S3, CloudFront, Route53, API Gateway and Lambda to accomplish your goal.
Step01
Create a S3 bucket and upload your frontend vueJs code
Enable Static Web Hosting onto your bucket from S3 properties
Create a CloudFront distribution
Create a CloudFront origin pointing to your s3 bucket url (you have to add static website url of the s3 bucket)
Set the default behaviour pointing to S3 orgin ID
Step 02
Create your lambda function
Create a API gateway
Add new resource (GET/POST) pointing to your lambda
Deploy your API
Go back to the CloudFront distribution and add a origin pointing to your API Gateway
In the behaviour tab, create a new behaviour eg: (/checkUrl) and point it to the OriginId of the API Gateway
Step 03
Goto Route53 and create a new Hosted Zone
Set the NS records of the hosted zone in your domain configuration
Create a new record set (eg: www.webapp.com) and point it to the DNS of your CloudFront distribution
Update your CloudFront distribution's Alternate Domain Name to www.webapp.com

Websites hosted on Amazon S3 loading very slowly

I have an application which is a static website builder.Users can create their websites and publish them to their custom domains.I am using Amazon S3 to host these sites and a proxy server nginx to route the requests to the S3 bucket hosting sites.
I am facing a load time issue.As S3 specifically is not associated with any region and the content being entirely HTML there shouldn't ideally be any delay.I have a few css and js files which are not too heavy.
What can be the optimization techniques for better performance? eg: Will setting headers ? or Leverage caching help? I have added an image of pingdom analysis for reference.
Also i cannot use cloudfront as when the user updates an image the edge locations have a delay of few minutes before the new image is reflected.It is not instant update,hence restricting the use for me. Any suggestions on improving it?
S3 HTTPS access from a different region is extremely slow especially TLS handshake. To solve the problem we invented Nginx S3 proxy which can be find over the web. S3 is the best as origin source but not as a transport endpoint.
By the way try to avoid your "folder" as a subdomain but specify only S3 regional(!) endpoint URL instead with the long version of endpoint URL, never use https://s3.amazonaws.com
One the good example that reduces number of DNS calls is the following below:
https://s3-eu-west-1.amazonaws.com/folder/file.jpg
Your S3 buckets are associated with a specific region that you can choose when you create them. They are not geographically distributed. Please see AWS doc about S3 regions: https://aws.amazon.com/s3/faqs/
As we can see in your screenshot, it looks like your bucket is located in Singapore (ap-southeast-1).
Are your clients located in Asia? If they are not, you should try to create buckets nearer, in order to reduce data access latency.
About cloudfront, it should be possible to use it if you invalide your objects, or just use new filenames for each modification, as tedder42 suggested.