I am trying to set up a AppEngine flexible (go) backend/api server together with a static frontend.
Ideally i would like to completely decouple the api server from the frontend so was planning to serve all the static files from cloud storage. I have managed to set this up by serving the static files on a subdomain from cloud storage - however, this means that users have to visit the subdomain to retrieve the index.html file.
Does anyone know if it is possible (in e.g. app.yml - but couldnt find anything in the docs here) to get fetch index.html from cloud storage?
I.e. such that:
https://example.com would return index.html from cloud storage
https://example.com/api is routed to my appengine service?
Simply set the "www" subdomain to be your index.html, then let your App Engine handle the request routing. Look into how dispatch.yaml works and you will see how to do it.
Basically, let App Engine route all your default traffic to your index.html and then do the routine specific subdomains to whatever API handlers you have setup.
Related
I have an application in Google app engine flexible which is written in Python. It uses Flask framework for backend. Currently, the flask framework serves the static files using the following code.
#app.route('/<path:path>') #Catch All urls, enabling copy-paste url
def home(path):
return send_from_directory(CLIENT_APP_FOLDER, path)
This eats up resources for serving my website written in Angular.
I have been reading on how I could serve static files not using my app engine app. One suggestion is to use Google Cloud Storage for serving the static files but I am not able to understand how I could set my DNS so that
www.example.com serves from Google Cloud Storage and www.example.com/api serves app engine app.
Another suggestion is to use dispatch.yaml and deploy two services, one pointing to the app engine app and another serving the static files, but again I am unable to figure out what the static file serving service would look like. Also does it deploy two services on the same instance or does it create two instances? I want to optimize for cost and not spin up another instance.
There is 2 solutions for minimizing cost.
The first one is to use Cloud Run instead of appengine flex. You can deploy the same container but you pay only when you are serving request. It's in beta but it's really stable. And you can use custom domain
The second solution, if you keep your app engine flex, is to deploy a second service. This second service will serve the static resources. Use standard appengine, and customize your app.yaml for serving only static resources. Here the doc for python 2 but the configuration is language agnostic
Serving static resources don't create instances. In any case, you have 28h of standard instance free per day.
I have a static web client SPA serviced by a REST API. I'm trying to figure out the best way to host these apps on Google's Cloud Platform using App Engine to host the API, and Cloud Storage to host the static web client.
If I were doing this from scratch, a simple reverse proxy could manage routing traffic between the API and the client assets. To do the equivalent with GCP, I've looked at the following:
Google's Compute Engine supports content-based load balancing: though no equivalent for App Engine
the API on App Engine could proxy requests to Cloud Storage, though at the expense of unnecessary load on the API service
simply host the API and client on separate domains (App Engine and Cloud Storage respectively), and properly configure cross origin issues
Use Google Cloud Endpoints as a reverse proxy to route traffic appropriately between App Engine and Cloud Storage: haven't fully explored this option, though as of writing, Cloud Endpoints does not support routing to multiple hosts (which is defined only in v3 of the OpenAPI spec).
All of the above have limitations. What i'm trying to do seems fairly conventional, but I'm not sure what the path of least resistance is on GCP.
Google Cloud storage allow you to host a static website :
https://cloud.google.com/storage/docs/hosting-static-website
You don't need to use Endpoint or AppEngine as a reverse proxy
If you need to setup a load balancer based on route or if you need to setup ssl certificates you could use storage bucket as a service backend :
https://cloud.google.com/compute/docs/load-balancing/http/backend-bucket
Let's talk about serving SPA static files from Google App Engine.
The SPAs need to serve many routes to a single index.html, normally called rewrite rules.
App Engine can do that with a proper configured app.yaml handlers section.
For the real files part, you serve the real path:
- url: /assets/
static_dir: path/to/real/files
For these fake routes, serve the entrypoint index.html:
- url: /
static_file: path/to/index.html
upload: path/to/index.html
- url: /.*
static_file: path/to/index.html
upload: path/to/index.html
By this configuration, Google Frontend will serve the static files without hitting your backend.
Here's one Angular application and I deployed to App Engine, as an example:
Other stuff about securing APIs and CORS policies, you can consider using dispatch.yaml to avoid cross domain problem. Or serve from different domain with cloud endpoints (with IAP jwk configured).
As you have rightly observed, there are a number of complications that might come into play with your setup. The Google Cloud Storage is simply a Storage, which might not necessarily manage requests to GAE as well as you desire. Perhaps, using Endpoints would be a more viable solution in this case (considering your listed options), where you can use simple Javascripts to call Endpoints in your GAE applications from your Application Files in Google Cloud Storage. However, that being said, I think the better option is to move your static files into App Engine as described here. This will ease the complication of managing resources between two different technologies
Current App:
Goole App Engine on a custom domain: myapp.com
Google Cloud Storage bucket on a custom subdomain (it uses DNS): images.myapp.com
I have SSL certificate with the images subdomain
My question is: Is possible to have this configuration with SSL?
Things I have tried:
Load balancer. I cannot figure out how to redirect everything that is not /images/* to the GAE (it seems it only works with backends)
dispatch.yaml. I think it only works for the services you deploy
In App Engine Settings I have added images.myapp.com, but as the redirection of images.myapp.com is done at DNS level, the secure layer is lost
Any suggestion or idea is more than welcome.
Thank you!
The limitation comes from the Cloud Storage bucket presented as a website under a custom domain - you can't use SSL with that. From You want your content served through HTTPS:
SSL is not currently supported by the Cloud Storage webservers; thus,
you can only use a CNAME redirect with HTTP and not with HTTPS. If you
wish to serve content through HTTPS from your bucket, we recommend you
use a third-party Content Delivery Network with Cloud Storage.
Alternatively, you can serve your static website content from
Firebase Hosting instead of Google Cloud Storage.
If the content of your site meets the Code and static data storage quota you can serve your website through GAE, as static content (through a google CDN), which can be mapped to a custom domain and use SSL. See:
Serving Static Files
Hosting a static website on Google App Engine
If your content exceeds the mentioned quota then you can still serve it through your app, but dynamically, with your app accessing the content stored on GCS and serving it - more expensive as you'll be using instance hours for it.
Up until recently, I've been hosting my dev app on a single heroku instance. The API and the angular app are hosted from the same Express.js server. Along with a front-facing sales page, separate from the angular app, sitting at the base domain. It's time for production, so I need to split the two into the api server and any other service to host the static pages.
My Current Setup all on an express.js server
mydomain.com --> Sales Page, static simple page with bower deps
mydomain.com/api --> api
mydomain.com/anything else --> Angular App
mydomain.com/assets -> images and misc files
I would love to use a service like Amazon S3, Cloudfront, or Divshot to host #1, #3, and #4 on a CDN service. And keep the API (#2) on Heroku or AWS ec2.
Right now, my only thought is that I'd have to run a separate server myself and host the static files with Nginx, apache, or express.js to allow for the routing based on url because as far as I can find, the CDN services don't allow for .htaccess redirecting and such.
Thank you for the time.
To simplify, you only have 2 categories here:
Static: Sales, Angular, Assets
Dynamic: API
You should consider exposing all your static assets under mydomain.com/* hosted from whatever CDN, and have the dynamic stuff being served from your (probably AWS) instance # api.mydomain.com
It is not the exact layout that you had in mind, but that one is trivial to setup.
The only minor addition here, is that you might need to setup CORS due to the double domains.
First, Build a site www.example.com with Google App Engine https://cloud.google.com/products/
Second, Upload a static image example.jpg to Google Cloud Storage https://cloud.google.com/products/cloud-storage aka https://developers.google.com/storage/
Is it possibe to serve the example.jpg as http://www.example.com/images/example.jpg? instead of using a subdomain such as images.example.com or cdn.example.com etc
The reason I want to do this is because I want to make it easier to move my site to a VPS when necessary.
I don't believe so, no. A single domain name must route to either Google Cloud Storage or Google App Engine.
You could cheat, mind you. You could configure your app engine app to take all requests for, say "/images/X" and redirect them to images.example.com/X, or you could have your app read the data from GCS and feed it back to the user directly from app engine, but neither of those are a good solution.
If you wanted to move to a VPS later, you could perhaps configure the VPS to handle two domains, one for images and one for dynamic content.
You have setup Google Cloud Storage (GCS) https://cloud.google.com/products/cloud-storage aka https://developers.google.com/storage/
You could not serve your image example.jpg that uploaded to Google Cloud Storage (GCS) as http://www.example.com/images/example.jpg when you have assigned your www.example.com pointed other than GCS (c.storage.googleapis.com).
If you insist to serve with the domain, you may consider to parsing the images in base64code when you could redirecthttp://www.example.com/images/example.jpg via .htaccess to a dynamic file where you can put the code to print out the image on the fly like so:
header("Location: http://mybucket/resample/example.jpg");
You may also consider to put your static files like js, html, css, etc in the bucket and access those files to act like a dynamic content via Google App Engine (GAE).