GCP: load balancer rewrite path - google-cloud-platform

I'm setting up traffic management for a global external HTTP(S) load balancers. I have two backend Cloud Run services, serverless-lb-www-service and serverless-lb-api-service, that I want to serve from the same IP/domain.
I want to configure them like this:
example.com -> serverless-lb-www-service
example.com/api -> serverless-lb-api-service
I can use the simple routing rules to serve traffic semi-expected:
path
backend
/*
serverless-lb-www-service
/api
serverless-lb-api-service
/api/*
serverless-lb-api-service
However, I'm running into an issue where I try to access an endpoint that is not the root API end, like example.com/api/test. I'm always seeing the response I would expect from example.com/api.
I believe it has something to do with my API (running express.js) receiving the path /api when it is instead expecting to serve that route from there just /test. I think I might need to set up a rewrite to remove /api when it hits the API
Any help would be much appreciated. Thanks
update
I can confirm that the requests as logged in the API are all prefixed with /api. I can solve my issue by changing all API route handlers to expect the /api prefix in production environment. However I would still rather do this via a path rewrite so application code is the same in all environments

You can customize the host and path rules. You can follow the steps through this link. It is also using Cloud Run services and might help you with the rewrite path issues.
Note: Just scroll all the way down if the link will not redirect and show the "Customize the host and path rules" steps.

Related

Redirect to url from load balancer without CORS error

I was wondering if any of you know how to achieve that a GCP load balancer redirect to an url with "CORS enabled". What do I mean by that?, well I have the following scenario:
One load balancer that has to redirect to other load balancers depending on the path of the URL (LB A)
"Simple" load balancer that has many backends attached (LB B, LB C, etc)
So my flow is as follow:
LB A (/pathB) -- redirect -> LB B
LB A (/pathC) -- redirect -> LB C
This works as expected if requested by a simple HTTP Request (like cURL or Postman) but fails if its requested on a website. Why?, because the preflight OPTIONS request is redirected and that brings a CORS error Redirect is not allowed for a preflight request, and even if the OPTIONS request is skipped, a simple GET request will also have a redirected response without the CORS headers (which will fail).
Is this possible?, if so how can I achieve it?, I tried to add a cors policy on LB A but a LB can't have a routeAction with a urlRedirect.
Practically I just want to inject the CORS headers on the 301 Response to avoid the error.
After a long time searching for a solution I finally got to a "working" conclusion.
If you want that a google's load balancer inject some headers (specially cors headers) on a request thats redirected to another domain, then you are out of luck (also mentioned here). Even with the new LB version it seems that is not possible (at the moment, am sure this feature will release in some time). Maybe there is a way of doing it, but neither the docs nor the api seems to tell you how.
Then you just "can't" do this?. Well, no, the classic load balancer has something call an Internet NEG which is like having "external backends" you can point to, so I just create various NEGs to meet my needs and attach them in the LB as backends. So I accomplish my example as follow:
If LB B has the domain lb-b.com and LB C has lb-c.com
Create 2 Global NEGs (Internet NEGs) with the full domain name as lb-b.com and lb-c.com respectibly
Then create 2 backend services on LB A with each one associated with each NEG.
Finally select Advanced host and path rule and create one Path rule for each LB, for example for LB B:
Create a path rule of /pathB/*
Select the option Route traffic to a single backend
Use path prefix as / (if you want to "remove" the pathB prefix on the forward)
Select the backend service you previously create corresponding to lb-b.com
Sharing this information with documentation and guidance as a workaround for handling and enabling CORS.
Another thing that I can think of for this scenario is by using cloud function for redirects and CORS headers. You can use this link as a guidance for this scenario. Let me also share another link where you can see different code sample.
To use a reverse proxy in front of the load balancer that can handle the CORS header and the redirecting request we can use Apache or Nginx. For this scenario we can follow this link as a guidance.

How can I get django to work on https using elastic beanstalk and apache?

I have my .config files set up using the information available on aws and I have my load balancer listening on 443. My website is being served correctly via https when I connect using my elastic beanstalk url. Of course that url is not what my ssl certificate lists so there's an error but none the less, it is displaying all the html and static files. Https seems to be working there.
When I attempt to visit my custom domain using http everything also displays correctly so my application seems fine, but when I attempt https using my custom domain nothing is loaded from my server. I just get the "Index of /" page. This is what I receive when my ALLOWED_HOSTS is incorrect so I assume it's something super simple in my settings file that is blocking django from allowing apache to serve the content over https to my custom domain. Or else theres one other place I'm missing that needs me to register my domain with my load balancer? Is that a thing? I feel like I've been scouring the internet for help here so any suggestions are very much appreciated.
One other note is that I have all my static files being served via s3. That bucket actually does get loaded correctly when I visit my website's custom url over https... Not sure if that's a clue or just even more confusing.
Serving my static files via s3 lead me to omit the below as I wasn't quite sure what to do with it....
Alias /static/ /opt/python/current/app/static/
from the example listed here
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/https-singleinstance-python.html
Again, everything seems to be working via the https://[...]elasticbeantalk.com with an expected
ERR_CERT_COMMON_NAME_INVALID
Not sure why I'm getting "Index of /" when visiting my custom domain over https. Http works fine too.
I kind of figured it out in asking that question...
No where in any tutorial had I read anything about creating a dns entry that aliased my load balancer to my domain name... This info solved it for me-
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-elb-load-balancer.html
Check out this post about forcing HTTPS with django and elastic beanstalk. This solution only works if your elastic beanstalk environment has an application load balancer (as opposed to classic load balancer)
https://medium.com/#Pibastte/how-to-setup-http-to-https-redirection-for-a-django-application-on-aws-elastic-beanstalk-and-have-de44cf05565

GCP Load Balancer - Host and path rules not working

I have a VM that has 3 applications hosted on it. All the apps are working fine with the VM's public IP and port (e.g. 34.44.55.66:{port})
React JS website 1 (port 3001)
React JS website 2 (port 3002)
Express JS API 1 (port 3003)
I now want to have all these behind a Cloud Load Balancer. I've done the following for it.
Created three backend services (one for each application)
Created Host and Path rules as below
The load balancer is created without any issues. However, only the default path works fine. Refer to the details below (consider the LB IP as 55.66.77.88).
55.66.77.88: Website-1 opens without any issue (default path)
55.66.77.88/website-1: Website-1 shows error messages in the browser console
55.66.77.88/website-2: Website-2 shows error messages in the browser console
55.66.77.88/api-1: API-1 shows an error message in the browser console
GET http://55.66.77.88/api-1 404 (Not Found)
Whenever I map any of the above backend services with the default path, they work fine. However, they do not work as expected when the path is entered in the browser.
Any advice will be appreciated.
Keep in mind that, in your configuration, there isn't URL rewrite action. That means your request
55.66.77.88/website-1/index.html
will reach the backend on this path
# Backend bucket example
gs://my-bucket/website-1/index.html
# Instance group backend
<backend>/website-1/index.html
# Network Endpoint Group backend
<NEG>/website-1/index.html
The base path provided to the load balancer is forwarded. When you haven't additional path in the forward, it works (case of the root path 55.66.77.88/)
You can override the behavior in the advanced mode, and you can define URL rewrite for each of your rules.
You can define rewrite rule like this in the console
Click on advanced configuration
Set up your default configuration (any domain, any path)
Then click on add host and path rule
Put * in the host as you did
Then click on the pencil of the path rule section to define the rule by default. Here again, select your backend by default. no special rewrite, it's the default path.
Now click on add path rule.
Add your matching paths. And only / in the rewrite URL part (you can rewrite your host if the backend rely on the host name, but it doesn't seem your case)
Do this for all your backend and test it (let 3 - 5 minutes to propagate your update to the edge node)

DNS hosting public and web application on different hosts

Here is my setup.
Public site hosted by squarespace.com (www.example-domain.com)
Web application (AWS EC2/ELB), i would like to be available via the same domain. (my.example-domain.com)
Custom profile pages available as www.example-domain.com/username
My question is how can i setup the DNS to achieve this? If can't do it just through DNS, any suggestions? The problem i am facing is that if squarespace.com is handling the www.example-domain.com traffic how can i have it only partially handle it for certain urls. Maybe i am going about this in the wrong was all together though.
The two first are ok. As you mention, (1) is not compatible with (3) for a pure DNS config as www of example-domain.com has to be configured to a single end-point.
Some ideas of non-DNS workaround:
Having the squarespace.com domain on sqsp.example-domain.com and configure your www domain to a custom web server on which you configure the root (/) to redirect (HTTP 300) to sqsp.example-domain.com. It will be quite transparent for the user, except in his browser address.
The same but setting on / a full page HTML iframe containing sqsp.example-domain.com.
The iframe approach is a "less clean", Google the solutions to build your opinion.
EDIT:
As #mike-ryan mentioned, there is the proxy solution as well where you configure you web server to request another server to get the content to return to your user. If you are already using AWS, a smart way to do this is to use CloudFront: you can setup CloudFront to proxy one server on one URL and proxy another server on other URL. Actually, this is maybe the faster to way to implement you need. Of course, a proxy is one more "hop", so it may add more delay.
If you really want to have content served from different servers while only using a single domain name, you'll need to set up a proxy server to handle the request routing for you. I am assuming your custom profile pages must be served from your EC2 instance.
Nginx will receive all requests, and will then decide whether they should be sent to Square Space or your web app. Requests will be reverse proxied to Square Space or to your app, depending on the URL.
This is similar to #smad's answer, except it will all be invisible to the users which IMHO is better than redirecting the user to a new domain name.
Example steps:
Set up an Nginx server, create two virtual hosts - one for my.example.com, and one for www.example.com
Create two upstreams in your Nginx config - one for Square Space, and one for your app
Configure the www.example.com virtual host to reverse proxy connections to the Square Space upstream, if the URL is "/". Otherwise, traffic should be proxied to your app upstream [0]
Configure the my.example.com virtual host to proxy all traffic to your app upstream
[0] how to reverse proxy via nginx a specific url?

CDN only works assigned domain

For example:
About www.abc.com , and en.abc.com
I want to know how to configure the CDN or somethings, make the CDN only works in www.abc.com,
for en.abc.com don't works.
I am using aliyun.com as my cdn provider.
How about the NGINX or Django or Domain or CDN settings?
CDN systems always 'only' work on their configured hostnames. Basically, a CDN is a reverse proxy with a set of rules on it. For any request coming in, it has to know
where to fetch the content from
which additional logic to apply to the content when delivering it
If you want to use a different hostname on the CDN, you will have to make the CDN work, all other components in your web site delivery will not be reached if the CDN configuration doesn't proxy the request to your web server.
I am not familiar with aliyun.com specifically, but there might be a chance to have them set up a wildcard/regex hostname (like *.example.com). You will have to get suport from aliyun to understand if this is possible.