Static_files vs Static_dir Cache expiration header in Python App Engine - google-app-engine

I'm using Google App Engine 1.7.2 / Python 2.7 and am trying to add client caching of static files.
When I specify static_dir in my app.yaml, the cache-control headers do not get set.
- url: /static/images
static_dir: static/images
expiration: "7d 0h"
However, when I switch the specification over to static_files, like the following, it does get set.
- url: /static/images(.*)
static_files: static/images/\1
upload: static/(.*)
expiration: "7d 0h"
Is anyone else seeing this? Am I missing something? I was under the impression that static_dir and static_files were equivalent if written like the above.
Thanks!

I realise your question was asked a while ago, but I came across it while searching for a similar issue and thought I'd answer it for others' benefit.
You've specified the static file handlers correctly.
The issue with caching may have been due to you being logged in as administrator in the browser (logged in to appengine.google.com). Running your application, without being logged in as administrator, should show caching working as expected. Here's a link to the 'issue'.

Related

React Static Website Problem Deploying on GCP (can't find main.js or main.css)

I followed this tutorial: https://cloud.google.com/storage/docs/hosting-static-website to host my React webapp. Here is what I have so far:
// app.yaml
runtime: nodejs10
handlers:
- url: /static
static_dir: build/static
- url: /(.*\.(json|ico|js))$
static_files: build/\1
upload: build/.*\.(json|ico|js)$
- url: /.*
static_files: build/index.html
upload: build/index.html
(I've tried MANY configurations here)
I run npm run build and put the build directory in GCP Cloud Storage along with app.yaml. When I go to my website I get this:
This happens when I hit the root url.
It looks like it is looking at the static directory which should then look at build/static according to my app.yaml.
If I go directly to the webpage such as https://www.drinkingbuddy.io/build/static/js/main.39aaab31.js, the browser displays the file as expected. So it is there being hosted but something is messed up with pathing? I'm not sure.
Testing locally, everything works. Even when serving the build files.
Any guidance would be greatly appreciated! Thank you.
EDIT:
Another thing is that when I go to the base url, it just shows the document tree.
EDIT 2:
When accessing the files directly from the bucket such as https://www.storage.googleapis.com/drinkingbuddy-static/build/index.html, I then get this error:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>UserProjectAccountProblem</Code>
<Message>User project billing account not in good standing.</Message>
<Details>The billing account for the owning project is disabled in state absent</Details>
</Error>
But looking through my account I don't see any billing issues.
EDIT 3:
Now I am able to get to .../build/index.html and it displays my site. but the root / is still throwing errors saying it can't find main.js. I added homepage: "." to my package.json.
I was able to get it to work by doing homepage:"/build". Now I can access the root url and get expected behavior.

Deploying an App with Code Splitting on GCP App Engine - Loading chunk * failed

We have a web application (frontend) using React created from Create React App. The app is running on Google Cloud Platform App Engine Standard. Our web application is code splitted. Each page is then loaded on user navigation.
It's working really well. The issue we have is for example user A is on the app home page. We deploy a fix that change the chunk file name. The user A then try to access another page and then got the error Loading chunk * failed. The url to get the file is now returning a 404 because the file has been replaced by some new chunk files.
It's a frequent problem as I can see during my research but I didn't find a solution that apply for Google App Engine.
Here's an article that explain the problem / solution: https://mitchgavan.com/code-splitting-react-safely/
I would like to use the solution "Solution 1: Keep old files on your server after a deployment" but I can't see how to do this using GCP ...
Here's the app.yaml file
service: frontend
runtime: nodejs14
env: standard
instance_class: F1
handlers:
- url: /(.*\..+)$
static_files: build/\1
upload: build/(.*\..+)$
- url: /.*
static_files: build/index.html
upload: build/index.html
We have the following dispatch file (* for masked url)
dispatch:
- url: "*"
service: frontend
- url: "www.*"
service: frontend
Haven't tried this before but see if it makes sense/works.
We have a blog article about downloading your source code from GAE. It contains an explanation of where your source is stored when you deploy (a staging bucket), how long it stays there and how you can modify how long it stays before Google automatically deletes it.
When you deploy to GAE, gcloud only deploys files that have changed (it doesn't deploy those that haven't). Since you now have 'new' files because new hashes were generated, the older files no longer exist on your local machine. I do not know if Google will automatically delete those files from the staging location in bullet 1 above.
My proposal here is that you follow the steps in the blog article (from bullet 1) and alter (change) how long the files are retained in your staging bucket. Another option is to check the retention policy tab and see if you can change the rule so the files don't get deleted. If you're able to alter how long the files remain or the retention policy, it just might solve your problem. Let me know if this works

App Engine not caching static content despite expiration set in app.yaml

I am using Google App Engine Standard Environment for a node.js app.
I have a folder named public for my static files. This contains files such as chunk-XIAWB55V.js. I want these files to be heavily cached as the hashed filename will change if the contents change.
I added a static file handler to my app.yaml to redirect requests starting /static to my public folder, and I confirmed it worked by checking the logs: requests to e.g. https://<redacted>.com/static/javascript/build/prod/chunk-Z4M5HAC7.js are in the request log and are not hitting my app. The docs imply that a default cache of 10 minutes should be applied. However the browser devtools show that the actual headers are cache-control: no-cache, must-revalidate and a request (which gets a 304) is sent every time.
I have tried adding a expiration param to my app.yaml but it did not make a difference. I also tried setting the headers in app.yaml but it did not make a difference. My current file looks like:
handlers:
- url: /static
static_dir: public
secure: always
expiration: "1d"
http_headers:
Cache-Control: public
Vary: Accept-Encoding
- url: /.*
secure: always
script: auto
I am still getting responses like:
I am using Identity Aware Proxy in front of App Engine and I know from e.g. this question that IAP and caching can mix badly but that seems to refer simply to possible IAP bypass. My static files are not sensitive and I am happy to accept that risk.
GCP support have suggested this is an edge case due to the use of IAP. A workaround I have implemented which I can recommend for anyone else in this situation is to remove the static route and serve the files from your app instead. While this increases load on the app, the high max age means they will not be requested often.
There's some documentation of this at : This page describes best practices for using Identity-Aware Proxy (IAP) https://cloud.google.com/iap/docs/concepts-best-practices -- TL;DR, App Engine does some caching for static_files that interacts poorly with IAP. That page has some instructions you can apply if you want to protect your static_files.

Redirect base `/` path to folder in Google App Engine

I have an Angular site hosted in Google App Engine using the Python27 runtime in a standard env.
When someone visits my site www.site.com I want them automatically redirected to www.site.com/app. For reasons, I cannot do within the index.html file.
(For an explanation why and reason for doing so, see this question Renaming the index.html on Google App Engine)
In my app, I have tried things like
- url: /
mime_type: text/html
static_files: dist/app/index.html
upload: dist/app/index.html
expiration: 0s
For reasons that seem obvious to me now, this won't work as it does not rewrite the URL for the user. It doesn't seem there is a solution to rewrite rules similar to and .htaccess file. I understand this is arguably a better solution but not what I need to do right now.
Is there a setting in the Google App Engine that I am missing?
Is there an attribute in the app.yaml file that I am overlooking?
Thank you for your help

Can I configure all URLs to be secure on Google App Engine (python app) with just one setting?

Is it possible in the app.yaml to make sure that all requests to my app on http get redirected to https without having to specify secure: always for every url endpoint in my app.
Currently I am doing this:
url: /users/login
script: users_handler.app
secure: always
url: /signin
script: authentication.app
secure: always
url: /users/logout
script: users_handler.app
secure: always
But as new urls are added, its risky as a developer might forget to specify secure always. I would prefer to just specify a global setting that applies to all urls in my app.
If you don not want to use secure in your app.yaml you can accomplish this with webapp2.
https://webapp2.readthedocs.io/en/latest/guide/routing.html#restricting-uri-schemes
And here is a working code eaxmple: How to use WSGI to reroute a user from http to https
I feel like archaeologist, but nonetheless I'll share my findings.
All it has to be made is to add this into app.yaml:
handlers:
- url: /.*
secure: always
script: auto
There is even documentation example with that case. It's exactly the same as mine, but I removed redirection.
I don't believe that is possible. However, I think you can mitigate the problem by restructuring the URLs you have defined in your app.yaml.
The URLs is matched against handlers in your app.yaml starting from the top. So you should specify your one-off URLs and then at the bottom have a catch all setting that routes all URLs that didn't match the other settings to your default handler. You application should then display 404 pages etc. for URLs that don't exist in your application.
Something like this would work:
- url: /signin
script: authentication.app
secure: always
- url: /.*
script: users_handler.app
secure: always
This way you only have to specify a couple handlers for your application and you are much less likely to miss setting secure:always when adding a new URL or setting.
Hope that helps!

Resources