Serving static files efficiently in google app engine flexible python - google-app-engine

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.

Related

Node.js hosting on GCP using App Engine (API) and Cloud Storage Bucket (Frontend)

With GCP giving you endless options of how to "best" host a Node.JS web application (frontend/backend) I'm struggling to decide which way to go. I'm looking for an easy way to deploy my app (using Git Actions) and scale it. We are also looking at an open source app here, so I'm trying to be as cheap as possible...
From what I can see best practice would be to serve all my static assets (frontend) from a cloud storage bucket (cdn) and my backend from an app engine. What I'm not so sure about is where to point my custom domain at. I would expect the index.html to be served from my bucket, but if I point my domain at the app engine the requests would still go through my app which is what I want to avoid if I want to reduce load against my app engine (to not have to run too many instances). Pointing my domain at my bucket feels wrong as well. Is everyone just hosting index.html from their app engine anyway and just serve other assets from a bucket?
I might be thinking in circles here. Any help very much appreciated!
You have to use two domains:
app.yourdomain.com pointing to the bucket with your front files
api.youtdomain.com pointing to app engine with your backend node.js files

Why can't I deploy a React app to Google Cloud Storage?

In the past when I've created a client-side web app using a framework like React, I can create a browser build and push it to a static hosting platform like AWS S3.
For Google Cloud Platform, it seems like the go-to approach is to deploy it to App Engine. If I'm understanding correctly, GAE is a combination of storage and compute resources.
Why can't I simply host the JavaScript app as prepared by webpack?
Google Cloud Storage (GCS) would be the way to go to host your static website on Google Cloud Platform (GCP). Notice that in order to use GCS you'll need to have a domain as well as a GCP project. The documentation is very straightforward on how to achieve this. Here you can find some examples and other useful information.
You could also host your static website on Google App Engine (GAE). But in this case you'll need to cleverly build your app.yaml file in order to manage your URL handlers, as well as structuring your project in a particular way. Simply uploading the JS app as prepared by webpack won't work. You can find all the useful information here in order to use GAE to host your static website.

Is it possible to use Google Cloud CDN with App Engine Standard environment?

I see no way to connect my app engine backends with Cloud CDN. Seems like it's only available when using Compute Engine directly.
No, that is not currently possible. Currently, Google Cloud CDN can be used only to serve content that originates from Cloud Storage buckets, Compute Engine instance groups, and Compute Engine network endpoint groups. I agree that it would make sense to support App Engine Standard, too!
Update
Currently in beta is Serverless NEGs (Network Endpoint Groups) which will allow you to use App Engine behind a HTTP(S) Load balancer and give you all the features provided with that including CDN
Original
Yes, App Engine will serve content via Google Cloud CDN as long as a cacheable response is returned.
Try setting the Cache-Control header to something like max-age=86400, public and ensuring a Set-Cookie header is not sent with the response

Serve static SPA from Google Cloud Storage and API from Google App Engine

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

Is it possible to serve static files on Google Cloud Storage with Google App Engine with one domain?

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).

Resources