first of all sorry for my ignorance but there is a concept which is not very clear for me in the AWS ELB word.
I have a frontend site deployed on cloudfront and an API running into an EC2 instance.
What I want to avoid is having 2 domains to serve the same data.
For example, I want to access my site using https://example.com/post and you will see the site itself (HTML from cloudfront).
But if you are trying to access to https://example.com/post passing the HTTP/HEADER Accept: application/json you would be able to see the json content from the API server itself (EC2 Instance).
Is that possible using an ELB? or do I have to make some trick into the EC2 instance like having an nginx seted up as a proxy and serve the cloudfront content if no header is present?
Thanks in advance.
I'm not sure if this can be done using the accept header. But, if you separate the static and dynamic content with different root paths then it's a pretty standard deployment.
So for example, if all dynamic content is prefixed with /api (or alternatively, all static content is prefixed with /static/) then what you'll need is:
create an origin in cloudfront pointing to ELB/EC2
create a static origin in cloudfront pointing to S3 bucket.
create a behavior in cloudfront for the /api/ path (make sure it caches nothing and passes all headers and cookies), it should point to the ELB/EC2 origin.
create a static behavior for the root path (default) pointing to the s3 origin, this behavior can have cache static content where applicable.
See this guide for more details on this approach:
https://aws.amazon.com/blogs/networking-and-content-delivery/dynamic-whole-site-delivery-with-amazon-cloudfront/
Related
I have a single page application (made with angular), which I am serving by pointing cloudfront to an S3 bucket. This is working well.
However, I want to run the backend of my website via the same domain - What I've done is added another origin to my cloudfront distribution which points to elastic beanstalk where the django app is running.
Then, I configured behaviors so that the Path Pattern /apiv1/* is handled by django. This doesn't work and I'm getting a 403 forbidden error when trying to access my endpoints.
The behavior I'm looking for is as follows:
/ should point to index.html and load static files (this currently works)
/apiv1/... should point to django. For example, to access a login endpoint I would have website.come/apiv1/api/login (as a pose to localhost/api/login on my machine).
Is this possible?
If anyone is doing something similar, here is a fix:
Add a subdomain - I added api.example.com which is a subdomain of example.com
Then, in Route 53, I configured api.example.com to point to elb via an alias and requested an ssl certificate for the subdomain! Note, YOU MUST use https when making requests hence the reason for the ssl certificate.
I simply changed the base url in my angular http requests and it works.
My current website (single page app with CORS + API) is deployed on AWS EC2 instance and is served via ALB (mostly for easier setup of HTTPS as I only have one region covered now). The web server is configured to serve the single page application but that's all it is doing regarding frontend. I want to move the single page application to S3 instead and so completely separate the backend from the frontend. The question is, what would be the most efficient way to do it with regards to AWS setup? I can come up with the following:
point the domain at the S3 instance to serve frontend files, point API calls to ALB public DNS address
keep the domain pointed at the ELB as it is, route port 80 & 443 to S3, change API port and route that port to EC2
...
Any help appreciated.
If you're trying to completely separate the infrastructure for frontend and backend but keep the same domain you could make use of CloudFront.
In CloudFront you would create 2 origins within your distribution:
The default origin would be the S3 static website.
Then an additional origin which would point to the original ALB.
You would configure the behaviours of this CloudFront distribution so that when a path matches a specific pattern i.e. api/* it would forward traffic to the ELB. If it does not match this it would default to your S3 bucket.
Take a look at the Can I use a single CloudFront web distribution to serve content from multiple origins using multiple behaviors? article which covers a similar behaviour to what I have outlined.
I have a website which I serve using express running in an EC2 instance. But this EC2 serves only the static content (html, js, css) and the dynamic part comes from API Gateway. Right now, these two have different IPs (and domains) which means that I have to deal with CORS problems accessing API Gateway from the web pages. If I could somehow serve the static content and dynamic one through the same address, that would be much better.
The way I see it, this can be done in two ways. I can serve both of them on the same host but different ports which I'm not sure if it's going to solve the same CORS problem or not. But another way which I'm sure it will not face the CORS problem is serving API Gateway under some specific sub-folder. Like http://example.com/api while the static content is served from any url except that.
Does anyone know how can I do this? Is CloudFront what I need? Or Elastic Load Balancer?
Yes, CloudFront is what you need for this scenario.
Application Load Balancer can also do path-based routing, but it doesn't support API Gateway as a target.
By default, CloudFront can route requests under a single domain to the correct choice from up to 25 destinations, using up to 25 path (matching) patterns (both of these limits can be increased by request, but it sounds like for now, you only need 2 of each, /api/* to the API, and the default * route to EC2). You can also leverage this setup to put some static content in an S3 bucket and take some load off of the servers in EC2.
For this configuration, you will want to configure your API Gateway deployment with a regional endpoint, not an edge optimized endpoint. This is because edge optimized endpoints already use part of the CloudFront infrastructure (a part to which you have no ability to configure), so using an edge-optimized endpoint behind your own CloudFront distribution sends each request and response through the CloudFront network twice, increasing latency.
My problem is not only hosting a static website on S3, it goes a bit further than that.
My plan is to have a www.foo.com on the S3.
So I create a bucket called www.foo.com and I set the domain to point there.
So every single file I have on my bucket is public, and is part of the website.
But there is one exception:
Whenever I navigate to www.foo.com/blog, I want to make an internal redirection to the blog hosted on an EC2 container.
That would be easily achievable by using Nginx with a proxy_pass definition. But S3 is not Nginx.
I know there are some redirection rules I can apply, but how would I go for doing an internal redirection where for the user the URL is http://www.foo.com/blog but the blog is stored on a different machine.
Since you mentioned you are using CloudFront, you want to use that for the redirection instead of S3. You would configure two origins in your CloudFront distribution, your S3 bucket and your EC2 server. You would configure S3 as your default origin, and create a cache behavior with the /blog pattern that points to the EC2 origin.
My mobile app consists of a dynamic portion on heroku (foo.herokuapp.com) which serves up our API and web views for some content we expose to users who don't have the app installed. There is also of course a static landing page (http://foo.co) which is hosted on S3.
Currently, I have DNS setup to resolve foo.co to our S3 instance. And S3 has routing rules to redirect our dynamic content (http://foo.co/some_dynamic_data/1234/) to our heroku servers.
Given it's a 3XX redirect, this results in a pretty ugly experience for the user since their browser bar is now going to reflect our heroku backend.
Question:
Is there an easy proxy service I can deploy that has special routing rules to route dynamic content to heroku and static content to S3 so that I can point foo.co DNS to the proxy and not have to expose the backend to users via redirects?
CloudFront.
And don't say, "but I thought that was a CDN." That's how it's marketed, but it's also a reverse proxying HTTP request router that can choose the backend based on the request path. The caching capability can be used, or it can be disabled if you don't need/want/understand it.
Create a distribution with two origins (that's what CloudFront calls your backend servers) -- one for the bucket and one for the API endpoint.
Configure your example.com hostname as an alternative hostname in the distribution settings.
Create path behaviors to choose which path patterns route to which origin. If there's an obvious choice for one of them to be the default, catching every path that's otherwise unconfigured, point the default behavior to that particular origin.
Point the DNS hostname to the CloudFront distribution.
Optional: have some SSL on your site with a free certificate from Amazon Certificate Manager, which is integrated with CloudFront.